<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_adu_access.C $     */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//--------------------------------------------------------------------------
//
//
/// @file p9_adu_access.C
/// @brief Read coherent state of memory via the ADU (FAPI)
///
// *HWP HWP Owner Christina Graves clgraves@us.ibm.com
// *HWP FW Owner: Thi Tran thi@us.ibm.com
// *HWP Team: Nest
// *HWP Level: 3
// *HWP Consumed by: SBE
//
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
// Includes
//--------------------------------------------------------------------------
#include <p9_adu_access.H>
#include <p9_adu_coherent_utils.H>

extern "C" {

//--------------------------------------------------------------------------
//  HWP entry point
//--------------------------------------------------------------------------
    fapi2::ReturnCode p9_adu_access(const
                                    fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
                                    const uint64_t i_address,
                                    const bool i_rnw,
                                    const uint32_t i_flags,
                                    const bool i_firstGranule,
                                    const bool i_lastGranule,
                                    uint8_t io_data[])
    {

        bool l_busyBitStatus = false;
        adu_status_busy_handler l_busyHandling;

        // mark HWP entry
        FAPI_DBG("Entering ...\n");

        // Process input flag
        p9_ADU_oper_flag l_myAduFlag;
        l_myAduFlag.getFlag(i_flags);

        //If autoinc is set and this is not a DMA operation unset autoinc before passing the flags through since autoinc is only allowed for DMA operations
        if (l_myAduFlag.getOperationType() != p9_ADU_oper_flag::DMA_PARTIAL)
        {
            l_myAduFlag.setAutoIncrement(false);
        }

        //If we were using autoinc and this is the last granule we need to clear autoinc before the last read/write
        if( i_lastGranule && l_myAduFlag.getAutoIncrement() )
        {
            FAPI_TRY(p9_adu_coherent_clear_autoinc(i_target), "Error from p9_adu_coherent_clear_autoinc");
        }

        //If we are doing a read operation read the data
        if (i_rnw)
        {
            FAPI_TRY(p9_adu_coherent_adu_read(i_target, i_firstGranule, i_address, l_myAduFlag, io_data),
                     "Error from p9_adu_coherent_adu_read");
        }
        //Otherwise this is a write and write the data
        else
        {
            FAPI_TRY(p9_adu_coherent_adu_write(i_target, i_firstGranule, i_address, l_myAduFlag, io_data),
                     "Error from p9_adu_coherent_adu_write");
        }

        //If we are not in fastmode or this is the last granule, we want to check the status
        if ( (i_lastGranule) || (l_myAduFlag.getFastMode() == false) )
        {
            //If we are using autoincrement and this is not the last granule we expect the busy bit to still be set
            if ( (l_myAduFlag.getAutoIncrement()) && !i_lastGranule )
            {
                l_busyHandling = EXPECTED_BUSY_BIT_SET;
            }
            //Otherwise we expect the busy bit to be cleared
            else
            {
                l_busyHandling = EXPECTED_BUSY_BIT_CLEAR;
            }

            //We only want to do the status check if this is not a ci operation
            if (l_myAduFlag.getOperationType() != p9_ADU_oper_flag::CACHE_INHIBIT)
            {
                FAPI_TRY(p9_adu_coherent_status_check(i_target, l_busyHandling, false,
                                                      l_busyBitStatus),
                         "Error from p9_adu_coherent_status_check");
            }

            //If it's the last read/write cleanup the adu
            if (i_lastGranule)
            {
                FAPI_TRY(p9_adu_coherent_cleanup_adu(i_target),
                         "Error doing p9_adu_coherent_cleanup_adu");
            }
        }

    fapi_try_exit:

        //If there is an error and we want to cleanup the ADU
        if ( fapi2::current_err && l_myAduFlag.getOperFailCleanup() )
        {
            //reset the ADU
            (void) p9_adu_coherent_utils_reset_adu(i_target);
            uint32_t num_attempts = l_myAduFlag.getNumLockAttempts();
            //Unlock the ADU
            (void) p9_adu_coherent_manage_lock(i_target, false, false, num_attempts);
        }

        //Append the input data to an error if we got an error back
#ifndef __PPE__

        if (fapi2::current_err)
        {
            p9_adu_coherent_append_input_data(i_address, i_rnw, i_flags, fapi2::current_err);
        }

#endif

        FAPI_DBG("Exiting...");
        //Return the error that we got from up above
        return fapi2::current_err;
    }

} // extern "C"
<commit_msg>update owner comments in ADU, PBA, TOD HWPs<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_adu_access.C $     */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//--------------------------------------------------------------------------
//
//
/// @file p9_adu_access.C
/// @brief Read coherent state of memory via the ADU (FAPI)
///
// *HWP HWP Owner Joe McGill jmcgill@us.ibm.com
// *HWP FW Owner: Thi Tran thi@us.ibm.com
// *HWP Team: Nest
// *HWP Level: 3
// *HWP Consumed by: SBE
//
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
// Includes
//--------------------------------------------------------------------------
#include <p9_adu_access.H>
#include <p9_adu_coherent_utils.H>

extern "C" {

//--------------------------------------------------------------------------
//  HWP entry point
//--------------------------------------------------------------------------
    fapi2::ReturnCode p9_adu_access(const
                                    fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
                                    const uint64_t i_address,
                                    const bool i_rnw,
                                    const uint32_t i_flags,
                                    const bool i_firstGranule,
                                    const bool i_lastGranule,
                                    uint8_t io_data[])
    {

        bool l_busyBitStatus = false;
        adu_status_busy_handler l_busyHandling;

        // mark HWP entry
        FAPI_DBG("Entering ...\n");

        // Process input flag
        p9_ADU_oper_flag l_myAduFlag;
        l_myAduFlag.getFlag(i_flags);

        //If autoinc is set and this is not a DMA operation unset autoinc before passing the flags through since autoinc is only allowed for DMA operations
        if (l_myAduFlag.getOperationType() != p9_ADU_oper_flag::DMA_PARTIAL)
        {
            l_myAduFlag.setAutoIncrement(false);
        }

        //If we were using autoinc and this is the last granule we need to clear autoinc before the last read/write
        if( i_lastGranule && l_myAduFlag.getAutoIncrement() )
        {
            FAPI_TRY(p9_adu_coherent_clear_autoinc(i_target), "Error from p9_adu_coherent_clear_autoinc");
        }

        //If we are doing a read operation read the data
        if (i_rnw)
        {
            FAPI_TRY(p9_adu_coherent_adu_read(i_target, i_firstGranule, i_address, l_myAduFlag, io_data),
                     "Error from p9_adu_coherent_adu_read");
        }
        //Otherwise this is a write and write the data
        else
        {
            FAPI_TRY(p9_adu_coherent_adu_write(i_target, i_firstGranule, i_address, l_myAduFlag, io_data),
                     "Error from p9_adu_coherent_adu_write");
        }

        //If we are not in fastmode or this is the last granule, we want to check the status
        if ( (i_lastGranule) || (l_myAduFlag.getFastMode() == false) )
        {
            //If we are using autoincrement and this is not the last granule we expect the busy bit to still be set
            if ( (l_myAduFlag.getAutoIncrement()) && !i_lastGranule )
            {
                l_busyHandling = EXPECTED_BUSY_BIT_SET;
            }
            //Otherwise we expect the busy bit to be cleared
            else
            {
                l_busyHandling = EXPECTED_BUSY_BIT_CLEAR;
            }

            //We only want to do the status check if this is not a ci operation
            if (l_myAduFlag.getOperationType() != p9_ADU_oper_flag::CACHE_INHIBIT)
            {
                FAPI_TRY(p9_adu_coherent_status_check(i_target, l_busyHandling, false,
                                                      l_busyBitStatus),
                         "Error from p9_adu_coherent_status_check");
            }

            //If it's the last read/write cleanup the adu
            if (i_lastGranule)
            {
                FAPI_TRY(p9_adu_coherent_cleanup_adu(i_target),
                         "Error doing p9_adu_coherent_cleanup_adu");
            }
        }

    fapi_try_exit:

        //If there is an error and we want to cleanup the ADU
        if ( fapi2::current_err && l_myAduFlag.getOperFailCleanup() )
        {
            //reset the ADU
            (void) p9_adu_coherent_utils_reset_adu(i_target);
            uint32_t num_attempts = l_myAduFlag.getNumLockAttempts();
            //Unlock the ADU
            (void) p9_adu_coherent_manage_lock(i_target, false, false, num_attempts);
        }

        //Append the input data to an error if we got an error back
#ifndef __PPE__

        if (fapi2::current_err)
        {
            p9_adu_coherent_append_input_data(i_address, i_rnw, i_flags, fapi2::current_err);
        }

#endif

        FAPI_DBG("Exiting...");
        //Return the error that we got from up above
        return fapi2::current_err;
    }

} // extern "C"
<|endoftext|>


<commit_before>/****************************************************************************
 * Copyright (c) 2012-2017 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 ****************************************************************************/
#include <Teuchos_CommandLineProcessor.hpp>
#include <Teuchos_StandardCatchMacros.hpp>

#include <Kokkos_DefaultNode.hpp>

#include <DTK_ConfigDefs.hpp>

#include <DTK_LinearBVH.hpp>
#include <details/DTK_DetailsTreeTraversal.hpp>

#include <cmath>
#include <random>

template <typename NO>
class RandomWithinLambda
{
  public:
    using DeviceType = typename DataTransferKit::BVH<NO>::DeviceType;
    using ExecutionSpace = typename DeviceType::execution_space;

    using PointsView = Kokkos::View<double * [3], ExecutionSpace>;
    using RView = Kokkos::View<double *, ExecutionSpace>;

  public:
    RandomWithinLambda( PointsView point_coords, RView radii,
                        DataTransferKit::BVH<NO> bvh,
                        unsigned int max_n_indices = 10000 )
        : _point_coords( point_coords )
        , _radii( radii )
        , _bvh( bvh )
        , _max_n_indices( max_n_indices )
    {
    }

    KOKKOS_INLINE_FUNCTION
    void operator()( int const i ) const
    {
        DataTransferKit::Details::Within within_predicate(
            {_point_coords( i, 0 ), _point_coords( i, 1 ),
             _point_coords( i, 2 )},
            _radii( i ) );
        int indices[_max_n_indices];
        unsigned int n_indices = 0;
        DataTransferKit::Details::spatial_query(
            _bvh, within_predicate, indices, n_indices, _max_n_indices );
    }

  private:
    PointsView _point_coords;
    RView _radii;
    DataTransferKit::BVH<NO> _bvh;
    unsigned int _max_n_indices;
};

template <typename NO>
class RandomNearestLambda
{
  public:
    using DeviceType = typename DataTransferKit::BVH<NO>::DeviceType;
    using ExecutionSpace = typename DeviceType::execution_space;

    using PointsView = Kokkos::View<double * [3], ExecutionSpace>;
    using KView = Kokkos::View<int *, ExecutionSpace>;

  public:
    RandomNearestLambda( PointsView point_coords, KView k,
                         DataTransferKit::BVH<NO> bvh )
        : _point_coords( point_coords )
        , _k( k )
        , _bvh( bvh )
    {
    }

    KOKKOS_INLINE_FUNCTION
    void operator()( int const i ) const
    {
        unsigned int constexpr max_n_indices = 1000;
        int indices[max_n_indices];
        unsigned int n_indices = 0;
        DataTransferKit::Details::nearest_query(
            _bvh, {_point_coords( i, 0 ), _point_coords( i, 1 ),
                   _point_coords( i, 2 )},
            _k[i], indices, n_indices, max_n_indices );
    }

  private:
    PointsView _point_coords;
    KView _k;
    DataTransferKit::BVH<NO> _bvh;
};

std::vector<std::array<double, 3>>
make_stuctured_cloud( double Lx, double Ly, double Lz, int nx, int ny, int nz )
{
    std::vector<std::array<double, 3>> cloud( nx * ny * nz );
    std::function<int( int, int, int )> ind = [nx, ny, nz](
        int i, int j, int k ) { return i + j * nx + k * ( nx * ny ); };
    double x, y, z;
    for ( int i = 0; i < nx; ++i )
        for ( int j = 0; j < ny; ++j )
            for ( int k = 0; k < nz; ++k )
            {
                x = i * Lx / ( nx - 1 );
                y = j * Ly / ( ny - 1 );
                z = k * Lz / ( nz - 1 );
                cloud[ind( i, j, k )] = {x, y, z};
            }
    return cloud;
}

