<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2016 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: <NAME>
// =============================================================================
//
// Tests for various methods of calculating a global AABB (which encompasses the
// AABBs of a collection of collision shapes).
//
// =============================================================================

#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
#include <climits>
#include <random>

#include <thrust/transform.h>
#include <thrust/transform_reduce.h>

#include "chrono/core/ChTimer.h"
#include "chrono/parallel/ChOpenMP.h"

#include "chrono_parallel/math/real3.h"
#include "chrono_parallel/collision/ChCollision.h"

#if defined(CHRONO_OPENMP_ENABLED)
#include <thrust/system/omp/execution_policy.h>
#elif defined(CHRONO_TBB_ENABLED)
#include <thrust/system/tbb/execution_policy.h>
#endif

#define EXEC_POLICY thrust::omp::par
////#define EXEC_POLICY

using namespace chrono;
using namespace chrono::collision;

// Original implementation in Chrono::Parallel (ChBroadphase.cpp)
// --------------------------------------------------------------

typedef thrust::pair<real3, real3> bbox;

struct bbox_reduction : public thrust::binary_function<bbox, bbox, bbox> {
    bbox operator()(bbox a, bbox b) {
        real3 ll = real3(Min(a.first.x, b.first.x), Min(a.first.y, b.first.y),
            Min(a.first.z, b.first.z));  // lower left corner
        real3 ur = real3(Max(a.second.x, b.second.x), Max(a.second.y, b.second.y),
            Max(a.second.z, b.second.z));  // upper right corner
        return bbox(ll, ur);
    }
};

struct bbox_transformation : public thrust::unary_function<real3, bbox> {
    bbox operator()(real3 point) { return bbox(point, point); }
};

void RigidBoundingBox(const custom_vector<real3>& aabb_min,
                      const custom_vector<real3>& aabb_max,
                      real3& min_point,
                      real3& max_point) {
    if (aabb_min.size() == 0)
        return;

    bbox res(aabb_min[0], aabb_min[0]);
    bbox_transformation unary_op;
    bbox_reduction binary_op;
    res = thrust::transform_reduce(EXEC_POLICY, aabb_min.begin(), aabb_min.end(), unary_op, res, binary_op);
    res = thrust::transform_reduce(EXEC_POLICY, aabb_max.begin(), aabb_max.end(), unary_op, res, binary_op);

    min_point = res.first;
    max_point = res.second;
}

// A sequential implementation of the conditional algorithm
void RigidBoundingBox_seq(const custom_vector<real3>& aabb_min,
                          const custom_vector<real3>& aabb_max,
                          const custom_vector<uint>& id_rigid,
                          const custom_vector<char>& collide_rigid,
                          real3& min_point,
                          real3& max_point) {
    uint num_rigid_shapes = static_cast<uint>(aabb_min.size());

    if (aabb_min.size() == 0)
        return;

    min_point = real3(+C_LARGE_REAL, +C_LARGE_REAL, +C_LARGE_REAL);
    max_point = real3(-C_LARGE_REAL, -C_LARGE_REAL, -C_LARGE_REAL);

    for (uint i = 0; i < num_rigid_shapes; i++) {
        uint id = id_rigid[i];

        if (id == UINT_MAX || !collide_rigid[id]) {
            continue;
        }

        for (int j = 0; j < 3; j++) {
            if (aabb_min[i][j] < min_point[j])
                min_point[j] = aabb_min[i][j];
            if (aabb_max[i][j] > max_point[j])
                max_point[j] = aabb_max[i][j];
        }
    }
}

// A parallel implementation of the conditional algorithm
auto inverted = thrust::make_tuple(real3(+C_LARGE_REAL, +C_LARGE_REAL, +C_LARGE_REAL),
                                   real3(-C_LARGE_REAL, -C_LARGE_REAL, -C_LARGE_REAL),
                                   0);

struct BoxInvert {
    BoxInvert(const custom_vector<char>* collide) : m_collide(collide) {}
    thrust::tuple<real3, real3, uint> operator()(const thrust::tuple<real3, real3, uint>& lhs) {
        uint lhs_id = thrust::get<2>(lhs);
        if (lhs_id == UINT_MAX || (*m_collide)[lhs_id] == 0)
            return inverted;
        else
            return lhs;
    }
    const custom_vector<char>* m_collide;
};

