/* * Copyright 2008-2012 NVIDIA Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include namespace thrust { namespace random { namespace detail { namespace math = thrust::detail::mpl::math; namespace detail { // two cases for this function avoids compile-time warnings of overflow template struct lshift_w { static const UIntType value = 0; }; template struct lshift_w { static const UIntType value = lhs << rhs; }; } // end detail template struct lshift_w { static const bool shift_will_overflow = rhs >= w; static const UIntType value = detail::lshift_w::value; }; template struct lshift : lshift_w::digits, lhs, rhs> {}; template struct two_to_the_power : lshift {}; template class xor_combine_engine_max_aux_constants { public: static const result_type two_to_the_d = two_to_the_power::value; static const result_type c = lshift::value; static const result_type t = math::max< result_type, c, b >::value; static const result_type u = math::min< result_type, c, b >::value; static const result_type p = math::log2::value; static const result_type two_to_the_p = two_to_the_power::value; static const result_type k = math::div::value; }; template struct xor_combine_engine_max_aux; template struct xor_combine_engine_max_aux_case4 { typedef xor_combine_engine_max_aux_constants constants; static const result_type k_plus_1_times_two_to_the_p = lshift< result_type, math::plus::value, constants::p >::value; static const result_type M = xor_combine_engine_max_aux< result_type, math::div< result_type, math::mod< result_type, constants::u, constants::two_to_the_p >::value, constants::two_to_the_p >::value, math::mod< result_type, constants::t, constants::two_to_the_p >::value, d >::value; static const result_type value = math::plus::value; }; template struct xor_combine_engine_max_aux_case3 { typedef xor_combine_engine_max_aux_constants constants; static const result_type k_plus_1_times_two_to_the_p = lshift< result_type, math::plus::value, constants::p >::value; static const result_type M = xor_combine_engine_max_aux< result_type, math::div< result_type, math::mod< result_type, constants::t, constants::two_to_the_p >::value, constants::two_to_the_p >::value, math::mod< result_type, constants::u, constants::two_to_the_p >::value, d >::value; static const result_type value = math::plus::value; }; template struct xor_combine_engine_max_aux_case2 { typedef xor_combine_engine_max_aux_constants constants; static const result_type k_plus_1_times_two_to_the_p = lshift< result_type, math::plus::value, constants::p >::value; static const result_type value = math::minus< result_type, k_plus_1_times_two_to_the_p, 1 >::value; }; template struct xor_combine_engine_max_aux_case1 { static const result_type c = lshift::value; static const result_type value = math::plus::value; }; template struct xor_combine_engine_max_aux_2 { typedef xor_combine_engine_max_aux_constants constants; static const result_type value = thrust::detail::eval_if< // if k is odd... math::is_odd::value, thrust::detail::identity_< thrust::detail::integral_constant< result_type, xor_combine_engine_max_aux_case2::value > >, thrust::detail::eval_if< // otherwise if a * 2^3 >= b, then case 3 a * constants::two_to_the_d >= b, thrust::detail::identity_< thrust::detail::integral_constant< result_type, xor_combine_engine_max_aux_case3::value > >, // otherwise, case 4 thrust::detail::identity_< thrust::detail::integral_constant< result_type, xor_combine_engine_max_aux_case4::value > > > >::type::value; }; template::value)> struct xor_combine_engine_max_aux_1 : xor_combine_engine_max_aux_case1 {}; template struct xor_combine_engine_max_aux_1 : xor_combine_engine_max_aux_2 {}; template struct xor_combine_engine_max_aux : xor_combine_engine_max_aux_1 {}; template struct xor_combine_engine_max { static const size_t w = std::numeric_limits::digits; static const result_type m1 = math::min< result_type, result_type(Engine1::max - Engine1::min), two_to_the_power::value - 1 >::value; static const result_type m2 = math::min< result_type, result_type(Engine2::max - Engine2::min), two_to_the_power::value - 1 >::value; static const result_type s = s1 - s2; static const result_type M = xor_combine_engine_max_aux< result_type, m1, m2, s >::value; // the value is M(m1,m2,s) lshift_w s2 static const result_type value = lshift_w< result_type, w, M, s2 >::value; }; // end xor_combine_engine_max } // end detail } // end random } // end thrust