std::vector<std::array<double, 3>> make_random_cloud( double Lx, double Ly,
                                                      double Lz, int n )
{
    std::vector<std::array<double, 3>> cloud( n );
    std::default_random_engine generator;
    std::uniform_real_distribution<double> distribution_x( 0.0, Lz );
    std::uniform_real_distribution<double> distribution_y( 0.0, Ly );
    std::uniform_real_distribution<double> distribution_z( 0.0, Lz );
    for ( int i = 0; i < n; ++i )
    {
        double x = distribution_x( generator );
        double y = distribution_y( generator );
        double z = distribution_z( generator );
        cloud[i] = {x, y, z};
    }
    return cloud;
}

template <class NO>
int main_( Teuchos::CommandLineProcessor &clp, int argc, char *argv[] )
{
    using DeviceType = typename DataTransferKit::BVH<NO>::DeviceType;
    using ExecutionSpace = typename DeviceType::execution_space;

    double Lx = 100.0;
    double Ly = 100.0;
    double Lz = 100.0;
    int nx = 11;
    int ny = 11;
    int nz = 11;
    int n_points = 100;
    std::string mode = "radius";

    clp.setOption( "nx", &nx, "source mesh points in x-direction." );
    clp.setOption( "ny", &ny, "source mesh points in y-direction." );
    clp.setOption( "nz", &nz, "source mesh points in z-direction." );
    clp.setOption( "N", &n_points,
                   "number of target mesh points (distributed randomly)." );
    clp.setOption( "mode", &mode, "mode: (knn | radius)" );

    clp.recogniseAllOptions( true );
    switch ( clp.parse( argc, argv ) )
    {
    case Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED:
        return EXIT_SUCCESS;
    case Teuchos::CommandLineProcessor::PARSE_ERROR:
    case Teuchos::CommandLineProcessor::PARSE_UNRECOGNIZED_OPTION:
        return EXIT_FAILURE;
    case Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL:
        break;
    }

    // contruct a cloud of points (nodes of a structured grid)
    auto cloud = make_stuctured_cloud( Lx, Ly, Lz, nx, ny, nz );
    int n = cloud.size();

    Kokkos::View<DataTransferKit::BBox *, DeviceType> bounding_boxes(
        "bounding_boxes", n );
    auto bounding_boxes_host = Kokkos::create_mirror_view( bounding_boxes );
    // build bounding volume hierarchy
    for ( int i = 0; i < n; ++i )
    {
        auto const &point = cloud[i];
        double x = std::get<0>( point );
        double y = std::get<1>( point );
        double z = std::get<2>( point );
        bounding_boxes_host[i] = {
            x, x, y, y, z, z,
        };
    }

    Kokkos::deep_copy( bounding_boxes, bounding_boxes_host );

    DataTransferKit::BVH<NO> bvh( bounding_boxes );

    // random points for radius search and kNN queries
    auto queries = make_random_cloud( Lx, Ly, Lz, n_points );
    Kokkos::View<double * [3], ExecutionSpace> point_coords( "point_coords",
                                                             n_points );

    auto point_coords_host = Kokkos::create_mirror_view( point_coords );
    for ( int i = 0; i < n_points; ++i )
    {
        auto const &point = queries[i];
        point_coords_host( i, 0 ) = std::get<0>( point );
        point_coords_host( i, 1 ) = std::get<1>( point );
        point_coords_host( i, 2 ) = std::get<2>( point );
    }
    Kokkos::deep_copy( point_coords, point_coords_host );

    std::default_random_engine generator;

    if ( mode == "knn" )
    {
        Kokkos::View<int *, ExecutionSpace> k( "distribution_k", n_points );
        auto k_host = Kokkos::create_mirror_view( k );

        // use random number k of for the kNN search
        std::uniform_int_distribution<int> distribution_k(
            1, std::floor( sqrt( nx * nx + ny * ny + nz * nz ) ) );
        for ( int i = 0; i < n_points; ++i )
        {
            k_host[i] = distribution_k( generator );
        }
        Kokkos::deep_copy( k, k_host );

        // do the search
        RandomNearestLambda<NO> random_nearest_lambda( point_coords, k, bvh );

        Kokkos::parallel_for(
            "random_nearest",
            Kokkos::RangePolicy<ExecutionSpace>( 0, n_points ),
            random_nearest_lambda );
        Kokkos::fence();
    }
    else if ( mode == "radius" )
    {
        Kokkos::View<double *, ExecutionSpace> radii( "radii", n_points );
        auto radii_host = Kokkos::create_mirror_view( radii );

        // use random radius for the search
        // set the limit of approximately 100 points by
        // solving n_points*pi*r^2/(Lx^2 + Ly^2 + Lz^2) <= 100
        const int approx_points = 100;
        double max_radius = sqrt(
            approx_points * ( Lx * Lx + Ly * Ly + Lz * Lz ) / ( n * M_PI ) );
        std::uniform_real_distribution<double> distribution_radius(
            0.0, max_radius );
        for ( int i = 0; i < n_points; ++i )
        {
            radii_host[i] = distribution_radius( generator );
        }

        Kokkos::deep_copy( radii, radii_host );

        // do the search
        RandomWithinLambda<NO> random_within_lambda(
            point_coords, radii, bvh, std::max( 2 * approx_points, 100 ) );

        Kokkos::parallel_for(
            "random_within", Kokkos::RangePolicy<ExecutionSpace>( 0, n_points ),
            random_within_lambda );
        Kokkos::fence();
    }

    return 0;
}

int main( int argc, char *argv[] )
{
    bool success = false;
    bool verbose = true;

    try
    {
        Kokkos::initialize();

        const bool throwExceptions = false;

        Teuchos::CommandLineProcessor clp( throwExceptions );

        std::string node = "";
        clp.setOption( "node", &node, "node type (serial | openmp | cuda)" );

        clp.recogniseAllOptions( false );
        switch ( clp.parse( argc, argv, NULL ) )
        {
        case Teuchos::CommandLineProcessor::PARSE_ERROR:
            return EXIT_FAILURE;
        case Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED:
        case Teuchos::CommandLineProcessor::PARSE_UNRECOGNIZED_OPTION:
        case Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL:
            break;
        }

        if ( node == "" )
        {
            typedef KokkosClassic::DefaultNode::DefaultNodeType Node;
            return main_<Node>( clp, argc, argv );
        }
        else if ( node == "serial" )
        {
#ifdef KOKKOS_HAVE_SERIAL
            typedef Kokkos::Compat::KokkosSerialWrapperNode Node;

            return main_<Node>( clp, argc, argv );
#else
            throw std::runtime_error( "Serial node type is disabled" );
#endif
        }
        else if ( node == "openmp" )
        {
#ifdef KOKKOS_HAVE_OPENMP
            typedef Kokkos::Compat::KokkosOpenMPWrapperNode Node;

            return main_<Node>( clp, argc, argv );
#else
            throw std::runtime_error( "OpenMP node type is disabled" );
#endif
        }
        else if ( node == "cuda" )
        {
#ifdef KOKKOS_HAVE_CUDA
            typedef Kokkos::Compat::KokkosCudaWrapperNode Node;

            return main_<Node>( clp, argc, argv );
#else
            throw std::runtime_error( "CUDA node type is disabled" );
#endif
        }
        else
        {
            throw std::runtime_error( "Unrecognized node type" );
        }
        Kokkos::finalize();
    }
    TEUCHOS_STANDARD_CATCH_STATEMENTS( verbose, std::cerr, success );

    return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
}
<commit_msg>Quick workaround for the hardcoded bounds<commit_after>/****************************************************************************
 * Copyright (c) 2012-2017 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 ****************************************************************************/
#include <Teuchos_CommandLineProcessor.hpp>
#include <Teuchos_StandardCatchMacros.hpp>

#include <Kokkos_DefaultNode.hpp>

#include <DTK_ConfigDefs.hpp>

#include <DTK_LinearBVH.hpp>
#include <details/DTK_DetailsTreeTraversal.hpp>

#include <cmath>
#include <random>

const int MAX_N_KNN = 1000;
const int MAX_N_WITHIN = 10000;

template <typename NO>
class RandomWithinLambda
{
  public:
    using DeviceType = typename DataTransferKit::BVH<NO>::DeviceType;
    using ExecutionSpace = typename DeviceType::execution_space;
    using MemorySpace = typename DeviceType::memory_space;

    using PointsView = Kokkos::View<double * [3], ExecutionSpace>;
    using RView = Kokkos::View<double *, ExecutionSpace>;

  public:
    RandomWithinLambda( PointsView point_coords, RView radii,
                        DataTransferKit::BVH<NO> bvh )
        : _point_coords( point_coords )
        , _radii( radii )
        , _bvh( bvh )
    {
    }

    KOKKOS_INLINE_FUNCTION
    void operator()( int const i ) const
    {
        DataTransferKit::Details::Within within_predicate(
            {_point_coords( i, 0 ), _point_coords( i, 1 ),
             _point_coords( i, 2 )},
            _radii( i ) );
        unsigned int constexpr max_n_indices = MAX_N_WITHIN;
        int indices[max_n_indices];

        unsigned int n_indices = 0;
        DataTransferKit::Details::spatial_query(
            _bvh, within_predicate, indices, n_indices, max_n_indices );
    }

  private:
    PointsView _point_coords;
    RView _radii;
    DataTransferKit::BVH<NO> _bvh;
};

template <typename NO>
class RandomNearestLambda
{
  public:
    using DeviceType = typename DataTransferKit::BVH<NO>::DeviceType;
    using ExecutionSpace = typename DeviceType::execution_space;

    using PointsView = Kokkos::View<double * [3], ExecutionSpace>;
    using KView = Kokkos::View<int *, ExecutionSpace>;

  public:
    RandomNearestLambda( PointsView point_coords, KView k,
                         DataTransferKit::BVH<NO> bvh )
        : _point_coords( point_coords )
        , _k( k )
        , _bvh( bvh )
    {
    }

    KOKKOS_INLINE_FUNCTION
    void operator()( int const i ) const
    {
        unsigned int constexpr max_n_indices = MAX_N_KNN;
        int indices[max_n_indices];
        unsigned int n_indices = 0;
        DataTransferKit::Details::nearest_query(
            _bvh, {_point_coords( i, 0 ), _point_coords( i, 1 ),
                   _point_coords( i, 2 )},
            _k[i], indices, n_indices, max_n_indices );
    }

  private:
    PointsView _point_coords;
    KView _k;
    DataTransferKit::BVH<NO> _bvh;
};

std::vector<std::array<double, 3>>
make_stuctured_cloud( double Lx, double Ly, double Lz, int nx, int ny, int nz )
{
    std::vector<std::array<double, 3>> cloud( nx * ny * nz );
    std::function<int( int, int, int )> ind = [nx, ny, nz](
        int i, int j, int k ) { return i + j * nx + k * ( nx * ny ); };
    double x, y, z;
    for ( int i = 0; i < nx; ++i )
        for ( int j = 0; j < ny; ++j )
            for ( int k = 0; k < nz; ++k )
            {
                x = i * Lx / ( nx - 1 );
                y = j * Ly / ( ny - 1 );
                z = k * Lz / ( nz - 1 );
                cloud[ind( i, j, k )] = {x, y, z};
            }
    return cloud;
}

std::vector<std::array<double, 3>> make_random_cloud( double Lx, double Ly,
                                                      double Lz, int n )
{
    std::vector<std::array<double, 3>> cloud( n );
    std::default_random_engine generator;
    std::uniform_real_distribution<double> distribution_x( 0.0, Lz );
    std::uniform_real_distribution<double> distribution_y( 0.0, Ly );
    std::uniform_real_distribution<double> distribution_z( 0.0, Lz );
    for ( int i = 0; i < n; ++i )
    {
        double x = distribution_x( generator );
        double y = distribution_y( generator );
        double z = distribution_z( generator );
        cloud[i] = {x, y, z};
    }
    return cloud;
}

