#include #include #include #include #include #include #include #include // This example computes several statistical properties of a data // series in a single reduction. The algorithm is described in detail here: // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm // // Thanks to Joseph Rhoads for contributing this example // structure used to accumulate the moments and other // statistical properties encountered so far. template struct summary_stats_data { T n; T min; T max; T mean; T M2; T M3; T M4; // initialize to the identity element void initialize() { n = mean = M2 = M3 = M4 = 0; min = std::numeric_limits::max(); max = std::numeric_limits::min(); } T variance() { return M2 / (n - 1); } T variance_n() { return M2 / n; } T skewness() { return std::sqrt(n) * M3 / std::pow(M2, (T) 1.5); } T kurtosis() { return n * M4 / (M2 * M2); } }; // stats_unary_op is a functor that takes in a value x and // returns a variace_data whose mean value is initialized to x. template struct summary_stats_unary_op { __host__ __device__ summary_stats_data operator()(const T& x) const { summary_stats_data result; result.n = 1; result.min = x; result.max = x; result.mean = x; result.M2 = 0; result.M3 = 0; result.M4 = 0; return result; } }; // summary_stats_binary_op is a functor that accepts two summary_stats_data // structs and returns a new summary_stats_data which are an // approximation to the summary_stats for // all values that have been agregated so far template struct summary_stats_binary_op : public thrust::binary_function&, const summary_stats_data&, summary_stats_data > { __host__ __device__ summary_stats_data operator()(const summary_stats_data& x, const summary_stats_data & y) const { summary_stats_data result; // precompute some common subexpressions T n = x.n + y.n; T n2 = n * n; T n3 = n2 * n; T delta = y.mean - x.mean; T delta2 = delta * delta; T delta3 = delta2 * delta; T delta4 = delta3 * delta; //Basic number of samples (n), min, and max result.n = n; result.min = thrust::min(x.min, y.min); result.max = thrust::max(x.max, y.max); result.mean = x.mean + delta * y.n / n; result.M2 = x.M2 + y.M2; result.M2 += delta2 * x.n * y.n / n; result.M3 = x.M3 + y.M3; result.M3 += delta3 * x.n * y.n * (x.n - y.n) / n2; result.M3 += (T) 3.0 * delta * (x.n * y.M2 - y.n * x.M2) / n; result.M4 = x.M4 + y.M4; result.M4 += delta4 * x.n * y.n * (x.n * x.n - x.n * y.n + y.n * y.n) / n3; result.M4 += (T) 6.0 * delta2 * (x.n * x.n * y.M2 + y.n * y.n * x.M2) / n2; result.M4 += (T) 4.0 * delta * (x.n * y.M3 - y.n * x.M3) / n; return result; } }; template void print_range(const std::string& name, Iterator first, Iterator last) { typedef typename std::iterator_traits::value_type T; std::cout << name << ": "; thrust::copy(first, last, std::ostream_iterator(std::cout, " ")); std::cout << "\n"; } int main(void) { typedef float T; // initialize host array T h_x[] = {4, 7, 13, 16}; // transfer to device thrust::device_vector d_x(h_x, h_x + sizeof(h_x) / sizeof(T)); // setup arguments summary_stats_unary_op unary_op; summary_stats_binary_op binary_op; summary_stats_data init; init.initialize(); // compute summary statistics summary_stats_data result = thrust::transform_reduce(d_x.begin(), d_x.end(), unary_op, init, binary_op); std::cout <<"******Summary Statistics Example*****"<