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

Louis Dionne via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jun 24 09:13:55 PDT 2021


ldionne requested changes to this revision.
ldionne added a comment.
This revision now requires changes to proceed.

Sorry for sitting on this for so long. Let's push this through now.



================
Comment at: libcxx/include/complex:585
 
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 float
+__copysign_constexpr(float __lcpp_x, float __lcpp_y) {
----------------
We already jump through some hoops in `<math.h>` to provide `copysign`. Would it make sense to try and unify those in some way? Maybe create a `__copysign` function that is `constexpr` whenever it can be, and then call that from `copysign`. Here, we'd call `__copysign` directly, which has the right constexpr-ness. WDYT? I'm trying to avoid proliferating helper functions that might be useful elsewhere in just this header, since it means we'll reinvent the wheel in the future eventually.

Also, I don't understand why we're guarding the use of the builtin on `_LIBCPP_STD_VER` and not `__has_builtin`.

Same comment applies to other general functions below like `fabs` & friends. I think it may be a good idea to tackle those as a separate patch, then this patch would be a lot simpler.


================
Comment at: libcxx/include/complex:622
+#if _LIBCPP_STD_VER > 17
+    if (__libcpp_is_constant_evaluated()) {
+        bool __z_zero = __a == _Tp(0) && __b == _Tp(0);
----------------
I think we can remove the `#if _LIBCPP_STD_VER > 17` check here. In C++ <= 17, `__libcpp_is_constant_evaluated()` will just return `false`, so this `if` will never be entered (but it still needs to parse).

Also, I believe a comment saying something like "catch all corner cases that would otherwise cause invalid operations if evaluated in a constant expression" wouldn't hurt. This applies here and everywhere else where the same pattern appears.


================
Comment at: libcxx/test/std/numerics/complex.number/cases.h:183
         return zero;
-    if (std::isinf(x.real()) || std::isinf(x.imag()))
+    if (__builtin_isinf(x.real()) || __builtin_isinf(x.imag()))
         return inf;
----------------
We can't use builtins like that in the tests unless we know all supported compilers do support that builtin. Is it the case?


================
Comment at: libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.clang.pass.cpp:11
+
+// ADDITIONAL_COMPILE_FLAGS: -fconstexpr-steps=3500000
+
----------------
I'm quite worried by the need to add this. It means that if we somehow went crazy in the implementation and used a huge number of steps to implement the functionality, we wouldn't catch it with the tests. I'd like to suggest something like this to remove the need to pass `-fconstexpr-steps`:

```
// Helper to avoid blowing the number of steps in constexpr
template <typename F>
TEST_CONSTEXPR void chunk(std::size_t N, F f) {
  for (std::size_t i = (N/5) * 0; i != (N/5) * 1; ++i) f(i);
  for (std::size_t i = (N/5) * 1; i != (N/5) * 2; ++i) f(i);
  for (std::size_t i = (N/5) * 2; i != (N/5) * 3; ++i) f(i);
  for (std::size_t i = (N/5) * 3; i != (N/5) * 4; ++i) f(i);
  for (std::size_t i = (N/5) * 4; i != N;         ++i) f(i);
}
```

This is just an idea, and it's untested code, but basically I think we could add a generic helper to help us chunk large ranges into several for loops instead of one giant loop. Then we'd use it something like

```
TEST_CONSTEXPR_CXX20
bool test_edges() {
  const unsigned N = sizeof(testcases) / sizeof(testcases[0]);
  int classification[N];
  for (unsigned i=0; i < N; ++i)
    classification[i] = classify(testcases[i]);

  chunk(N, [](int i) {
    for (int j = 0; j != N; ++j) {
      std::complex<double> r = testcases[i] / testcases[j];
      switch (classification[i]) {
        ...
      };
    }
  });
}
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D79555



More information about the libcxx-commits mailing list