template <class NO>
int main_( Teuchos::CommandLineProcessor &clp, int argc, char *argv[] )
{
    using DeviceType = typename DataTransferKit::BVH<NO>::DeviceType;
    using ExecutionSpace = typename DeviceType::execution_space;

    double Lx = 100.0;
    double Ly = 100.0;
    double Lz = 100.0;
    int nx = 11;
    int ny = 11;
    int nz = 11;
    int n_points = 100;
    std::string mode = "radius";

    clp.setOption( "nx", &nx, "source mesh points in x-direction." );
    clp.setOption( "ny", &ny, "source mesh points in y-direction." );
    clp.setOption( "nz", &nz, "source mesh points in z-direction." );
    clp.setOption( "N", &n_points,
                   "number of target mesh points (distributed randomly)." );
    clp.setOption( "mode", &mode, "mode: (knn | radius)" );

    clp.recogniseAllOptions( true );
    switch ( clp.parse( argc, argv ) )
    {
    case Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED:
        return EXIT_SUCCESS;
    case Teuchos::CommandLineProcessor::PARSE_ERROR:
    case Teuchos::CommandLineProcessor::PARSE_UNRECOGNIZED_OPTION:
        return EXIT_FAILURE;
    case Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL:
        break;
    }

    // contruct a cloud of points (nodes of a structured grid)
    auto cloud = make_stuctured_cloud( Lx, Ly, Lz, nx, ny, nz );
    int n = cloud.size();

    Kokkos::View<DataTransferKit::BBox *, DeviceType> bounding_boxes(
        "bounding_boxes", n );
    auto bounding_boxes_host = Kokkos::create_mirror_view( bounding_boxes );
    // build bounding volume hierarchy
    for ( int i = 0; i < n; ++i )
    {
        auto const &point = cloud[i];
        double x = std::get<0>( point );
        double y = std::get<1>( point );
        double z = std::get<2>( point );
        bounding_boxes_host[i] = {
            x, x, y, y, z, z,
        };
    }

    Kokkos::deep_copy( bounding_boxes, bounding_boxes_host );

    DataTransferKit::BVH<NO> bvh( bounding_boxes );

    // random points for radius search and kNN queries
    auto queries = make_random_cloud( Lx, Ly, Lz, n_points );
    Kokkos::View<double * [3], ExecutionSpace> point_coords( "point_coords",
                                                             n_points );

    auto point_coords_host = Kokkos::create_mirror_view( point_coords );
    for ( int i = 0; i < n_points; ++i )
    {
        auto const &point = queries[i];
        point_coords_host( i, 0 ) = std::get<0>( point );
        point_coords_host( i, 1 ) = std::get<1>( point );
        point_coords_host( i, 2 ) = std::get<2>( point );
    }
    Kokkos::deep_copy( point_coords, point_coords_host );

    std::default_random_engine generator;

    if ( mode == "knn" )
    {
        Kokkos::View<int *, ExecutionSpace> k( "distribution_k", n_points );
        auto k_host = Kokkos::create_mirror_view( k );

        // use random number k of for the kNN search
        int max_k = std::floor( sqrt( nx * nx + ny * ny + nz * nz ) );
        std::uniform_int_distribution<int> distribution_k( 1, max_k );
        for ( int i = 0; i < n_points; ++i )
        {
            k_host[i] = distribution_k( generator );
        }
        Kokkos::deep_copy( k, k_host );

        if ( max_k >= MAX_N_KNN )
            throw std::runtime_error(
                "Abort: some hardcoded arrays may overflow." );

        // do the search
        RandomNearestLambda<NO> random_nearest_lambda( point_coords, k, bvh );

        Kokkos::parallel_for(
            "random_nearest",
            Kokkos::RangePolicy<ExecutionSpace>( 0, n_points ),
            random_nearest_lambda );
        Kokkos::fence();
    }
    else if ( mode == "radius" )
    {
        Kokkos::View<double *, ExecutionSpace> radii( "radii", n_points );
        auto radii_host = Kokkos::create_mirror_view( radii );

        // use random radius for the search
        // set the limit of approximately 100 points by
        // solving n_points*pi*r^2/(Lx^2 + Ly^2 + Lz^2) <= 100
        const int approx_points = 100;
        double max_radius = sqrt(
            approx_points * ( Lx * Lx + Ly * Ly + Lz * Lz ) / ( n * M_PI ) );
        std::uniform_real_distribution<double> distribution_radius(
            0.0, max_radius );
        for ( int i = 0; i < n_points; ++i )
        {
            radii_host[i] = distribution_radius( generator );
        }

        Kokkos::deep_copy( radii, radii_host );

        if ( 2 * approx_points >= MAX_N_WITHIN )
            throw std::runtime_error(
                "Abort: some hardcoded arrays may overflow." );

        // do the search
        RandomWithinLambda<NO> random_within_lambda( point_coords, radii, bvh );

        Kokkos::parallel_for(
            "random_within", Kokkos::RangePolicy<ExecutionSpace>( 0, n_points ),
            random_within_lambda );
        Kokkos::fence();
    }

    return 0;
}

int main( int argc, char *argv[] )
{
    bool success = false;
    bool verbose = true;

    try
    {
        Kokkos::initialize();

        const bool throwExceptions = false;

        Teuchos::CommandLineProcessor clp( throwExceptions );

        std::string node = "";
        clp.setOption( "node", &node, "node type (serial | openmp | cuda)" );

        clp.recogniseAllOptions( false );
        switch ( clp.parse( argc, argv, NULL ) )
        {
        case Teuchos::CommandLineProcessor::PARSE_ERROR:
            return EXIT_FAILURE;
        case Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED:
        case Teuchos::CommandLineProcessor::PARSE_UNRECOGNIZED_OPTION:
        case Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL:
            break;
        }

        if ( node == "" )
        {
            typedef KokkosClassic::DefaultNode::DefaultNodeType Node;
            return main_<Node>( clp, argc, argv );
        }
        else if ( node == "serial" )
        {
#ifdef KOKKOS_HAVE_SERIAL
            typedef Kokkos::Compat::KokkosSerialWrapperNode Node;

            return main_<Node>( clp, argc, argv );
#else
            throw std::runtime_error( "Serial node type is disabled" );
#endif
        }
        else if ( node == "openmp" )
        {
#ifdef KOKKOS_HAVE_OPENMP
            typedef Kokkos::Compat::KokkosOpenMPWrapperNode Node;

            return main_<Node>( clp, argc, argv );
#else
            throw std::runtime_error( "OpenMP node type is disabled" );
#endif
        }
        else if ( node == "cuda" )
        {
#ifdef KOKKOS_HAVE_CUDA
            typedef Kokkos::Compat::KokkosCudaWrapperNode Node;

            return main_<Node>( clp, argc, argv );
#else
            throw std::runtime_error( "CUDA node type is disabled" );
#endif
        }
        else
        {
            throw std::runtime_error( "Unrecognized node type" );
        }
        Kokkos::finalize();
    }
    TEUCHOS_STANDARD_CATCH_STATEMENTS( verbose, std::cerr, success );

    return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
}
<|endoftext|>


<commit_before>// symbiosis: A hacky and lightweight compiler framework
//
#include "symbiosis.hpp"
#include <sys/stat.h>

#include <iostream>

#include <vector>

using namespace std;

namespace symbiosis {

  bool intel = false;
  bool arm = false;
  bool am_i_pic = false;

  void figure_out_cpu_architecture() {
    uchar *p = (uchar *)figure_out_cpu_architecture;
    if (p[3] == 0xe9 || p[3] == 0xe5) { cout << "ARM" << endl;
        arm = true; return }
    cout << "Unknown CPU id: "; dump(p, 4);
  }

  bool __am_i_pic() {
    uchar *p = (uchar *)__am_i_pic;
    int i = 0;
    uchar c = 0;
    do {
      c = p[i++];
    } while (i < 10 && c != 0x48 && c != 0xbf);
    return c == 0x48;
  }

  class exception : public std::exception {
    const char *what_;
  public:
    exception(const char *w) : what_(w) { }
    virtual ~exception() throw() { }
    virtual const char* what() const throw() { return what_; }
  };

  char *command_file = 0;;

  #define M10(v, b) #v #b
  #define M3(a,b) M10(a+1000, v),M10(a+2000, v), M10(a+3000, v),M10(a+4000, v)
  #define M2(a,b) M3(a+100, v) , M3(a+200, v) , M3(a+300, v) , M3(a+400, v)
  #define M1(a,b) M2(a+10, v) , M2(a+20, v) , M2(a+30, v) , M2(a+40, v)
  #define M(v) M1(1, v), M1(2, v), M1(3, v), M1(4, v), M1(5, v)

  uchar *virtual_code_start = 0;
  uchar *virtual_code_end = 0;

  uchar *out_code_start = 0;
  uchar *out_code_end = 0;
  uchar *out_c = 0;
  uchar *out_c0 = 0;

  uchar *virtual_strings_start = 0;
  uchar *virtual_strings_end = 0;
  uchar *out_strings_start = 0;
  uchar *out_strings_end = 0;
  uchar *out_s = 0;

  #define STRINGS_START "STRINGS_START"
  #define STRINGS_END "STRINGS_END"

  unsigned int _i32 = 0;

  const char* id::i32() {
    if (virtual_adr) { _i32 = (size_t)virtual_adr;
         //printf("virtual_adr: %x\n", _i32);
        return (const char*)&_i32; }
    if (type == T_UINT) return (const char*)&d.ui;
    return (const char*)&d.i;
  }
  const char* id::i64() {
    if (type == T_ULONG) return (const char*)&d.ul;
    return (const char*)&d.l;
  }
  vector<const char*> type_str = { "0:???", "int", "uint", "long", "ulong",
      "charp", "float", "double"};

  void id::describe() {
    if (type > type_str.size() - 1) {
      cout << "<id:" << type << ">";
    } else {
      cout << type_str[type];
    }
    cout << endl;
  }
  id  id::operator()(id i) { add_parameter(i); return i; }

  id_new::id_new(const char *p) : id(p) {
    virtual_adr = virtual_strings_start + (out_s - out_strings_start);
    virtual_size = strlen(p);
    if (out_s + virtual_size + 1 > out_strings_end)
        throw exception("Strings: Out of memory");
    memcpy(out_s, p, virtual_size + 1);
    out_s += virtual_size + 1;
  };

  const char *reserved_strings[] = { STRINGS_START,
  M(ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc)
  STRINGS_END };

#define FIND(v) { \
  pos = 0; \
  bool found = false; \
  for (size_t i = 0; !found && i < (input_size - v##_s); i++) { \
    for (int j = 0; j < v##_s; j++) { \
      if (buf[i + j] != v[j]) break; \
      if (j == v##_s - 1) { \
        pos = i; \
        found = true; \
      } \
    } \
  } }

  uchar buf[200 * 1024];
  FILE* input = 0;
  size_t input_size = 0;

  void find_space(uchar* start, size_t start_s,
      uchar* end, size_t end_s, uchar **out_start, uchar **out_end) {
    if (!input) {
      input = fopen(command_file, "r");
      if (!input) { fprintf(stderr, "Failed\n"); }
      input_size = fread(buf, 1, sizeof(buf), input);
    }
    size_t pos = 0, s = 0, e = 0;
    FIND(start); s = pos;
    FIND(end); e = pos;
    *out_start = &buf[s];
    *out_end = &buf[e];
    //printf("s: %zd, e:%zd, l:%zd\n", s, e, e - s);
  }

  void write() {
    FILE *out = fopen("a.out", "w");
    fwrite(buf, 1, input_size, out);
    fclose(out);
    printf("Writing a.out\n");
    chmod("a.out", 0777);
  }

  void dump(uchar* start, size_t s) {
    for (size_t i = 0; i < s; i++) {
      printf("%02x ", start[i]);
    }
    //printf("\n");
  }

  int __offset = 0;
  const char* call_offset(uchar *out_current_code_pos, void *__virt_f) {
    auto virt_f = (uchar*)__virt_f;
    ssize_t out_start_distance = out_current_code_pos - out_code_start;
    ssize_t virt_dist_from_code_start = virt_f - virtual_code_start;
    __offset = virt_dist_from_code_start - out_start_distance - 5;
    cout << "__virt_f: " << __virt_f << endl;
    //cout << "call_offset: " << __offset << " virt: " << virt_dist_from_code_start << " out: " << out_start_distance << endl;
    return (const char*)&__offset;
  }

