Skip to content

Commit

Permalink
Merge pull request QMCPACK#4825 from ye-luo/value-alias
Browse files Browse the repository at this point in the history
Add ValueAlias for ValueType reconstruction
  • Loading branch information
prckent authored Nov 11, 2023
2 parents 1c37a5b + 6e86357 commit 470e00c
Show file tree
Hide file tree
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
Expand Up @@ -12,6 +12,9 @@
#ifndef QMCPLUSPLUS_COMPLEX_HELP_HPP
#define QMCPLUSPLUS_COMPLEX_HELP_HPP

#include <type_traits>
#include <complex>

namespace qmcplusplus
{
template<typename T>
Expand All @@ -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; }
Expand All @@ -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
Expand Up @@ -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)

Expand Down
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.