Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ValueAlias for ValueType reconstruction #4825

Merged
merged 4 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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