  const char* rip_relative_offset(uchar *out_current_code_pos,
      uchar *virt_adr) {
    ssize_t distance = out_current_code_pos - out_code_start;
    ssize_t virt_dist_from_code_start = (size_t)virt_adr -
        (size_t)virtual_code_start - distance;
    __offset = virt_dist_from_code_start - 7;
    printf("virt_dist_from_code_start: %zx %x, string ofs: %zd\n",
        (size_t)virt_adr, __offset,
        (size_t)(out_s - out_strings_start));
    return (const char*)&__offset;
  }

  int parameter_count = 0;
  const char *register_parameters_intel_32[] = {
      "\xbf", /*edi*/ "\xbe", /*esi*/ "\xba" /*edx*/ };

  const char *register_rip_relative_parameters_intel_64[] = {
    "\x48\x8d\x3d", /* rdi */ "\x48\x8d\x35", /* rsi */
    "\x48\x8d\x15" /* rdx */ };

  const char *register_parameters_arm_32[] = {
      "\xe5\x9f\x00", /*r0*/ "\xe5\x9f\x10", /*r1*/ "\xe5\x9f\x20" /*r2*/ };
  const char *register_parameters_intel_64[] = {
      "\x48\xbf" /*rdi*/, "\x48\xbe" ,/*rsi*/ "\x48\xba" /*rdx*/ };

  constexpr int parameters_max = 3;

  void emit(const char* _s, size_t _l = 0) {
    size_t l = _l > 0 ? _l : strlen(_s);
    uchar *s = (uchar *)_s; uchar *e = s + l;
    if (out_c + l > out_code_end) throw exception("Code: Out of memory");
    for (uchar * b  = s; b < e; b++, out_c++) {
      *out_c = *b;
    }
    dump(s, l);
  }

  bool intel() { return true; }

  id add_parameter(id p) {
    if (parameter_count >= parameters_max) {
      fprintf(stderr, "Too many parameters!\n");
      return p;
    }
    //cout << "parameter_count: " << parameter_count << " "; p.describe();
    if (p.is_charp()) {
      if (!am_i_pic) {
        emit(register_parameters_intel_32[parameter_count]);
        emit(p.i32(), 4);
      } else {
        uchar *out_current_code_pos = out_c;
        emit(register_rip_relative_parameters_intel_64[parameter_count]);
        emit(rip_relative_offset(out_current_code_pos, p.virtual_adr), 4);
      }
    } else if (p.is_integer()) {
      //cout << "is_integer" << endl;
      if (intel) {
        //cout << "intel" << endl;
        if (p.is_32()) {
          //cout << "is_32" << endl;
          emit(register_parameters_intel_32[parameter_count]);
          emit(p.i32(), 4);
        } else if (p.is_64()) {
          //cout << "is_64" << endl;
          emit(register_parameters_intel_64[parameter_count]);
          emit(p.i64(), 8);
        }
      } else if (arm) {
        emit(register_parameters_intel_32[parameter_count]);
      }
    }
    ++parameter_count;
    return p;
  }

  void jmp(void *f) {
    uchar *out_current_code_pos = out_c;
    emit("\xe9"); // JMP
    emit(call_offset(out_current_code_pos, f), 4);
  }

  void __call(void *f) {
    uchar *out_current_code_pos = out_c;
    emit("\xe8"); // call
    emit(call_offset(out_current_code_pos, f), 4);
    parameter_count = 0;
  }

  void __vararg_call(void *f) {
    emit("\x30\xc0"); // xor    al,al
    call(f);
  }

  size_t __p = 0;

  void f(const char *s, int i) {
    __p += (size_t)s + i;
  }

  void init(char *c, uchar *start, size_t ss, uchar *end, size_t es) {
    figure_out_cpu_architecture();
    am_i_pic = __am_i_pic();
    printf("am_i_pic: %d\n", am_i_pic);
    command_file = c;
    virtual_code_start = start;
    virtual_code_end = end;
    find_space(start, ss, end, es, &out_code_start,
        &out_code_end);
    //printf("code: %zu\n", out_code_end - out_code_start);
    virtual_strings_start = (uchar *)STRINGS_START;
    virtual_strings_end = (uchar *)STRINGS_END;
    out_c = out_code_start;
    find_space(virtual_strings_start, strlen(STRINGS_START),
        virtual_strings_end, strlen(STRINGS_END),
            &out_strings_start, &out_strings_end);
    //printf("strings: %zu\n", out_strings_end - out_strings_start);
    out_s = out_strings_start;
  }

  void finish() {
    jmp(virtual_code_end);
    write();
  }

}
<commit_msg>Check for intel.<commit_after>// symbiosis: A hacky and lightweight compiler framework
//
#include "symbiosis.hpp"
#include <sys/stat.h>

#include <iostream>

#include <vector>

using namespace std;

namespace symbiosis {

  void dump(uchar* start, size_t s) {
    for (size_t i = 0; i < s; i++) {
      printf("%02x ", start[i]);
    }
  }

  bool intel = false;
  bool arm = false;
  bool am_i_pic = false;

  void figure_out_cpu_architecture() {
    uchar *p = (uchar *)figure_out_cpu_architecture;
    cout << "CPU id: "; dump(p, 4);
    if (p[0] == 0x55 && p[1] == 0x48) { cout << "Intel" << endl;
        intel = true; return; }
    if (p[3] == 0xe9 || p[3] == 0xe5) { cout << "ARM" << endl;
        arm = true; return; }
    cout << "Unknown CPU id: "; dump(p, 4);
  }

  bool __am_i_pic() {
    uchar *p = (uchar *)__am_i_pic;
    int i = 0;
    uchar c = 0;
    do {
      c = p[i++];
    } while (i < 10 && c != 0x48 && c != 0xbf);
    return c == 0x48;
  }

  class exception : public std::exception {
    const char *what_;
  public:
    exception(const char *w) : what_(w) { }
    virtual ~exception() throw() { }
    virtual const char* what() const throw() { return what_; }
  };

  char *command_file = 0;;

  #define M10(v, b) #v #b
  #define M3(a,b) M10(a+1000, v),M10(a+2000, v), M10(a+3000, v),M10(a+4000, v)
  #define M2(a,b) M3(a+100, v) , M3(a+200, v) , M3(a+300, v) , M3(a+400, v)
  #define M1(a,b) M2(a+10, v) , M2(a+20, v) , M2(a+30, v) , M2(a+40, v)
  #define M(v) M1(1, v), M1(2, v), M1(3, v), M1(4, v), M1(5, v)

  uchar *virtual_code_start = 0;
  uchar *virtual_code_end = 0;

  uchar *out_code_start = 0;
  uchar *out_code_end = 0;
  uchar *out_c = 0;
  uchar *out_c0 = 0;

  uchar *virtual_strings_start = 0;
  uchar *virtual_strings_end = 0;
  uchar *out_strings_start = 0;
  uchar *out_strings_end = 0;
  uchar *out_s = 0;

  #define STRINGS_START "STRINGS_START"
  #define STRINGS_END "STRINGS_END"

  unsigned int _i32 = 0;

  const char* id::i32() {
    if (virtual_adr) { _i32 = (size_t)virtual_adr;
         //printf("virtual_adr: %x\n", _i32);
        return (const char*)&_i32; }
    if (type == T_UINT) return (const char*)&d.ui;
    return (const char*)&d.i;
  }
  const char* id::i64() {
    if (type == T_ULONG) return (const char*)&d.ul;
    return (const char*)&d.l;
  }
  vector<const char*> type_str = { "0:???", "int", "uint", "long", "ulong",
      "charp", "float", "double"};

  void id::describe() {
    if (type > type_str.size() - 1) {
      cout << "<id:" << type << ">";
    } else {
      cout << type_str[type];
    }
    cout << endl;
  }
  id  id::operator()(id i) { add_parameter(i); return i; }

  id_new::id_new(const char *p) : id(p) {
    virtual_adr = virtual_strings_start + (out_s - out_strings_start);
    virtual_size = strlen(p);
    if (out_s + virtual_size + 1 > out_strings_end)
        throw exception("Strings: Out of memory");
    memcpy(out_s, p, virtual_size + 1);
    out_s += virtual_size + 1;
  };

  const char *reserved_strings[] = { STRINGS_START,
  M(ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc)
  STRINGS_END };

#define FIND(v) { \
  pos = 0; \
  bool found = false; \
  for (size_t i = 0; !found && i < (input_size - v##_s); i++) { \
    for (int j = 0; j < v##_s; j++) { \
      if (buf[i + j] != v[j]) break; \
      if (j == v##_s - 1) { \
        pos = i; \
        found = true; \
      } \
    } \
  } }

  uchar buf[200 * 1024];
  FILE* input = 0;
  size_t input_size = 0;

  void find_space(uchar* start, size_t start_s,
      uchar* end, size_t end_s, uchar **out_start, uchar **out_end) {
    if (!input) {
      input = fopen(command_file, "r");
      if (!input) { fprintf(stderr, "Failed\n"); }
      input_size = fread(buf, 1, sizeof(buf), input);
    }
    size_t pos = 0, s = 0, e = 0;
    FIND(start); s = pos;
    FIND(end); e = pos;
    *out_start = &buf[s];
    *out_end = &buf[e];
    //printf("s: %zd, e:%zd, l:%zd\n", s, e, e - s);
  }

  void write() {
    FILE *out = fopen("a.out", "w");
    fwrite(buf, 1, input_size, out);
    fclose(out);
    printf("Writing a.out\n");
    chmod("a.out", 0777);
  }

  int __offset = 0;
  const char* call_offset(uchar *out_current_code_pos, void *__virt_f) {
    auto virt_f = (uchar*)__virt_f;
    ssize_t out_start_distance = out_current_code_pos - out_code_start;
    ssize_t virt_dist_from_code_start = virt_f - virtual_code_start;
    __offset = virt_dist_from_code_start - out_start_distance - 5;
    cout << "__virt_f: " << __virt_f << endl;
    //cout << "call_offset: " << __offset << " virt: " << virt_dist_from_code_start << " out: " << out_start_distance << endl;
    return (const char*)&__offset;
  }

  const char* rip_relative_offset(uchar *out_current_code_pos,
      uchar *virt_adr) {
    ssize_t distance = out_current_code_pos - out_code_start;
    ssize_t virt_dist_from_code_start = (size_t)virt_adr -
        (size_t)virtual_code_start - distance;
    __offset = virt_dist_from_code_start - 7;
    printf("virt_dist_from_code_start: %zx %x, string ofs: %zd\n",
        (size_t)virt_adr, __offset,
        (size_t)(out_s - out_strings_start));
    return (const char*)&__offset;
  }

  int parameter_count = 0;
  const char *register_parameters_intel_32[] = {
      "\xbf", /*edi*/ "\xbe", /*esi*/ "\xba" /*edx*/ };

  const char *register_rip_relative_parameters_intel_64[] = {
    "\x48\x8d\x3d", /* rdi */ "\x48\x8d\x35", /* rsi */
    "\x48\x8d\x15" /* rdx */ };

  const char *register_parameters_arm_32[] = {
      "\xe5\x9f\x00", /*r0*/ "\xe5\x9f\x10", /*r1*/ "\xe5\x9f\x20" /*r2*/ };
  const char *register_parameters_intel_64[] = {
      "\x48\xbf" /*rdi*/, "\x48\xbe" ,/*rsi*/ "\x48\xba" /*rdx*/ };

  constexpr int parameters_max = 3;

  void emit(const char* _s, size_t _l = 0) {
    size_t l = _l > 0 ? _l : strlen(_s);
    uchar *s = (uchar *)_s; uchar *e = s + l;
    if (out_c + l > out_code_end) throw exception("Code: Out of memory");
    for (uchar * b  = s; b < e; b++, out_c++) {
      *out_c = *b;
    }
    dump(s, l);
  }

