//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ #ifndef vtk_m_random_Philox_h #define vtk_m_random_Philox_h #include namespace vtkm { namespace random { namespace detail { VTKM_EXEC_CONT vtkm::Vec mulhilo(vtkm::UInt32 a, vtkm::UInt32 b) { vtkm::UInt64 r = static_cast(a) * b; auto lo = static_cast(r); vtkm::UInt32 hi = static_cast(r >> 32); return { lo, hi }; } template struct philox_parameters; template struct philox_parameters { static constexpr Vec multipliers = { M0 }; static constexpr Vec round_consts = { C0 }; }; template struct philox_parameters { static constexpr vtkm::Vec multipliers = { M0, M1 }; static constexpr vtkm::Vec round_consts = { C0, C1 }; }; template class philox_functor; template class philox_functor { public: using counters_type = vtkm::Vec; using keys_type = vtkm::Vec; VTKM_EXEC_CONT counters_type operator()(counters_type counters, keys_type keys) const { for (std::size_t i = 0; i < R; ++i) { counters = round(counters, keys); keys = bump_keys(keys); } return counters; } private: static VTKM_EXEC_CONT counters_type round(counters_type counters, keys_type round_keys) { auto constexpr multipliers = philox_parameters::multipliers; vtkm::Vec r = mulhilo(multipliers[0], counters[0]); return { r[1] ^ round_keys[0] ^ counters[1], r[0] }; } static VTKM_EXEC_CONT keys_type bump_keys(keys_type keys) { auto constexpr round_consts = philox_parameters::round_consts; return { keys[0] + round_consts[0] }; } }; template class philox_functor { using counters_type = vtkm::Vec; using keys_type = vtkm::Vec; static VTKM_EXEC_CONT counters_type round(counters_type counters, keys_type round_keys) { auto constexpr multipliers = philox_parameters::multipliers; vtkm::Vec r0 = mulhilo(multipliers[0], counters[0]); vtkm::Vec r1 = mulhilo(multipliers[1], counters[2]); return { r1[1] ^ round_keys[0] ^ counters[1], r1[0], r0[1] ^ round_keys[1] ^ counters[3], r0[0] }; } static VTKM_EXEC_CONT keys_type bump_key(keys_type keys) { auto constexpr round_consts = philox_parameters::round_consts; keys[0] += round_consts[0]; keys[1] += round_consts[1]; return keys; } public: VTKM_EXEC_CONT counters_type operator()(counters_type counters, keys_type keys) const { for (std::size_t i = 0; i < R; ++i) { counters = round(counters, keys); keys = bump_key(keys); } return counters; } }; } // namespace detail using PhiloxFunctor2x32x7 = detail::philox_functor; using PhiloxFunctor2x32x10 = detail::philox_functor; } // namespace random } // namespace vtkm #endif //vtk_m_random_Philox_h