struct BoxReduce {
    thrust::tuple<real3, real3, uint> operator()(const thrust::tuple<real3, real3, uint>& lhs,
                                                 const thrust::tuple<real3, real3, uint>& rhs) {
        real3 lhs_ll = thrust::get<0>(lhs);
        real3 lhs_ur = thrust::get<1>(lhs);

        real3 rhs_ll = thrust::get<0>(rhs);
        real3 rhs_ur = thrust::get<1>(rhs);

        real3 ll = real3(Min(lhs_ll.x, rhs_ll.x), Min(lhs_ll.y, rhs_ll.y), Min(lhs_ll.z, rhs_ll.z));
        real3 ur = real3(Max(lhs_ur.x, rhs_ur.x), Max(lhs_ur.y, rhs_ur.y), Max(lhs_ur.z, rhs_ur.z));

        return thrust::tuple<real3, real3, uint>(ll, ur, 0);
    }
};

void RigidBoundingBox_par(const custom_vector<real3>& aabb_min,
                          const custom_vector<real3>& aabb_max,
                          const custom_vector<uint>& id_rigid,
                          const custom_vector<char>& collide_rigid,
                          real3& min_point,
                          real3& max_point) {
    auto begin = thrust::make_zip_iterator(thrust::make_tuple(aabb_min.begin(), aabb_max.begin(), id_rigid.begin()));
    auto end = thrust::make_zip_iterator(thrust::make_tuple(aabb_min.end(), aabb_max.end(), id_rigid.end()));

    auto result = thrust::transform_reduce(EXEC_POLICY, begin, end, BoxInvert(&collide_rigid), inverted, BoxReduce());

    min_point = thrust::get<0>(result);
    max_point = thrust::get<1>(result);
}

// =================================================================================