  id add_parameter(id p) {
    if (parameter_count >= parameters_max) {
      fprintf(stderr, "Too many parameters!\n");
      return p;
    }
    //cout << "parameter_count: " << parameter_count << " "; p.describe();
    if (p.is_charp()) {
      if (!am_i_pic) {
        emit(register_parameters_intel_32[parameter_count]);
        emit(p.i32(), 4);
      } else {
        uchar *out_current_code_pos = out_c;
        emit(register_rip_relative_parameters_intel_64[parameter_count]);
        emit(rip_relative_offset(out_current_code_pos, p.virtual_adr), 4);
      }
    } else if (p.is_integer()) {
      //cout << "is_integer" << endl;
      if (intel) {
        //cout << "intel" << endl;
        if (p.is_32()) {
          //cout << "is_32" << endl;
          emit(register_parameters_intel_32[parameter_count]);
          emit(p.i32(), 4);
        } else if (p.is_64()) {
          //cout << "is_64" << endl;
          emit(register_parameters_intel_64[parameter_count]);
          emit(p.i64(), 8);
        }
      } else if (arm) {
        emit(register_parameters_intel_32[parameter_count]);
      }
    }
    ++parameter_count;
    return p;
  }

  void jmp(void *f) {
    uchar *out_current_code_pos = out_c;
    emit("\xe9"); // JMP
    emit(call_offset(out_current_code_pos, f), 4);
  }

  void __call(void *f) {
    uchar *out_current_code_pos = out_c;
    emit("\xe8"); // call
    emit(call_offset(out_current_code_pos, f), 4);
    parameter_count = 0;
  }

  void __vararg_call(void *f) {
    emit("\x30\xc0"); // xor    al,al
    call(f);
  }

  size_t __p = 0;

  void f(const char *s, int i) {
    __p += (size_t)s + i;
  }

  void init(char *c, uchar *start, size_t ss, uchar *end, size_t es) {
    figure_out_cpu_architecture();
    am_i_pic = __am_i_pic();
    printf("am_i_pic: %d\n", am_i_pic);
    command_file = c;
    virtual_code_start = start;
    virtual_code_end = end;
    find_space(start, ss, end, es, &out_code_start,
        &out_code_end);
    //printf("code: %zu\n", out_code_end - out_code_start);
    virtual_strings_start = (uchar *)STRINGS_START;
    virtual_strings_end = (uchar *)STRINGS_END;
    out_c = out_code_start;
    find_space(virtual_strings_start, strlen(STRINGS_START),
        virtual_strings_end, strlen(STRINGS_END),
            &out_strings_start, &out_strings_end);
    //printf("strings: %zu\n", out_strings_end - out_strings_start);
    out_s = out_strings_start;
  }

  void finish() {
    jmp(virtual_code_end);
    write();
  }

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "endpoint_resolver.h"
#include "client_http.h"

#include <unistd.h>

EndpointList::EndpointList()
	: status(ST_NEW),
	  max_mastery_level(0),
	  init_timeout(0.005)
{
	pthread_cond_init(&time_cond, 0);
	pthread_mutexattr_init(&endl_qmtx_attr);
	pthread_mutexattr_settype(&endl_qmtx_attr, PTHREAD_MUTEX_RECURSIVE);
	pthread_mutex_init(&endl_qmtx, &endl_qmtx_attr);
}

EndpointList::~EndpointList()
{
	pthread_mutex_destroy(&endl_qmtx);
	pthread_mutexattr_destroy(&endl_qmtx_attr);
	pthread_cond_destroy(&time_cond);
}

void EndpointList::add_endpoint(const Endpoint &element) {
	pthread_mutex_lock(&endl_qmtx);

	clock_gettime(CLOCK_REALTIME, &last_recv);

	endp_set.insert(element);

	int factor = 3;
	if (element.mastery_level > max_mastery_level) {
		max_mastery_level = element.mastery_level;
		factor = 2;
	}

	next_wake = init_time + (last_recv - init_time);

	pthread_mutex_unlock(&endl_qmtx);

	pthread_cond_broadcast(&time_cond);
}

bool EndpointList::resolve_endpoint(const std::string &path, XapiandManager *manager, std::vector<Endpoint> &endpv, int n_endps, double timeout) {
	int initial_status, retval;
	double elapsed;

	pthread_mutex_lock(&endl_qmtx);

	initial_status = status;

	if (initial_status == ST_NEW) {
		elapsed = timeout;
	} else {
		clock_gettime(CLOCK_REALTIME, &current_time);
		elapsed = timespec_to_double(&current_time) - timespec_to_double(&init_time);

		if (elapsed > timeout && endp_set.empty()) {
			initial_status = ST_NEW;
			elapsed = timeout;
		} else if (elapsed > timeout * 10 && endp_set.size() < n_endps) {
			initial_status = ST_NEW;
			elapsed = timeout;
		} else if (elapsed > 3600.0) {
			manager->discovery(DISCOVERY_DB, serialise_string(path));
		}
	}

	while (elapsed <= timeout) {
		switch (initial_status) {
			case ST_NEW:
				clock_gettime(CLOCK_REALTIME, &init_time);

				manager->discovery(DISCOVERY_DB, serialise_string(path));

				next_wake = init_time + init_timeout;

				status = initial_status = ST_WAITING;

			case ST_WAITING:
				retval = pthread_cond_timedwait(&time_cond, &endl_qmtx, &next_wake);
				if (retval == ETIMEDOUT) {
					clock_gettime(CLOCK_REALTIME, &current_time);
					elapsed = timespec_to_double(&current_time) - timespec_to_double(&init_time);

					if (elapsed < timeout) {
						if (endp_set.size() < n_endps) {
							elapsed *= 3.0;
							if (elapsed >= timeout) {
								elapsed = timeout;
							}
							next_wake = init_time + elapsed;
						} else {
							elapsed = timeout + 1; // force it out
						}
					}
				} else if (retval) {
					LOG_ERR(this, "ERROR: pthread_cond_timedwait: %s\n", strerror(retval));
				}
				break;
		}
	}

	if (endp_set.empty()) {
		pthread_mutex_unlock(&endl_qmtx);
		return false;
	}

	bool ret = _get_endpoints(endpv, n_endps);

	pthread_mutex_unlock(&endl_qmtx);

	return ret;
}

bool EndpointList::_get_endpoints(std::vector<Endpoint> &Endv, int n_endps) {
	int c;
	std::set<Endpoint, Endpoint::compare>::const_iterator it_endp = endp_set.cbegin();
	for (c = 1; c <= n_endps && it_endp != endp_set.cend(); it_endp++) {
		Endv.push_back(*it_endp);
	}
	return c == n_endps;
}

size_t EndpointList::size() {
	return endp_set.size();
}

bool EndpointList::empty() {
	return endp_set.empty();
}

void EndpointList::show_list()
{
	pthread_mutex_lock(&endl_qmtx);
	std::set<Endpoint, Endpoint::compare>::iterator it;
	for (it = endp_set.begin(); it != endp_set.end(); it++) {
		LOG(this,"Endpoint list: --%s--\n",(*it).host.c_str());
	}
	pthread_mutex_unlock(&endl_qmtx);
}

void EndpointResolver::add_index_endpoint(Endpoint index)
{
	pthread_mutex_lock(&re_qmtx);
	EndpointList &enl = (*this)[index.path];
	pthread_mutex_unlock(&re_qmtx);

	enl.add_endpoint(index);
}

bool EndpointResolver::resolve_index_endpoint(const std::string &path, XapiandManager *manager, std::vector<Endpoint> &endpv, int n_endps, double timeout)
{
	pthread_mutex_lock(&re_qmtx);
	EndpointList &enl = (*this)[path];
	pthread_mutex_unlock(&re_qmtx);

	return enl.resolve_endpoint(path, manager, endpv, n_endps, timeout);
}
<commit_msg>Don't use intermediate doubles for time calculations<commit_after>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "endpoint_resolver.h"
#include "client_http.h"

#include <unistd.h>

EndpointList::EndpointList()
	: status(ST_NEW),
	  max_mastery_level(0),
	  init_timeout(0.005)
{
	pthread_cond_init(&time_cond, 0);
	pthread_mutexattr_init(&endl_qmtx_attr);
	pthread_mutexattr_settype(&endl_qmtx_attr, PTHREAD_MUTEX_RECURSIVE);
	pthread_mutex_init(&endl_qmtx, &endl_qmtx_attr);
}

EndpointList::~EndpointList()
{
	pthread_mutex_destroy(&endl_qmtx);
	pthread_mutexattr_destroy(&endl_qmtx_attr);
	pthread_cond_destroy(&time_cond);
}

void EndpointList::add_endpoint(const Endpoint &element) {
	pthread_mutex_lock(&endl_qmtx);

	last_recv = now();

	endp_set.insert(element);

	double factor = 3.0;
	if (element.mastery_level > max_mastery_level) {
		max_mastery_level = element.mastery_level;
		factor = 2.0;
	}

	timespec_t elapsed = last_recv - init_time;
	next_wake = init_time + elapsed * factor;

	pthread_mutex_unlock(&endl_qmtx);

	pthread_cond_broadcast(&time_cond);
}

bool EndpointList::resolve_endpoint(const std::string &path, XapiandManager *manager, std::vector<Endpoint> &endpv, int n_endps, double timeout) {
	int initial_status, retval;
	timespec_t elapsed;

	pthread_mutex_lock(&endl_qmtx);

	initial_status = status;

	if (initial_status == ST_NEW) {
		elapsed = timeout;
	} else {
		elapsed = now() - init_time;

		if (elapsed > timeout && endp_set.empty()) {
			initial_status = ST_NEW;
			elapsed = timeout;
		} else if (elapsed > timeout * 10 && endp_set.size() < n_endps) {
			initial_status = ST_NEW;
			elapsed = timeout;
		} else if (elapsed > 3600.0) {
			manager->discovery(DISCOVERY_DB, serialise_string(path));
		}
	}

	while (elapsed <= timeout) {
		switch (initial_status) {
			case ST_NEW:
				clock_gettime(CLOCK_REALTIME, &init_time);

				manager->discovery(DISCOVERY_DB, serialise_string(path));

				next_wake = init_time + init_timeout;

				status = initial_status = ST_WAITING;

			case ST_WAITING:
				retval = pthread_cond_timedwait(&time_cond, &endl_qmtx, &next_wake);
				if (retval == ETIMEDOUT) {
					elapsed = now() - init_time;

					if (elapsed < timeout) {
						if (endp_set.size() < n_endps) {
							elapsed *= 3.0;
							if (elapsed >= timeout) {
								elapsed = timeout;
							}
							next_wake = init_time + elapsed;
						} else {
							elapsed = timeout + 1; // force it out
						}
					}
				} else if (retval) {
					LOG_ERR(this, "ERROR: pthread_cond_timedwait: %s\n", strerror(retval));
				}
				break;
		}
	}

	if (endp_set.empty()) {
		pthread_mutex_unlock(&endl_qmtx);
		return false;
	}

	bool ret = _get_endpoints(endpv, n_endps);

	pthread_mutex_unlock(&endl_qmtx);

	return ret;
}

bool EndpointList::_get_endpoints(std::vector<Endpoint> &Endv, int n_endps) {
	int c;
	std::set<Endpoint, Endpoint::compare>::const_iterator it_endp = endp_set.cbegin();
	for (c = 1; c <= n_endps && it_endp != endp_set.cend(); it_endp++) {
		Endv.push_back(*it_endp);
	}
	return c == n_endps;
}

size_t EndpointList::size() {
	return endp_set.size();
}

bool EndpointList::empty() {
	return endp_set.empty();
}

void EndpointList::show_list()
{
	pthread_mutex_lock(&endl_qmtx);
	std::set<Endpoint, Endpoint::compare>::iterator it;
	for (it = endp_set.begin(); it != endp_set.end(); it++) {
		LOG(this,"Endpoint list: --%s--\n",(*it).host.c_str());
	}
	pthread_mutex_unlock(&endl_qmtx);
}

void EndpointResolver::add_index_endpoint(Endpoint index)
{
	pthread_mutex_lock(&re_qmtx);
	EndpointList &enl = (*this)[index.path];
	pthread_mutex_unlock(&re_qmtx);

	enl.add_endpoint(index);
}

bool EndpointResolver::resolve_index_endpoint(const std::string &path, XapiandManager *manager, std::vector<Endpoint> &endpv, int n_endps, double timeout)
{
	pthread_mutex_lock(&re_qmtx);
	EndpointList &enl = (*this)[path];
	pthread_mutex_unlock(&re_qmtx);

	return enl.resolve_endpoint(path, manager, endpv, n_endps, timeout);
}
<|endoftext|>


<commit_before>#include "power_tortuga.h"

PowerNodeTortuga::PowerNodeTortuga(std::shared_ptr<ros::NodeHandle> n, int rate, int board_fd, std::string board_file):
  SensorBoardTortugaNode(n, rate, board_fd, board_file) {
    for ( int i = 0; i < 6; i ++ ) {
      publisher[i] = n->advertise<ram_msgs::PowerSource>(("tortuga/power_source/" + i), 1000);
    }
}

PowerNodeTortuga::~PowerNodeTortuga() {}

void PowerNodeTortuga::update() {
  checkError(readBatteryVoltages(fd, &info));
  checkError(readBatteryCurrents(fd, &info));

  /* This doesn't return an error code, it bitmasks part of readStatus()
    Not sure which battery this actually is, so for now I'm just setting all them to this value
  */
  int life = readBatteryUsage(fd);
  for ( int i = 0; i < 6; i++ ) {
    msg.voltage = info.battVoltages[i];
    msg.current = info.battCurrents[i];
    msg.life = life;
    publisher[i].publish(msg);
  }
  ros::spinOnce();

}
<commit_msg>power topics messed up<commit_after>#include "power_tortuga.h"

PowerNodeTortuga::PowerNodeTortuga(std::shared_ptr<ros::NodeHandle> n, int rate, int board_fd, std::string board_file):
  SensorBoardTortugaNode(n, rate, board_fd, board_file) {
    for ( int i = 0; i < 6; i ++ ) {
      publisher[i] = n->advertise<ram_msgs::PowerSource>(("tortuga/power_source/" + i), 1000);
    }
}

PowerNodeTortuga::~PowerNodeTortuga() {}

void PowerNodeTortuga::update() {
	checkError(readBatteryVoltages(fd, &info));
	checkError(readBatteryCurrents(fd, &info));

	/* This doesn't return an error code, it bitmasks part of readStatus()
	Not sure which battery this actually is, so for now I'm just setting all them to this value
  */
	int life = readBatteryUsage(fd);
	for ( int i = 0; i < 6; i++ ) {
		msg.voltage = info.battVoltages[i];
		msg.current = info.battCurrents[i];
		msg.life = life;
		publisher[i].publish(msg);
	}
	ros::spinOnce();

}
<|endoftext|>


<commit_before>#include "GameView.h"
#include <imgui/imgui.h>
#include <iostream>
GameView::GameView() {

}

GameView::~GameView() {}

void GameView::draw() {
    static bool show_game_view = true;
    if(show_game_view) {
        float rapport = (float)renderTexture->getWidth()/(float)renderTexture->getHeight();
        //std::cout << rapport << std::endl;
        float scale = 500;
        ImGui::SetNextWindowSize(ImVec2(rapport*scale, scale));
        ImGui::Begin("Game View", &show_game_view );
        fm::Texture texture = renderTexture->getColorBuffer()[0];
        ImGui::Image((void*)texture.getID(), ImGui::GetWindowSize(), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
        ImGui::End();
    }

}

void GameView::resize() {}
void GameView::zoom() {}
<commit_msg>Kid way<commit_after>#include "GameView.h"
#include <imgui/imgui.h>
GameView::GameView() {

}

GameView::~GameView() {}

void GameView::draw() {
    static bool show_game_view = true;
    if(show_game_view) {
        float rapport = (float)renderTexture->getWidth()/(float)renderTexture->getHeight();

        float scale = 500;
        ImGui::SetNextWindowSize(ImVec2(rapport*scale, scale));
        ImGui::Begin("Game View", &show_game_view,ImGuiWindowFlags_NoScrollbar );
        fm::Texture texture = renderTexture->getColorBuffer()[0];

        ImVec2 pos = ImGui::GetWindowPos();
        pos.y += 10;
        ImVec2 end;
        end.x = pos.x + ImGui::GetWindowSize().x;
        end.y = pos.y + ImGui::GetWindowSize().y;

        ImGui::GetWindowDrawList()->AddImage((void*)texture.getID(),ImGui::GetWindowPos(), end);

        //ImGui::Image((void*)texture.getID(), ImGui::GetWindowSize(), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
        ImGui::End();
    }

}

void GameView::resize() {}
void GameView::zoom() {}
<|endoftext|>


<commit_before>#include "SdlWindow.hpp"

#include <sstream>
#include <cassert>

#if defined(BLOWTORCH_DEBUG_MODE)
#include "graphics/GlUtils.hpp"
#endif // defined

/**
 * @brief SdlWindow::SdlWindow
 * @param title
 * @param width = 800u
 * @param height = 600u
 */
SdlWindow::SdlWindow(const char* title, const unsigned int width, const unsigned int height)
: mTitle(title)
, mOpenGlContext(SDL_GL_CONTEXT_PROFILE_CORE)
, mLogPriority(SDL_LOG_PRIORITY_VERBOSE)
{
    SDL_LogSetAllPriority(mLogPriority);

    initWindow(sInitFlags, width, height);

    if (sInitFlags & SDL_INIT_JOYSTICK)
        initJoysticks();
    if (sInitFlags & SDL_INIT_HAPTIC)
        initHaptic();

    // Only load OpenGL functions after a Gl Context is created
    loadGl();

    if (sSamples > 1)
    {
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, sSamples);
        glEnable(GL_MULTISAMPLE);
    }

#if defined(BLOWTORCH_DEBUG_MODE)
       glEnable(GL_DEBUG_OUTPUT);
       glDebugMessageCallback(GlUtils::GlDebugCallback, nullptr);
       glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr, GL_TRUE);
       glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION,
           GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_MEDIUM,
           GL_DEBUG_SEVERITY_MEDIUM, -1, "Start debugging");
