Files
mfem/general/tassign.hpp
T
Veselin Dobrev c9d9d0f8ff Various tweaks in the template + SIMD code. Make sure the SIMD
interinsics can be used when CUDA is enabled.

A few tweaks related to adios2 when building with GNU make.
2020-05-15 12:33:07 -07:00

153 lines
3.4 KiB
C++

// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#ifndef MFEM_TEMPLATE_ASSIGN
#define MFEM_TEMPLATE_ASSIGN
#include "../config/tconfig.hpp"
#include "../general/cuda.hpp"
#include "../general/hip.hpp"
namespace mfem
{
// Assignment operations
struct AssignOp
{
enum Type
{
Set, // a = b
Add, // a += b
Mult, // a *= b
Div, // a /= b
rDiv // a = b/a
};
};
namespace internal
{
template <AssignOp::Type Op>
struct AssignOp_Impl;
template <>
struct AssignOp_Impl<AssignOp::Set>
{
template <typename lvalue_t, typename rvalue_t>
static inline lvalue_t &Assign(lvalue_t &a, const rvalue_t &b)
{
return (a = b);
}
template <typename lvalue_t, typename rvalue_t>
MFEM_HOST_DEVICE
static inline lvalue_t &AssignHD(lvalue_t &a, const rvalue_t &b)
{
return (a = b);
}
};
template <>
struct AssignOp_Impl<AssignOp::Add>
{
template <typename lvalue_t, typename rvalue_t>
static inline lvalue_t &Assign(lvalue_t &a, const rvalue_t &b)
{
MFEM_FLOPS_ADD(1);
return (a += b);
}
template <typename lvalue_t, typename rvalue_t>
MFEM_HOST_DEVICE
static inline lvalue_t &AssignHD(lvalue_t &a, const rvalue_t &b)
{
MFEM_FLOPS_ADD(1);
return (a += b);
}
};
template <>
struct AssignOp_Impl<AssignOp::Mult>
{
template <typename lvalue_t, typename rvalue_t>
static inline lvalue_t &Assign(lvalue_t &a, const rvalue_t &b)
{
MFEM_FLOPS_ADD(1);
return (a *= b);
}
template <typename lvalue_t, typename rvalue_t>
MFEM_HOST_DEVICE
static inline lvalue_t &AssignHD(lvalue_t &a, const rvalue_t &b)
{
MFEM_FLOPS_ADD(1);
return (a *= b);
}
};
template <>
struct AssignOp_Impl<AssignOp::Div>
{
template <typename lvalue_t, typename rvalue_t>
static inline lvalue_t &Assign(lvalue_t &a, const rvalue_t &b)
{
MFEM_FLOPS_ADD(1);
return (a /= b);
}
template <typename lvalue_t, typename rvalue_t>
MFEM_HOST_DEVICE
static inline lvalue_t &AssignHD(lvalue_t &a, const rvalue_t &b)
{
MFEM_FLOPS_ADD(1);
return (a /= b);
}
};
template <>
struct AssignOp_Impl<AssignOp::rDiv>
{
template <typename lvalue_t, typename rvalue_t>
static inline lvalue_t &Assign(lvalue_t &a, const rvalue_t &b)
{
MFEM_FLOPS_ADD(1);
return (a = b/a);
}
template <typename lvalue_t, typename rvalue_t>
MFEM_HOST_DEVICE
static inline lvalue_t &AssignHD(lvalue_t &a, const rvalue_t &b)
{
MFEM_FLOPS_ADD(1);
return (a = b/a);
}
};
} // namespace mfem::internal
template <AssignOp::Type Op, typename lvalue_t, typename rvalue_t>
inline lvalue_t &Assign(lvalue_t &a, const rvalue_t &b)
{
return internal::AssignOp_Impl<Op>::Assign(a, b);
}
template <AssignOp::Type Op, typename lvalue_t, typename rvalue_t>
MFEM_HOST_DEVICE
inline lvalue_t &AssignHD(lvalue_t &a, const rvalue_t &b)
{
return internal::AssignOp_Impl<Op>::AssignHD(a, b);
}
} // namespace mfem
#endif // MFEM_TEMPLATE_ASSIGN