int main(int argc, char* argv[]) {
    // Set number of threads
    int threads = 10;
    int max_threads = CHOMPfunctions::GetNumProcs();
    if (threads > max_threads)
        threads = max_threads;
    CHOMPfunctions::SetNumThreads(threads);

#pragma omp parallel
#pragma omp master
    std::cout << "Using " << CHOMPfunctions::GetNumThreads() << " threads.\n" << std::endl;

    // Set an arbitrary number of bodies
    uint nbodies = 100;

    // Miscellaneous uniform distributions
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dist_id(0, nbodies - 1);
    std::uniform_int_distribution<> dist_coll(0, 1);
    std::uniform_real_distribution<> dist_loc(-1.0, +1.0);<commit_msg>Update to reflect renamed ChOMP class<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2016 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: <NAME>
// =============================================================================
//
// Tests for various methods of calculating a global AABB (which encompasses the
// AABBs of a collection of collision shapes).
//
// =============================================================================

#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
#include <climits>
#include <random>

#include <thrust/transform.h>
#include <thrust/transform_reduce.h>

#include "chrono/core/ChTimer.h"
#include "chrono/parallel/ChOpenMP.h"

#include "chrono_parallel/math/real3.h"
#include "chrono_parallel/collision/ChCollision.h"

#if defined(CHRONO_OPENMP_ENABLED)
#include <thrust/system/omp/execution_policy.h>
#elif defined(CHRONO_TBB_ENABLED)
#include <thrust/system/tbb/execution_policy.h>
#endif

#define EXEC_POLICY thrust::omp::par
////#define EXEC_POLICY

using namespace chrono;
using namespace chrono::collision;

// Original implementation in Chrono::Parallel (ChBroadphase.cpp)
// --------------------------------------------------------------

typedef thrust::pair<real3, real3> bbox;

struct bbox_reduction : public thrust::binary_function<bbox, bbox, bbox> {
    bbox operator()(bbox a, bbox b) {
        real3 ll = real3(Min(a.first.x, b.first.x), Min(a.first.y, b.first.y),
            Min(a.first.z, b.first.z));  // lower left corner
        real3 ur = real3(Max(a.second.x, b.second.x), Max(a.second.y, b.second.y),
            Max(a.second.z, b.second.z));  // upper right corner
        return bbox(ll, ur);
    }
};

struct bbox_transformation : public thrust::unary_function<real3, bbox> {
    bbox operator()(real3 point) { return bbox(point, point); }
};

void RigidBoundingBox(const custom_vector<real3>& aabb_min,
                      const custom_vector<real3>& aabb_max,
                      real3& min_point,
                      real3& max_point) {
    if (aabb_min.size() == 0)
        return;

    bbox res(aabb_min[0], aabb_min[0]);
    bbox_transformation unary_op;
    bbox_reduction binary_op;
    res = thrust::transform_reduce(EXEC_POLICY, aabb_min.begin(), aabb_min.end(), unary_op, res, binary_op);
    res = thrust::transform_reduce(EXEC_POLICY, aabb_max.begin(), aabb_max.end(), unary_op, res, binary_op);

    min_point = res.first;
    max_point = res.second;
}

// A sequential implementation of the conditional algorithm
void RigidBoundingBox_seq(const custom_vector<real3>& aabb_min,
                          const custom_vector<real3>& aabb_max,
                          const custom_vector<uint>& id_rigid,
                          const custom_vector<char>& collide_rigid,
                          real3& min_point,
                          real3& max_point) {
    uint num_rigid_shapes = static_cast<uint>(aabb_min.size());

    if (aabb_min.size() == 0)
        return;

    min_point = real3(+C_LARGE_REAL, +C_LARGE_REAL, +C_LARGE_REAL);
    max_point = real3(-C_LARGE_REAL, -C_LARGE_REAL, -C_LARGE_REAL);

    for (uint i = 0; i < num_rigid_shapes; i++) {
        uint id = id_rigid[i];

        if (id == UINT_MAX || !collide_rigid[id]) {
            continue;
        }

        for (int j = 0; j < 3; j++) {
            if (aabb_min[i][j] < min_point[j])
                min_point[j] = aabb_min[i][j];
            if (aabb_max[i][j] > max_point[j])
                max_point[j] = aabb_max[i][j];
        }
    }
}

// A parallel implementation of the conditional algorithm
auto inverted = thrust::make_tuple(real3(+C_LARGE_REAL, +C_LARGE_REAL, +C_LARGE_REAL),
                                   real3(-C_LARGE_REAL, -C_LARGE_REAL, -C_LARGE_REAL),
                                   0);

struct BoxInvert {
    BoxInvert(const custom_vector<char>* collide) : m_collide(collide) {}
    thrust::tuple<real3, real3, uint> operator()(const thrust::tuple<real3, real3, uint>& lhs) {
        uint lhs_id = thrust::get<2>(lhs);
        if (lhs_id == UINT_MAX || (*m_collide)[lhs_id] == 0)
            return inverted;
        else
            return lhs;
    }
    const custom_vector<char>* m_collide;
};

struct BoxReduce {
    thrust::tuple<real3, real3, uint> operator()(const thrust::tuple<real3, real3, uint>& lhs,
                                                 const thrust::tuple<real3, real3, uint>& rhs) {
        real3 lhs_ll = thrust::get<0>(lhs);
        real3 lhs_ur = thrust::get<1>(lhs);

        real3 rhs_ll = thrust::get<0>(rhs);
        real3 rhs_ur = thrust::get<1>(rhs);

        real3 ll = real3(Min(lhs_ll.x, rhs_ll.x), Min(lhs_ll.y, rhs_ll.y), Min(lhs_ll.z, rhs_ll.z));
        real3 ur = real3(Max(lhs_ur.x, rhs_ur.x), Max(lhs_ur.y, rhs_ur.y), Max(lhs_ur.z, rhs_ur.z));

        return thrust::tuple<real3, real3, uint>(ll, ur, 0);
    }
};

void RigidBoundingBox_par(const custom_vector<real3>& aabb_min,
                          const custom_vector<real3>& aabb_max,
                          const custom_vector<uint>& id_rigid,
                          const custom_vector<char>& collide_rigid,
                          real3& min_point,
                          real3& max_point) {
    auto begin = thrust::make_zip_iterator(thrust::make_tuple(aabb_min.begin(), aabb_max.begin(), id_rigid.begin()));
    auto end = thrust::make_zip_iterator(thrust::make_tuple(aabb_min.end(), aabb_max.end(), id_rigid.end()));

    auto result = thrust::transform_reduce(EXEC_POLICY, begin, end, BoxInvert(&collide_rigid), inverted, BoxReduce());

    min_point = thrust::get<0>(result);
    max_point = thrust::get<1>(result);
}

// =================================================================================

int main(int argc, char* argv[]) {
    // Set number of threads
    int threads = 10;
    int max_threads = ChOMP::GetNumProcs();
    if (threads > max_threads)
        threads = max_threads;
    ChOMP::SetNumThreads(threads);

#pragma omp parallel
#pragma omp master
    std::cout << "Using " << ChOMP::GetNumThreads() << " threads.\n" << std::endl;

    // Set an arbitrary number of bodies
    uint nbodies = 100;

    // Miscellaneous uniform distributions
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dist_id(0, nbodies - 1);
    std::uniform_int_distribution<> dist_coll(0, 1);
    std::uniform_real_distribution<> dist_loc(-1.0, +1.0);
{'fraction_non_alphanumeric': 0.1915966386554622, 'fraction_numerical': 0.012276214833759591, 'mean_word_length': 2.9304997128087305, 'pattern_counts': {'":': 0, '<': 111, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2400396', 'n_tokens_mistral': 4629, 'n_tokens_neox': 4458, 'n_words': 932}