#endif // defined
}

SdlWindow::~SdlWindow()
{
    if (mSdlWindow != nullptr)
        cleanUp();
}

SdlWindow::SdlWindow(const SdlWindow& other)
{

}

SdlWindow& SdlWindow::operator=(const SdlWindow& other)
{

}

/**
 * @brief SdlWindow::cleanUp
 */
void SdlWindow::cleanUp()
{
    destroyWindow();
    SDL_Quit();
}

/**
 * @brief SdlWindow::initWindow
 * @param flags
 */
void SdlWindow::initWindow(Uint32 flags, unsigned int width, unsigned int height)
{
    if (SDL_Init(flags) < 0)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, SDL_GetError());
        throw new std::runtime_error("Could not intialize Sdl");
    }

    // Set up the GL attributes
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, sRedBufferSize);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, sGreenBufferSize);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, sBlueBufferSize);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, sAlphaBufferSize);

    SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, sBufferSize);

    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, sDepthBufferSize);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, sStencilBufferSize);

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, mOpenGlContext);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, sOpenGlMajor);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, sOpenGlMinor);

#if defined(APP_DESKTOP)
    if (sFullscreen)
    {
        SDL_DisplayMode mode;
        SDL_GetDisplayMode(0, 0, &mode);
        mSdlWindow = SDL_CreateWindow(nullptr, 0, 0, mode.w, mode.h, sWinFlags);
    }
    else
    {
        mSdlWindow = SDL_CreateWindow(mTitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, sWinFlags);
    }
#elif defined(APP_ANDROID)
    SDL_DisplayMode mode;
    SDL_GetDisplayMode(0, 0, &mode);
    mSdlWindow = SDL_CreateWindow(nullptr, 0, 0, mode.w, mode.h, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN);
#endif // defined

    if (mSdlWindow == 0)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, SDL_GetError());
        throw new std::runtime_error("Sdl Window did not create!\n");
    }

    mGlContext = SDL_GL_CreateContext(mSdlWindow);

    // Sometimes Vsync is enabled by default
    if (sVSync && SDL_GL_SetSwapInterval(1) < 0)
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Vsync mode is not available\n");
    else
        SDL_GL_SetSwapInterval(0);
}

void SdlWindow::initJoysticks()
{
    // setup joystick
    mSdlJoystick = SDL_JoystickOpen(0);
    if (!mSdlJoystick)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Joystick 0 did not initialize\n");
    }
}

void SdlWindow::initHaptic()
{
    mSdlHaptic = SDL_HapticOpenFromJoystick(mSdlJoystick);
    if (!mSdlHaptic)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "This controller does not support haptic feedback\n");
    }
    else
    {
        if (SDL_HapticRumbleInit(mSdlHaptic) < 0)
        {
            SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL haptic did not initialize the rumble\n");
        }
    }
}

/**
 * @brief SdlWindow::destroyWindow
 */
void SdlWindow::destroyWindow()
{
    SDL_GL_DeleteContext(mGlContext);
    SDL_DestroyWindow(mSdlWindow);
}

/**
 * Only loads on desktop since mobile uses OpenGL ES
 * @brief SdlWindow::loadGl
 */
void SdlWindow::loadGl()
{
#if defined(APP_DESKTOP)
    // Load the OpenGL functions (glLoadGen).
    if (ogl_LoadFunctions() == ogl_LOAD_FAILED)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Error loading glLoadGen");
        cleanUp();
        throw new std::runtime_error("Could not load OpenGL functions\n");
    }
#endif // defined
}

/**
 * @brief SdlWindow::getSdlInfoString
 * @return
 */
std::string SdlWindow::getSdlInfoString() const
{
    int context, major, minor;
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &context);
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);

    int multisamples;
    SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &multisamples);

    assert(major == sOpenGlMajor);
    assert(minor == sOpenGlMinor);
    //assert(multisamples == mSamples);

    std::stringstream ss;
    ss << "\nPrinting SdlWindow info:\n";
    ss << "\nWindow Title: " << mTitle << "\n";
    ss << "Vsync: " << sVSync << "\n";
    ss << "Fullscreen: " << sFullscreen << "\n";
    ss << "Window (width, height): " << "(" << getWindowWidth() << ", " << getWindowHeight() << ")\n";
    ss << "The number of connected joysticks: " << SDL_NumJoysticks() << "\n";
    ss << "The GL context is : " << getContextString(context) << "\n";
    ss << "Major, Minor versions: " << major << ", " << minor << "\n";
    return ss.str();
}

/**
 * @brief SdlWindow::getGlInfoString
 * @return
 */
std::string SdlWindow::getGlInfoString() const
{
    const GLubyte* renderer = glGetString(GL_RENDERER);
    const GLubyte* vendor = glGetString(GL_VENDOR);
    const GLubyte* version = glGetString(GL_VERSION);
    const GLubyte* glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);

    GLint major, minor;
    glGetIntegerv(GL_MAJOR_VERSION, &major);
    glGetIntegerv(GL_MINOR_VERSION, &minor);

    std::stringstream ss;
    ss << "\n-------------------------------------------------------------\n";
    ss << "GL Vendor:\t\t\t" << vendor;
    ss << "\nGL GLRenderer:\t\t\t" << renderer;
    ss << "\nGL Version:\t\t\t" << version;
    ss << "\nGL Major, Minor:\t\t\t" << major << "." << minor;
    ss << "\nGLSL Version:\t\t\t" << glslVersion;
    ss << "\n-------------------------------------------------------------\n";
    return ss.str();
}

/**
 * @brief SdlWindow::swapBuffers
 */
void SdlWindow::swapBuffers() const
{
    SDL_GL_SwapWindow(mSdlWindow);
}

/**
 * @brief SdlWindow::hapticRumblePlay
 * @param strength
 * @param length
 * @return
 */
bool SdlWindow::hapticRumblePlay(float strength, float length) const
{
    return static_cast<bool>(SDL_HapticRumblePlay(mSdlHaptic, strength, length));
}

/**
 * @brief SdlWindow::buildBufferFromFile
 * @param filename
 * @param bufferSize
 * @return the buffer
 */
unsigned char* SdlWindow::buildBufferFromFile(const std::string& filename, long& bufferSize) const
{
    SDL_RWops* rwOps = SDL_RWFromFile(filename.c_str(), "rb");

    if (rwOps)
    {
        long fileSize = SDL_RWsize(rwOps);
        unsigned char* result = static_cast<unsigned char*>(malloc(fileSize + 1));
        long numberReadTotal = 0;
        long numberRead = 1;

        unsigned char* buffer = result;

        while (numberRead < fileSize && numberRead != 0)
        {
            numberRead = SDL_RWread(rwOps, buffer, 1, (fileSize - numberReadTotal));
            numberReadTotal += numberRead;
            buffer += numberRead;
        }

        SDL_RWclose(rwOps);

        if (numberReadTotal != fileSize)
        {
            free(result);
        }

        result[numberReadTotal] = '\0';

        bufferSize = fileSize;

        return result;
    }
    else
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, SDL_GetError());
        return nullptr;
    }
}

