You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
7.7 KiB
325 lines
7.7 KiB
11 years ago
|
/*
|
||
|
* 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 <thrust/detail/type_traits.h>
|
||
|
#include <thrust/detail/mpl/math.h>
|
||
|
#include <limits>
|
||
|
#include <cstddef>
|
||
|
|
||
|
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<typename UIntType, UIntType w,
|
||
|
UIntType lhs, UIntType rhs,
|
||
|
bool shift_will_overflow>
|
||
|
struct lshift_w
|
||
|
{
|
||
|
static const UIntType value = 0;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename UIntType, UIntType w,
|
||
|
UIntType lhs, UIntType rhs>
|
||
|
struct lshift_w<UIntType,w,lhs,rhs,false>
|
||
|
{
|
||
|
static const UIntType value = lhs << rhs;
|
||
|
};
|
||
|
|
||
|
} // end detail
|
||
|
|
||
|
|
||
|
template<typename UIntType, UIntType w,
|
||
|
UIntType lhs, UIntType rhs>
|
||
|
struct lshift_w
|
||
|
{
|
||
|
static const bool shift_will_overflow = rhs >= w;
|
||
|
|
||
|
static const UIntType value = detail::lshift_w<UIntType, w, lhs, rhs, shift_will_overflow>::value;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename UIntType, UIntType lhs, UIntType rhs>
|
||
|
struct lshift
|
||
|
: lshift_w<UIntType, std::numeric_limits<UIntType>::digits, lhs, rhs>
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename UIntType, int p>
|
||
|
struct two_to_the_power
|
||
|
: lshift<UIntType, 1, p>
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename result_type, result_type a, result_type b, int d>
|
||
|
class xor_combine_engine_max_aux_constants
|
||
|
{
|
||
|
public:
|
||
|
static const result_type two_to_the_d = two_to_the_power<result_type, d>::value;
|
||
|
static const result_type c = lshift<result_type, a, d>::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<u>::value;
|
||
|
static const result_type two_to_the_p = two_to_the_power<result_type, p>::value;
|
||
|
|
||
|
static const result_type k = math::div<result_type, t, two_to_the_p>::value;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename result_type, result_type, result_type, int> struct xor_combine_engine_max_aux;
|
||
|
|
||
|
|
||
|
template<typename result_type, result_type a, result_type b, int d>
|
||
|
struct xor_combine_engine_max_aux_case4
|
||
|
{
|
||
|
typedef xor_combine_engine_max_aux_constants<result_type,a,b,d> constants;
|
||
|
|
||
|
static const result_type k_plus_1_times_two_to_the_p =
|
||
|
lshift<
|
||
|
result_type,
|
||
|
math::plus<result_type,constants::k,1>::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<result_type, k_plus_1_times_two_to_the_p, M>::value;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename result_type, result_type a, result_type b, int d>
|
||
|
struct xor_combine_engine_max_aux_case3
|
||
|
{
|
||
|
typedef xor_combine_engine_max_aux_constants<result_type,a,b,d> constants;
|
||
|
|
||
|
static const result_type k_plus_1_times_two_to_the_p =
|
||
|
lshift<
|
||
|
result_type,
|
||
|
math::plus<result_type,constants::k,1>::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<result_type, k_plus_1_times_two_to_the_p, M>::value;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
template<typename result_type, result_type a, result_type b, int d>
|
||
|
struct xor_combine_engine_max_aux_case2
|
||
|
{
|
||
|
typedef xor_combine_engine_max_aux_constants<result_type,a,b,d> constants;
|
||
|
|
||
|
static const result_type k_plus_1_times_two_to_the_p =
|
||
|
lshift<
|
||
|
result_type,
|
||
|
math::plus<result_type,constants::k,1>::value,
|
||
|
constants::p
|
||
|
>::value;
|
||
|
|
||
|
static const result_type value =
|
||
|
math::minus<
|
||
|
result_type,
|
||
|
k_plus_1_times_two_to_the_p,
|
||
|
1
|
||
|
>::value;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename result_type, result_type a, result_type b, int d>
|
||
|
struct xor_combine_engine_max_aux_case1
|
||
|
{
|
||
|
static const result_type c = lshift<result_type, a, d>::value;
|
||
|
|
||
|
static const result_type value = math::plus<result_type,c,b>::value;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename result_type, result_type a, result_type b, int d>
|
||
|
struct xor_combine_engine_max_aux_2
|
||
|
{
|
||
|
typedef xor_combine_engine_max_aux_constants<result_type,a,b,d> constants;
|
||
|
|
||
|
static const result_type value =
|
||
|
thrust::detail::eval_if<
|
||
|
// if k is odd...
|
||
|
math::is_odd<result_type, constants::k>::value,
|
||
|
thrust::detail::identity_<
|
||
|
thrust::detail::integral_constant<
|
||
|
result_type,
|
||
|
xor_combine_engine_max_aux_case2<result_type,a,b,d>::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<result_type,a,b,d>::value
|
||
|
>
|
||
|
>,
|
||
|
// otherwise, case 4
|
||
|
thrust::detail::identity_<
|
||
|
thrust::detail::integral_constant<
|
||
|
result_type,
|
||
|
xor_combine_engine_max_aux_case4<result_type,a,b,d>::value
|
||
|
>
|
||
|
>
|
||
|
>
|
||
|
>::type::value;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename result_type,
|
||
|
result_type a,
|
||
|
result_type b,
|
||
|
int d,
|
||
|
bool use_case1 = (a == 0) || (b < two_to_the_power<result_type,d>::value)>
|
||
|
struct xor_combine_engine_max_aux_1
|
||
|
: xor_combine_engine_max_aux_case1<result_type,a,b,d>
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename result_type,
|
||
|
result_type a,
|
||
|
result_type b,
|
||
|
int d>
|
||
|
struct xor_combine_engine_max_aux_1<result_type,a,b,d,false>
|
||
|
: xor_combine_engine_max_aux_2<result_type,a,b,d>
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename result_type,
|
||
|
result_type a,
|
||
|
result_type b,
|
||
|
int d>
|
||
|
struct xor_combine_engine_max_aux
|
||
|
: xor_combine_engine_max_aux_1<result_type,a,b,d>
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename Engine1, size_t s1, typename Engine2, size_t s2, typename result_type>
|
||
|
struct xor_combine_engine_max
|
||
|
{
|
||
|
static const size_t w = std::numeric_limits<result_type>::digits;
|
||
|
|
||
|
static const result_type m1 =
|
||
|
math::min<
|
||
|
result_type,
|
||
|
result_type(Engine1::max - Engine1::min),
|
||
|
two_to_the_power<result_type, w-s1>::value - 1
|
||
|
>::value;
|
||
|
|
||
|
static const result_type m2 =
|
||
|
math::min<
|
||
|
result_type,
|
||
|
result_type(Engine2::max - Engine2::min),
|
||
|
two_to_the_power<result_type, w-s2>::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
|
||
|
|