Skip to content

Commit

Permalink
Merge pull request #4825 from ye-luo/value-alias
Browse files Browse the repository at this point in the history
Add ValueAlias for ValueType reconstruction
prckent authored Nov 11, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 1c37a5b + 6e86357 commit 470e00c
Showing 3 changed files with 88 additions and 9 deletions.
49 changes: 41 additions & 8 deletions src/type_traits/complex_help.hpp
Original file line number Diff line number Diff line change
@@ -12,6 +12,9 @@
#ifndef QMCPLUSPLUS_COMPLEX_HELP_HPP
#define QMCPLUSPLUS_COMPLEX_HELP_HPP

#include <type_traits>
#include <complex>

namespace qmcplusplus
{
template<typename T>
@@ -26,24 +29,54 @@ using IsComplex = std::enable_if_t<IsComplex_t<T>::value, bool>;
template<typename T>
using IsReal = std::enable_if_t<std::is_floating_point<T>::value, bool>;

template <typename T, typename = bool>
struct RealAlias_impl {};
template<typename T, typename = bool>
struct RealAlias_impl
{};

template <typename T>
struct RealAlias_impl<T, IsReal<T>> { using value_type = T; };
template<typename T>
struct RealAlias_impl<T, IsReal<T>>
{
using value_type = T;
};

template <typename T>
struct RealAlias_impl<T, IsComplex<T>> { using value_type = typename T::value_type; };
template<typename T>
struct RealAlias_impl<T, IsComplex<T>>
{
using value_type = typename T::value_type;
};

/** If you have a function templated on a value that can be real or complex
* and you need to get the base Real type if its complex or just the real.
*
* If you try to do this on anything but a fp or a std::complex<fp> you will
* get a compilation error.
*/
template <typename T>
template<typename T>
using RealAlias = typename RealAlias_impl<T>::value_type;

template<typename TREAL, typename TREF, typename = bool>
struct ValueAlias_impl
{};

template<typename TREAL, typename TREF>
struct ValueAlias_impl<TREAL, TREF, IsReal<TREF>>
{
using value_type = TREAL;
};

template<typename TREAL, typename TREF>
struct ValueAlias_impl<TREAL, TREF, IsComplex<TREF>>
{
using value_type = std::complex<TREAL>;
};

/** If you need to make a value type of a given precision based on a reference value type
* set the desired POD float point type as TREAL and set the reference type as TREF.
* If TREF is real/complex, the generated Value type is real/complex.
*/
template<typename TREAL, typename TREF, typename = std::enable_if_t<std::is_floating_point<TREAL>::value>>
using ValueAlias = typename ValueAlias_impl<TREAL, TREF>::value_type;

///real part of a scalar. Cannot be replaced by std::real due to AFQMC specific needs.
inline float real(const float& c) { return c; }
inline double real(const double& c) { return c; }
@@ -59,7 +92,7 @@ inline float conj(const float& c) { return c; }
inline double conj(const double& c) { return c; }
inline std::complex<float> conj(const std::complex<float>& c) { return std::conj(c); }
inline std::complex<double> conj(const std::complex<double>& c) { return std::conj(c); }

} // namespace qmcplusplus

#endif
2 changes: 1 addition & 1 deletion src/type_traits/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ set(SRC_DIR type_traits)
set(UTEST_EXE test_${SRC_DIR})
set(UTEST_NAME deterministic-unit_test_${SRC_DIR})

set(TEST_SRCS test_qmctypes.cpp test_template_types.cpp)
set(TEST_SRCS test_qmctypes.cpp test_template_types.cpp test_complex_helper.cpp)
add_executable(${UTEST_EXE} ${TEST_SRCS})
target_link_libraries(${UTEST_EXE} catch_main containers)

46 changes: 46 additions & 0 deletions src/type_traits/tests/test_complex_helper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//////////////////////////////////////////////////////////////////////////////////////
// This file is distributed under the University of Illinois/NCSA Open Source License.
// See LICENSE file in top directory for details.
//
// Copyright (c) 2023 QMCPACK developers
//
// File developed by: Ye Luo, [email protected], Argonne National Laboratory
//
// File created by: Ye Luo, [email protected], Argonne National Laboratory
//////////////////////////////////////////////////////////////////////////////////////

#include "catch.hpp"
#include "type_traits/complex_help.hpp"

namespace qmcplusplus
{
template<typename P>
class TestComplexHelper
{
using Cmplx = std::complex<P>;
using Real = RealAlias<Cmplx>;
using CmplxRebuild = ValueAlias<P, Cmplx>;
using RealRebuild = ValueAlias<P, Real>;

public:
void run()
{
Cmplx aa;
CmplxRebuild bb;
aa = bb;

Real cc;
RealRebuild dd(0);
cc = dd;
}
};

TEST_CASE("complex_helper", "[type_traits]")
{
TestComplexHelper<float> float_test;
float_test.run();
TestComplexHelper<double> double_test;
double_test.run();
}

} // namespace qmcplusplus

0 comments on commit 470e00c

Please sign in to comment.