/**
 * @brief SdlWindow::buildStringFromFile
 * @param filename
 * @return
 */
std::string SdlWindow::buildStringFromFile(const std::string& filename) const
{
    std::string returnStr;
    SDL_RWops* rwOps = SDL_RWFromFile(filename.c_str(), "r");

    if (rwOps)
    {
        long fileSize = SDL_RWsize(rwOps);
        char* result = static_cast<char*>(malloc(fileSize + 1));
        long numberReadTotal = 0;
        long numberRead = 1;

        char* buffer = result;

        while (numberRead < fileSize && numberRead != 0)
        {
            numberRead = SDL_RWread(rwOps, buffer, 1, (fileSize - numberReadTotal));
            numberReadTotal += numberRead;
            buffer += numberRead;
        }

        SDL_RWclose(rwOps);

        if (numberReadTotal != fileSize)
        {
            free(result);
        }

        result[numberReadTotal] = '\0';

        returnStr.assign(result, fileSize);
        free(result);
    }
    else
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, SDL_GetError());
    }

    return returnStr;
}

/**
 * @brief SdlWindow::isFullScreen
 * @return
 */
bool SdlWindow::isFullScreen() const
{
    return sFullscreen;
}

/**
 * @brief SdlWindow::getWindowHeight
 * @return
 */
int SdlWindow::getWindowHeight() const
{
    int x, y;
    SDL_GetWindowSize(mSdlWindow, &x, &y);
    return y;
}

/**
 * @brief SdlWindow::getWindowWidth
 * @return
 */
int SdlWindow::getWindowWidth() const
{
    int x, y;
    SDL_GetWindowSize(mSdlWindow, &x, &y);
    return x;
}

/**
 * @brief SdlWindow::getAspectRatio
 * @return
 */
float SdlWindow::getAspectRatio() const
{
    int x, y;
    SDL_GetWindowSize(mSdlWindow, &x, &y);
    return static_cast<float>(x) / static_cast<float>(y);
}

/**
 * @brief SdlWindow::getSdlWindow
 * @return
 */
SDL_Window* SdlWindow::getSdlWindow() const
{
    return mSdlWindow;
}

/**
 * @return
 */
Uint32 SdlWindow::getInitFlags() const
{
    return sInitFlags;
}

/**
 * priv
 * @brief SdlWindow::getContextString
 * @param context
 * @return
 */
std::string SdlWindow::getContextString(int context) const
{
    switch (context)
    {
        case SDL_GL_CONTEXT_PROFILE_CORE: return "Core GL Context";
        case SDL_GL_CONTEXT_PROFILE_ES: return "ES GL Context";
        case SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG: return "Forward GL Context";
        //case SDL_GL_CONTEXT_DEBUG_FLAG: return "Debug GL Context";
        default: return "Unknown GL context";
    }
}
<commit_msg>Update SdlWindow.cpp<commit_after>#include "SdlWindow.hpp"

#include <sstream>
#include <cassert>

#if defined(BLOWTORCH_DEBUG_MODE)
#include "graphics/GlUtils.hpp"
#endif // defined

/**
 * @brief SdlWindow::SdlWindow
 * @param title
 * @param width = 800u
 * @param height = 600u
 */
SdlWindow::SdlWindow(const char* title, const unsigned int width, const unsigned int height)
: mTitle(title)
, mOpenGlContext(SDL_GL_CONTEXT_PROFILE_CORE)
, mLogPriority(SDL_LOG_PRIORITY_VERBOSE)
{
    SDL_LogSetAllPriority(mLogPriority);

    initWindow(sInitFlags, width, height);

    if (sInitFlags & SDL_INIT_JOYSTICK)
        initJoysticks();
    if (sInitFlags & SDL_INIT_HAPTIC)
        initHaptic();

    // Only load OpenGL functions after a Gl Context is created
    loadGl();

    if (sSamples > 1)
    {
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, sSamples);
        glEnable(GL_MULTISAMPLE);
    }

#if defined(BLOWTORCH_DEBUG_MODE)
       glEnable(GL_DEBUG_OUTPUT);
       glDebugMessageCallback(GlUtils::GlDebugCallback, nullptr);
       glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr, GL_TRUE);
       glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION,
           GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_MEDIUM,
           GL_DEBUG_SEVERITY_MEDIUM, -1, "Start debugging");
#endif // defined
}

SdlWindow::~SdlWindow()
{
    if (mSdlWindow != nullptr)
        cleanUp();
}

SdlWindow::SdlWindow(const SdlWindow& other)
{

}

SdlWindow& SdlWindow::operator=(const SdlWindow& other)
{

}

/**
 * @brief SdlWindow::cleanUp
 */
void SdlWindow::cleanUp()
{
    destroyWindow();
    SDL_Quit();
}

/**
 * @brief SdlWindow::initWindow
 * @param flags
 */
void SdlWindow::initWindow(Uint32 flags, unsigned int width, unsigned int height)
{
    if (SDL_Init(flags) < 0)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, SDL_GetError());
        throw new std::runtime_error("Could not intialize Sdl");
    }

    // Set up the GL attributes
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, sRedBufferSize);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, sGreenBufferSize);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, sBlueBufferSize);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, sAlphaBufferSize);

    SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, sBufferSize);

    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, sDepthBufferSize);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, sStencilBufferSize);

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, mOpenGlContext);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, sOpenGlMajor);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, sOpenGlMinor);

#if defined(APP_DESKTOP)
    if (sFullscreen)
    {
        SDL_DisplayMode mode;
        SDL_GetDisplayMode(0, 0, &mode);
        mSdlWindow = SDL_CreateWindow(nullptr, 0, 0, mode.w, mode.h, sWinFlags);
    }
    else
    {
        mSdlWindow = SDL_CreateWindow(mTitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, sWinFlags);
    }
#elif defined(APP_ANDROID)
    SDL_DisplayMode mode;
    SDL_GetDisplayMode(0, 0, &mode);
    mSdlWindow = SDL_CreateWindow(nullptr, 0, 0, mode.w, mode.h, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN);
#endif // defined

    if (mSdlWindow == 0)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, SDL_GetError());
        throw new std::runtime_error("Sdl Window did not create!\n");
    }

    mGlContext = SDL_GL_CreateContext(mSdlWindow);

    // Sometimes Vsync is enabled by default
    if (sVSync && SDL_GL_SetSwapInterval(1) < 0)
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Vsync mode is not available\n");
    else
        SDL_GL_SetSwapInterval(0);
}

void SdlWindow::initJoysticks()
{
    // setup joystick
    mSdlJoystick = SDL_JoystickOpen(0);
    if (!mSdlJoystick)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Joystick 0 did not initialize\n");
    }
}

void SdlWindow::initHaptic()
{
    mSdlHaptic = SDL_HapticOpenFromJoystick(mSdlJoystick);
    if (!mSdlHaptic)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "This controller does not support haptic feedback\n");
    }
    else
    {
        if (SDL_HapticRumbleInit(mSdlHaptic) < 0)
        {
            SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL haptic did not initialize the rumble\n");
        }
    }
}

/**
 * @brief SdlWindow::destroyWindow
 */
void SdlWindow::destroyWindow()
{
    SDL_GL_DeleteContext(mGlContext);
    SDL_DestroyWindow(mSdlWindow);
}

/**
 * Only loads on desktop since mobile uses OpenGL ES
 * @brief SdlWindow::loadGl
 */
void SdlWindow::loadGl()
{
#if defined(APP_DESKTOP)
    // Load the OpenGL functions (glLoadGen).
    if (ogl_LoadFunctions() == ogl_LOAD_FAILED)
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Error loading glLoadGen");
        SDL_Quit();
        throw new std::runtime_error("Could not load OpenGL functions\n");
    }
#endif // defined
}

/**
 * @brief SdlWindow::getSdlInfoString
 * @return
 */
std::string SdlWindow::getSdlInfoString() const
{
    int context, major, minor;
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &context);
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);

    int multisamples;
    SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &multisamples);

    assert(major == sOpenGlMajor);
    assert(minor == sOpenGlMinor);
    //assert(multisamples == mSamples);

    std::stringstream ss;
    ss << "\nPrinting SdlWindow info:\n";
    ss << "\nWindow Title: " << mTitle << "\n";
    ss << "Vsync: " << sVSync << "\n";
    ss << "Fullscreen: " << sFullscreen << "\n";
    ss << "Window (width, height): " << "(" << getWindowWidth() << ", " << getWindowHeight() << ")\n";
    ss << "The number of connected joysticks: " << SDL_NumJoysticks() << "\n";
    ss << "The GL context is : " << getContextString(context) << "\n";
    ss << "Major, Minor versions: " << major << ", " << minor << "\n";
    return ss.str();
}

/**
 * @brief SdlWindow::getGlInfoString
 * @return
 */
std::string SdlWindow::getGlInfoString() const
{
    const GLubyte* renderer = glGetString(GL_RENDERER);
    const GLubyte* vendor = glGetString(GL_VENDOR);
    const GLubyte* version = glGetString(GL_VERSION);
    const GLubyte* glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);

    GLint major, minor;
    glGetIntegerv(GL_MAJOR_VERSION, &major);
    glGetIntegerv(GL_MINOR_VERSION, &minor);

    std::stringstream ss;
    ss << "\n-------------------------------------------------------------\n";
    ss << "GL Vendor:\t\t\t" << vendor;
    ss << "\nGL GLRenderer:\t\t\t" << renderer;
    ss << "\nGL Version:\t\t\t" << version;
    ss << "\nGL Major, Minor:\t\t\t" << major << "." << minor;
    ss << "\nGLSL Version:\t\t\t" << glslVersion;
    ss << "\n-------------------------------------------------------------\n";
    return ss.str();
}

/**
 * @brief SdlWindow::swapBuffers
 */
void SdlWindow::swapBuffers() const
{
    SDL_GL_SwapWindow(mSdlWindow);
}

/**
 * @brief SdlWindow::hapticRumblePlay
 * @param strength
 * @param length
 * @return
 */
bool SdlWindow::hapticRumblePlay(float strength, float length) const
{
    return static_cast<bool>(SDL_HapticRumblePlay(mSdlHaptic, strength, length));
}

/**
 * @brief SdlWindow::buildBufferFromFile
 * @param filename
 * @param bufferSize
 * @return the buffer
 */
unsigned char* SdlWindow::buildBufferFromFile(const std::string& filename, long& bufferSize) const
{
    SDL_RWops* rwOps = SDL_RWFromFile(filename.c_str(), "rb");

    if (rwOps)
    {
        long fileSize = SDL_RWsize(rwOps);
        unsigned char* result = static_cast<unsigned char*>(malloc(fileSize + 1));
        long numberReadTotal = 0;
        long numberRead = 1;

        unsigned char* buffer = result;

        while (numberRead < fileSize && numberRead != 0)
        {
            numberRead = SDL_RWread(rwOps, buffer, 1, (fileSize - numberReadTotal));
            numberReadTotal += numberRead;
            buffer += numberRead;
        }

        SDL_RWclose(rwOps);

        if (numberReadTotal != fileSize)
        {
            free(result);
        }

        result[numberReadTotal] = '\0';

        bufferSize = fileSize;

        return result;
    }
    else
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, SDL_GetError());
        return nullptr;
    }
}

/**
 * @brief SdlWindow::buildStringFromFile
 * @param filename
 * @return
 */
std::string SdlWindow::buildStringFromFile(const std::string& filename) const
{
    std::string returnStr;
    SDL_RWops* rwOps = SDL_RWFromFile(filename.c_str(), "r");

    if (rwOps)
    {
        long fileSize = SDL_RWsize(rwOps);
        char* result = static_cast<char*>(malloc(fileSize + 1));
        long numberReadTotal = 0;
        long numberRead = 1;

        char* buffer = result;

        while (numberRead < fileSize && numberRead != 0)
        {
            numberRead = SDL_RWread(rwOps, buffer, 1, (fileSize - numberReadTotal));
            numberReadTotal += numberRead;
            buffer += numberRead;
        }

        SDL_RWclose(rwOps);

        if (numberReadTotal != fileSize)
        {
            free(result);
        }

        result[numberReadTotal] = '\0';

        returnStr.assign(result, fileSize);
        free(result);
    }
    else
    {
        SDL_LogError(SDL_LOG_CATEGORY_ERROR, SDL_GetError());
    }

    return returnStr;
}

/**
 * @brief SdlWindow::isFullScreen
 * @return
 */
bool SdlWindow::isFullScreen() const
{
    return sFullscreen;
}

/**
 * @brief SdlWindow::getWindowHeight
 * @return
 */
int SdlWindow::getWindowHeight() const
{
    int x, y;
    SDL_GetWindowSize(mSdlWindow, &x, &y);
    return y;
}

/**
 * @brief SdlWindow::getWindowWidth
 * @return
 */
int SdlWindow::getWindowWidth() const
{
    int x, y;
    SDL_GetWindowSize(mSdlWindow, &x, &y);
    return x;
}

/**
 * @brief SdlWindow::getAspectRatio
 * @return
 */
float SdlWindow::getAspectRatio() const
{
    int x, y;
    SDL_GetWindowSize(mSdlWindow, &x, &y);
    return static_cast<float>(x) / static_cast<float>(y);
}

/**
 * @brief SdlWindow::getSdlWindow
 * @return
 */
SDL_Window* SdlWindow::getSdlWindow() const
{
    return mSdlWindow;
}

/**
 * @return
 */
Uint32 SdlWindow::getInitFlags() const
{
    return sInitFlags;
}

/**
 * priv
 * @brief SdlWindow::getContextString
 * @param context
 * @return
 */
std::string SdlWindow::getContextString(int context) const
{
    switch (context)
    {
        case SDL_GL_CONTEXT_PROFILE_CORE: return "Core GL Context";
        case SDL_GL_CONTEXT_PROFILE_ES: return "ES GL Context";
        case SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG: return "Forward GL Context";
        //case SDL_GL_CONTEXT_DEBUG_FLAG: return "Debug GL Context";
        default: return "Unknown GL context";
    }
}
<|endoftext|>


<commit_before>#include "radial_por_lotes.cpp"
#include "../guia1/multicapa.cpp"
#include <gnuplot-iostream.h>
#include "../config.hpp"

int main()
{
    arma_rng::set_seed_random();

    mat datos;
    datos.load(config::sourceDir + "/guia2/datos/XOR_trn.csv");

    ic::ParametrosRBF parametros;
    ifstream ifs{config::sourceDir + "/guia2/parametrosRbfXor.txt"};
    if (!ifs)
        throw runtime_error("No se pudo abrir el archivo");

    if (!(ifs >> parametros))
        throw runtime_error("Se leyeron mal los parametros del RBF para el XOR");

    mat patrones = datos.head_cols(2);
    vec salidaDeseada = datos.tail_cols(1);

    // 1. Entrenar capa de base radial
    vector<rowvec> centroides;
    vec sigmas;
    tie(centroides, sigmas) = ic::entrenarRadialPorLotes(patrones,
                                                         parametros.estructuraRed(0),
                                                         ic::tipoInicializacion::valoresAlAzar);

    // 2. Calcular la salida de la capa radial para todos los patrones
    mat salidasRadiales(patrones.n_rows, centroides.size());
    for (unsigned int i = 0; i < patrones.n_rows; ++i) {
        salidasRadiales.row(i) = ic::salidaRadial(patrones.row(i), centroides, sigmas);
    }

    datos = join_horiz(salidasRadiales, salidaDeseada);

    // 3. Entrenar la capa de salida de la red usando el algoritmo del multicapa
    vector<mat> pesos;
    tie(pesos, ignore, ignore, ignore) = ic::entrenarMulticapa(vec{parametros.estructuraRed(1)},
                                                               datos,
                                                               parametros.nEpocas,
                                                               parametros.tasaAprendizaje,
                                                               parametros.inercia,
                                                               parametros.toleranciaError);

    // 4. Calcular el error de clasificación de la red final
    datos.load(config::sourceDir + "/guia2/datos/XOR_tst.csv");
    patrones = datos.head_cols(2);
    salidaDeseada = datos.tail_cols(1);
    salidasRadiales.clear();
    salidasRadiales.set_size(patrones.n_rows, centroides.size());

    for (unsigned int i = 0; i < patrones.n_rows; ++i) {
        salidasRadiales.row(i) = ic::salidaRadial(patrones.row(i), centroides, sigmas);
    }

    const double errorClasificacion = ic::errorClasificacionMulticapa(pesos, salidasRadiales, salidaDeseada);

    cout << "XOR Capa radial + Capa de salida multicapa" << endl
         << "Tasa de error de clasificación en prueba: " << errorClasificacion << endl;

    // 5. Gráficas
    mat matrizCentroides;
    for (const rowvec& centroide : centroides) {
        matrizCentroides.insert_rows(matrizCentroides.n_rows, centroide);
    }

    const mat verdaderos = patrones.rows(find(salidaDeseada == 1));
    const mat falsos = patrones.rows(find(salidaDeseada == -1));

    // Se calcula la salida de la red híbrida para todo el plano,
    // para luego graficar la frontera de decisión.
    const int N = 125;
    mat puntosSuperficie(N * N, 3);
    const vec x = linspace(-1.5, 1.5, N);
    const vec y = linspace(-1.5, 1.5, N);

    for (unsigned int i = 0; i < x.n_elem; ++i) {
        for (unsigned int j = 0; j < y.n_elem; ++j) {
            const rowvec salidaRBF = ic::salidaRadial(rowvec{x(i), y(j)}, centroides, sigmas);
            const vector<vec> salidasRed = ic::salidaMulticapa(pesos, salidaRBF.t());
            const double salidaFinal = salidasRed.back()(0);

            puntosSuperficie.row(N * i + j) = rowvec{x(i), y(j), salidaFinal};
        }
    }

    Gnuplot gp;
    gp << "set title 'XOR base radial' font ',13'" << endl
       << "set xlabel 'x_1'" << endl
       << "set ylabel 'x_2'" << endl
       << "set key box opaque outside width 3" << endl
       << "set grid" << endl

       // Se plotea la frontera de decisión a un archivo
       << "set contour base" << endl
       << "set cntrparam levels discrete 0" << endl
       << "set dgrid3d " << N << "," << N << endl
       << "unset surface" << endl
       << "set table 'fronteraRbfXor.dat'" << endl
       << "splot " << gp.file1d(puntosSuperficie) << endl
       << "unset table" << endl
       << "unset dgrid3d" << endl
       << "unset contour" << endl

       << "plot " << gp.file1d(verdaderos) << "title 'Verdaderos' with points lt rgb 'cyan', "
       << gp.file1d(falsos) << "title 'Falsos' with points lt rgb 'green', "
       << gp.file1d(matrizCentroides) << "title 'Centroides' with points pt 2 ps 1 lw 2 lt rgb 'black', "
       << "'fronteraRbfXor.dat' title 'Frontera de decisión' with lines lw 2.5 lt rgb 'magenta'" << endl;

    getchar();

    return 0;
}
<commit_msg>Guia 2 - Ejercicio 1: Agregar "set surface" al gráfico de curva de nivel<commit_after>#include "radial_por_lotes.cpp"
#include "../guia1/multicapa.cpp"
#include <gnuplot-iostream.h>
#include "../config.hpp"

int main()
{
    arma_rng::set_seed_random();

    mat datos;
    datos.load(config::sourceDir + "/guia2/datos/XOR_trn.csv");

    ic::ParametrosRBF parametros;
    ifstream ifs{config::sourceDir + "/guia2/parametrosRbfXor.txt"};
    if (!ifs)
        throw runtime_error("No se pudo abrir el archivo");

    if (!(ifs >> parametros))
        throw runtime_error("Se leyeron mal los parametros del RBF para el XOR");

    mat patrones = datos.head_cols(2);
    vec salidaDeseada = datos.tail_cols(1);

    // 1. Entrenar capa de base radial
    vector<rowvec> centroides;
    vec sigmas;
    tie(centroides, sigmas) = ic::entrenarRadialPorLotes(patrones,
                                                         parametros.estructuraRed(0),
                                                         ic::tipoInicializacion::valoresAlAzar);

    // 2. Calcular la salida de la capa radial para todos los patrones
    mat salidasRadiales(patrones.n_rows, centroides.size());
    for (unsigned int i = 0; i < patrones.n_rows; ++i) {
        salidasRadiales.row(i) = ic::salidaRadial(patrones.row(i), centroides, sigmas);
    }

    datos = join_horiz(salidasRadiales, salidaDeseada);

    // 3. Entrenar la capa de salida de la red usando el algoritmo del multicapa
    vector<mat> pesos;
    tie(pesos, ignore, ignore, ignore) = ic::entrenarMulticapa(vec{parametros.estructuraRed(1)},
                                                               datos,
                                                               parametros.nEpocas,
                                                               parametros.tasaAprendizaje,
                                                               parametros.inercia,
                                                               parametros.toleranciaError);

    // 4. Calcular el error de clasificación de la red final
    datos.load(config::sourceDir + "/guia2/datos/XOR_tst.csv");
    patrones = datos.head_cols(2);
    salidaDeseada = datos.tail_cols(1);
    salidasRadiales.clear();
    salidasRadiales.set_size(patrones.n_rows, centroides.size());

    for (unsigned int i = 0; i < patrones.n_rows; ++i) {
        salidasRadiales.row(i) = ic::salidaRadial(patrones.row(i), centroides, sigmas);
    }

    const double errorClasificacion = ic::errorClasificacionMulticapa(pesos, salidasRadiales, salidaDeseada);

    cout << "XOR Capa radial + Capa de salida multicapa" << endl
         << "Tasa de error de clasificación en prueba: " << errorClasificacion << endl;

    // 5. Gráficas
    mat matrizCentroides;
    for (const rowvec& centroide : centroides) {
        matrizCentroides.insert_rows(matrizCentroides.n_rows, centroide);
    }

    const mat verdaderos = patrones.rows(find(salidaDeseada == 1));
    const mat falsos = patrones.rows(find(salidaDeseada == -1));

    // Se calcula la salida de la red híbrida para todo el plano,
    // para luego graficar la frontera de decisión.
    const int N = 125;
    mat puntosSuperficie(N * N, 3);
    const vec x = linspace(-1.5, 1.5, N);
    const vec y = linspace(-1.5, 1.5, N);

    for (unsigned int i = 0; i < x.n_elem; ++i) {
        for (unsigned int j = 0; j < y.n_elem; ++j) {
            const rowvec salidaRBF = ic::salidaRadial(rowvec{x(i), y(j)}, centroides, sigmas);
            const vector<vec> salidasRed = ic::salidaMulticapa(pesos, salidaRBF.t());
            const double salidaFinal = salidasRed.back()(0);

            puntosSuperficie.row(N * i + j) = rowvec{x(i), y(j), salidaFinal};
        }
    }

    Gnuplot gp;
    gp << "set title 'XOR base radial' font ',13'" << endl
       << "set xlabel 'x_1'" << endl
       << "set ylabel 'x_2'" << endl
       << "set key box opaque outside width 3" << endl
       << "set grid" << endl

       // Se plotea la frontera de decisión a un archivo
       << "set contour base" << endl
       << "set cntrparam levels discrete 0" << endl
       << "set dgrid3d " << N << "," << N << endl
       << "unset surface" << endl
       << "set table 'fronteraRbfXor.dat'" << endl
       << "splot " << gp.file1d(puntosSuperficie) << endl
       << "unset table" << endl
       << "set surface" << endl
       << "unset dgrid3d" << endl
       << "unset contour" << endl

       << "plot " << gp.file1d(verdaderos) << "title 'Verdaderos' with points lt rgb 'cyan', "
       << gp.file1d(falsos) << "title 'Falsos' with points lt rgb 'green', "
       << gp.file1d(matrizCentroides) << "title 'Centroides' with points pt 2 ps 1 lw 2 lt rgb 'black', "
       << "'fronteraRbfXor.dat' title 'Frontera de decisión' with lines lw 2.5 lt rgb 'magenta'" << endl;

    getchar();

    return 0;
}
<|endoftext|>