<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#include "transfer.hpp"

namespace mfem
{

TransferOperator::TransferOperator(const FiniteElementSpace &lFESpace_,
                                   const FiniteElementSpace &hFESpace_)
    : Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize())
{
   // If both spaces' FE collection pointers are pointing to the same collection
   // we assume that the grid was refined while keeping the order constant
   if (lFESpace_.FEColl() == hFESpace_.FEColl())
   {
      OperatorPtr P(Operator::ANY_TYPE);
      hFESpace_.GetTransferOperator(lFESpace_, P);
      P.SetOperatorOwner(false);
      opr = P.Ptr();
   }
   else
   {
      opr = new OrderTransferOperator(lFESpace_, hFESpace_);
   }
}

TransferOperator::~TransferOperator() { delete opr; }

void TransferOperator::Mult(const Vector &x, Vector &y) const
{
   opr->Mult(x, y);
}

void TransferOperator::MultTranspose(const Vector &x, Vector &y) const
{
   opr->MultTranspose(x, y);
}

OrderTransferOperator::OrderTransferOperator(
    const FiniteElementSpace &lFESpace_, const FiniteElementSpace &hFESpace_)
    : Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize()), hFESpace(hFESpace_),
      lFESpace(lFESpace_)
{
}

OrderTransferOperator::~OrderTransferOperator() {}

void OrderTransferOperator::Mult(const Vector &x, Vector &y) const
{
   Mesh *mesh = hFESpace.GetMesh();
   Array<int> l_dofs, h_dofs;
   DenseMatrix loc_prol;
   Vector subY, subX;

   Geometry::Type cached_geom = Geometry::INVALID;
   const FiniteElement *h_fe = NULL;
   const FiniteElement *l_fe = NULL;
   IsoparametricTransformation T;

   for (int i = 0; i < mesh->GetNE(); i++)
   {
      hFESpace.GetElementDofs(i, h_dofs);
      lFESpace.GetElementDofs(i, l_dofs);

      const Geometry::Type geom = mesh->GetElementBaseGeometry(i);
      if (geom != cached_geom)
      {
         h_fe = hFESpace.GetFE(i);
         l_fe = lFESpace.GetFE(i);
         T.SetIdentityTransformation(h_fe->GetGeomType());
         h_fe->Project(*l_fe, T, loc_prol);
         subY.SetSize(loc_prol.Height());
         cached_geom = geom;
      }

      x.GetSubVector(l_dofs, subX);
      loc_prol.Mult(subX, subY);
      y.SetSubVector(h_dofs, subY);
   }
}

void OrderTransferOperator::MultTranspose(const Vector &x, Vector &y) const
{
   y = 0.0;

   Mesh *mesh = hFESpace.GetMesh();
   Array<int> l_dofs, h_dofs;
   DenseMatrix loc_prol;
   Vector subY, subX;

   Array<char> processed(hFESpace.GetVSize());
   processed = 0;

   Geometry::Type cached_geom = Geometry::INVALID;
   const FiniteElement *h_fe = NULL;
   const FiniteElement *l_fe = NULL;
   IsoparametricTransformation T;

   for (int i = 0; i < mesh->GetNE(); i++)
   {
      hFESpace.GetElementDofs(i, h_dofs);
      lFESpace.GetElementDofs(i, l_dofs);

      const Geometry::Type geom = mesh->GetElementBaseGeometry(i);
      if (geom != cached_geom)
      {
         h_fe = hFESpace.GetFE(i);
         l_fe = lFESpace.GetFE(i);
         T.SetIdentityTransformation(h_fe->GetGeomType());
         h_fe->Project(*l_fe, T, loc_prol);
         subY.SetSize(loc_prol.Width());
         cached_geom = geom;
      }

      x.GetSubVector(h_dofs, subX);
      for (int p = 0; p < h_dofs.Size(); ++p)
      {
         if (processed[h_dofs[p]])
         {
            subX[p] = 0.0;
         }
         else
         {
            processed[h_dofs[p]] = 1;
         }
      }

      loc_prol.MultTranspose(subX, subY);
      y.AddElementVector(l_dofs, subY);
   }
}

TrueTransferOperator::TrueTransferOperator(const FiniteElementSpace &lFESpace_,
                                           const FiniteElementSpace &hFESpace_)
{
   localTransferOperator = new TransferOperator(lFESpace_, hFESpace_);

   opr = new TripleProductOperator(
       hFESpace_.GetRestrictionMatrix(), localTransferOperator,
       lFESpace_.GetProlongationMatrix(), false, false, false);
}

TrueTransferOperator::~TrueTransferOperator()
{
   delete opr;
   delete localTransferOperator;
}

void TrueTransferOperator::Mult(const Vector &x, Vector &y) const
{
   opr->Mult(x, y);
}

void TrueTransferOperator::MultTranspose(const Vector &x, Vector &y) const
{
   opr->MultTranspose(x, y);
}

} // namespace mfem<commit_msg>Reordered initialization of member variables<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#include "transfer.hpp"

namespace mfem
{

TransferOperator::TransferOperator(const FiniteElementSpace &lFESpace_,
                                   const FiniteElementSpace &hFESpace_)
    : Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize())
{
   // If both spaces' FE collection pointers are pointing to the same collection
   // we assume that the grid was refined while keeping the order constant
   if (lFESpace_.FEColl() == hFESpace_.FEColl())
   {
      OperatorPtr P(Operator::ANY_TYPE);
      hFESpace_.GetTransferOperator(lFESpace_, P);
      P.SetOperatorOwner(false);
      opr = P.Ptr();
   }
   else
   {
      opr = new OrderTransferOperator(lFESpace_, hFESpace_);
   }
}

TransferOperator::~TransferOperator() { delete opr; }

void TransferOperator::Mult(const Vector &x, Vector &y) const
{
   opr->Mult(x, y);
}

void TransferOperator::MultTranspose(const Vector &x, Vector &y) const
{
   opr->MultTranspose(x, y);
}

OrderTransferOperator::OrderTransferOperator(
    const FiniteElementSpace &lFESpace_, const FiniteElementSpace &hFESpace_)
    : Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize()), lFESpace(lFESpace_),
      hFESpace(hFESpace_)
{
}

OrderTransferOperator::~OrderTransferOperator() {}

void OrderTransferOperator::Mult(const Vector &x, Vector &y) const
{
   Mesh *mesh = hFESpace.GetMesh();
   Array<int> l_dofs, h_dofs;
   DenseMatrix loc_prol;
   Vector subY, subX;

   Geometry::Type cached_geom = Geometry::INVALID;
   const FiniteElement *h_fe = NULL;
   const FiniteElement *l_fe = NULL;
   IsoparametricTransformation T;

   for (int i = 0; i < mesh->GetNE(); i++)
   {
      hFESpace.GetElementDofs(i, h_dofs);
      lFESpace.GetElementDofs(i, l_dofs);

      const Geometry::Type geom = mesh->GetElementBaseGeometry(i);
      if (geom != cached_geom)
      {
         h_fe = hFESpace.GetFE(i);
         l_fe = lFESpace.GetFE(i);
         T.SetIdentityTransformation(h_fe->GetGeomType());
         h_fe->Project(*l_fe, T, loc_prol);
         subY.SetSize(loc_prol.Height());
         cached_geom = geom;
      }

      x.GetSubVector(l_dofs, subX);
      loc_prol.Mult(subX, subY);
      y.SetSubVector(h_dofs, subY);
   }
}

void OrderTransferOperator::MultTranspose(const Vector &x, Vector &y) const
{
   y = 0.0;

   Mesh *mesh = hFESpace.GetMesh();
   Array<int> l_dofs, h_dofs;
   DenseMatrix loc_prol;
   Vector subY, subX;

   Array<char> processed(hFESpace.GetVSize());
   processed = 0;

   Geometry::Type cached_geom = Geometry::INVALID;
   const FiniteElement *h_fe = NULL;
   const FiniteElement *l_fe = NULL;
   IsoparametricTransformation T;

   for (int i = 0; i < mesh->GetNE(); i++)
   {
      hFESpace.GetElementDofs(i, h_dofs);
      lFESpace.GetElementDofs(i, l_dofs);

      const Geometry::Type geom = mesh->GetElementBaseGeometry(i);
      if (geom != cached_geom)
      {
         h_fe = hFESpace.GetFE(i);
         l_fe = lFESpace.GetFE(i);
         T.SetIdentityTransformation(h_fe->GetGeomType());
         h_fe->Project(*l_fe, T, loc_prol);
         subY.SetSize(loc_prol.Width());
         cached_geom = geom;
      }

      x.GetSubVector(h_dofs, subX);
      for (int p = 0; p < h_dofs.Size(); ++p)
      {
         if (processed[h_dofs[p]])
         {
            subX[p] = 0.0;
         }
         else
         {
            processed[h_dofs[p]] = 1;
         }
      }

      loc_prol.MultTranspose(subX, subY);
      y.AddElementVector(l_dofs, subY);
   }
}

TrueTransferOperator::TrueTransferOperator(const FiniteElementSpace &lFESpace_,
                                           const FiniteElementSpace &hFESpace_)
{
   localTransferOperator = new TransferOperator(lFESpace_, hFESpace_);

   opr = new TripleProductOperator(
       hFESpace_.GetRestrictionMatrix(), localTransferOperator,
       lFESpace_.GetProlongationMatrix(), false, false, false);
}

TrueTransferOperator::~TrueTransferOperator()
{
   delete opr;
   delete localTransferOperator;
}

void TrueTransferOperator::Mult(const Vector &x, Vector &y) const
{
   opr->Mult(x, y);
}

void TrueTransferOperator::MultTranspose(const Vector &x, Vector &y) const
{
   opr->MultTranspose(x, y);
}

} // namespace mfem<|endoftext|>


<commit_before>//
// Copyright (c) 2018 The nanoFramework project contributors
// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved
// Portions Copyright (c) Microsoft Corporation.  All rights reserved.
// See LICENSE file in the project root for full license information.
//

#include <ssl.h>
#include "mbedtls.h"

int ssl_connect_internal(int sd, const char* szTargetHost, int sslContextHandle)
{
    mbedTLS_NFContext* context;

    int ret = -1;

    // Retrieve SSL struct from g_SSL_Driver
    if((sslContextHandle >= (int)ARRAYSIZE(g_SSL_Driver.m_sslContextArray)) || (sslContextHandle < 0))
    {
        goto error;
    }

    // sd should already have been created
    // Now do the SSL negotiation
    context = (mbedTLS_NFContext*)g_SSL_Driver.m_sslContextArray[sslContextHandle].SslContext;
    if (context == NULL) goto error;

    // set socket
    context->server_fd->fd = sd;

    if(szTargetHost != NULL && szTargetHost[0] != 0)
    {
        if( (ret = mbedtls_ssl_set_hostname( context->ssl, szTargetHost )) != 0 )
        {
            // hostname_failed
            goto error;
        }
    }

    mbedtls_ssl_set_bio( context->ssl, context->server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout );

    while( ( ret = mbedtls_ssl_handshake( context->ssl ) ) != 0 )
    {
        if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
        {
            // SSL handshake failed
            //mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
            goto error;
        }
    }

error:
    return ret;
}
<commit_msg>Fix missing code to store SSL context in socket driver<commit_after>//
// Copyright (c) 2018 The nanoFramework project contributors
// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved
// Portions Copyright (c) Microsoft Corporation.  All rights reserved.
// See LICENSE file in the project root for full license information.
//

#include <ssl.h>
#include "mbedtls.h"

int ssl_connect_internal(int sd, const char* szTargetHost, int sslContextHandle)
{
    mbedTLS_NFContext* context;

    int ret = -1;

    // Retrieve SSL struct from g_SSL_Driver
    if((sslContextHandle >= (int)ARRAYSIZE(g_SSL_Driver.m_sslContextArray)) || (sslContextHandle < 0))
    {
        goto error;
    }

    // sd should already have been created
    // Now do the SSL negotiation
    context = (mbedTLS_NFContext*)g_SSL_Driver.m_sslContextArray[sslContextHandle].SslContext;
    if (context == NULL) goto error;

    // set socket
    context->server_fd->fd = sd;

    if(szTargetHost != NULL && szTargetHost[0] != 0)
    {
        if( (ret = mbedtls_ssl_set_hostname( context->ssl, szTargetHost )) != 0 )
        {
            // hostname_failed
            goto error;
        }
    }

    mbedtls_ssl_set_bio( context->ssl, context->server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout );

    while( ( ret = mbedtls_ssl_handshake( context->ssl ) ) != 0 )
    {
        if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
        {
            // SSL handshake failed
            //mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
            goto error;
        }
    }

    SOCKET_DRIVER.SetSocketSslData(sd, (void*)context);

error:
    return ret;
}
<|endoftext|>


<commit_before>#include "SoundRenderer.h"
#include "Game.h"

////////////////////////////////////////////////////////////////////////////////
SoundRenderer::SoundRenderer()
{
    //  init fmod
    FMOD::System_Create(&system_);

    result_ = system_->setOutput(FMOD_OUTPUTTYPE_AUTODETECT); FMOD::check(result_);
    result_ = system_->setSpeakerMode(FMOD_SPEAKERMODE_STEREO); FMOD::check(result_);
    result_ = system_->init(64, FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED, 0); FMOD::check(result_);

    //  start listening
    shootsRecording_ = false;
    shouldListen_ = false;
    sound_ = createBuffer();
    toggleListening();

    //  add massive reverb
    FMOD::Reverb* reverb;
    system_->createReverb(&reverb);
    reverb->setActive(true);

    FMOD_VECTOR pos = { 0.0f, 0.0f, 0.0f };
    float mindist = 0.0f;
    float maxdist = 100.0f;
    reverb->set3DAttributes(&pos, mindist, maxdist);

    FMOD_REVERB_PROPERTIES properties;
    properties.DecayTime = 100;
    properties.Reverb = 100;
    reverb->setProperties(&properties);
}

////////////////////////////////////////////////////////////////////////////////
SoundRenderer::~SoundRenderer() {
    result_ = system_->release(); FMOD::check(result_);
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::shoot()
{
    if (shouldListen_)
    {
        //  spawn sound with recording
        game->shoot();

        if (shootsRecording_) {
            const float velocity = 2 * (amplitude_ + 8);
            sounds_.push_back(Sound(shotSound_, this));
            sounds_.back().setVelocity(velocity);
        } else {
            sounds_.push_back(createDSP());
        }
    }
    else
    {
        //  get path

        //  spawn and shoot sound
        createDSP();
        sounds_.back().setVelocity(10);
    }

    const vector<vec2i> path = game->getBoard().getPath(false);
    sounds_.back().setPath(path);
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::toggleListening()
{
    if (shouldListen_) {
        system_->recordStop(0);
        channel_->stop();
    } else {
        system_->recordStart(0, sound_, true);
        system_->playSound(FMOD_CHANNEL_FREE, sound_, false, &channel_);
    }

    shouldListen_ = !shouldListen_;
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::toggleAmmunition() {
    shootsRecording_ = !shootsRecording_;
}

////////////////////////////////////////////////////////////////////////////////
FMOD::Sound* SoundRenderer::createBuffer(const float duration) const
{
    FMOD_CREATESOUNDEXINFO exinfo;
    memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));

    exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
    exinfo.numchannels = 2;
    exinfo.defaultfrequency = 44100;
    exinfo.format = FMOD_SOUND_FORMAT_PCMFLOAT;
    exinfo.length = exinfo.defaultfrequency * sizeof(float) * exinfo.numchannels * duration;

    FMOD_RESULT result;
    FMOD::Sound* sound = 0;
    result = system_->createSound(0, FMOD_LOOP_NORMAL | FMOD_3D | FMOD_SOFTWARE | FMOD_OPENUSER, &exinfo, &sound);
    FMOD::check(result_);

    return sound;
}

////////////////////////////////////////////////////////////////////////////////
Sound& SoundRenderer::createDSP()
{
    FMOD::Sound* sound = createBuffer();

    FMOD::DSP* dsp = 0;
    result_ = system_->createDSPByType(FMOD_DSP_TYPE_OSCILLATOR, &dsp); FMOD::check(result_);
    result_ = dsp->setParameter(FMOD_DSP_OSCILLATOR_RATE, 440.0f); FMOD::check(result_);
    result_ = dsp->setParameter(FMOD_DSP_OSCILLATOR_TYPE, Sine); FMOD::check(result_);

    FMOD::Channel* channel = 0;
    result_ = system_->playDSP(FMOD_CHANNEL_FREE, dsp, false, &channel); FMOD::check(result_);
    result_ = channel->setMode(FMOD_3D); FMOD::check(result_);

    Sound soundObj(sound, channel, dsp);
    sounds_.push_back(soundObj);

    return sounds_.back();
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::setListenerState(const Renderer::State& state)
{
    vec3f fwd = state[1] - state[0];
    fwd /= fwd.norm();

    FMOD_VECTOR lpos = {state[0].x, state[0].y, state[0].z};
    FMOD_VECTOR lfwd = {fwd.x, fwd.y, fwd.z};
    FMOD_VECTOR lup = {state[2].x, state[2].y, state[2].z};
    FMOD_VECTOR lvel = {0, 0, 0};

    result_ = system_->set3DListenerAttributes(0, &lpos, &lvel, &lfwd, &lup);
    FMOD::check(result_);
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::clear() {
    sounds_.clear();
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::playSound(const vec3f &position, const vec3f& velocity, FMOD::Sound* sound)
{
    FMOD::Channel* channel;
    system_->playSound(FMOD_CHANNEL_FREE, sound, true, &channel);

    FMOD_VECTOR pos = {position.x, position.y, position.z};
    FMOD_VECTOR vel = {velocity.x, velocity.y, velocity.z};
    channel->set3DAttributes(&pos, &vel);
    channel->setMode(FMOD_3D | FMOD_LOOP_OFF);
    channel->setPaused(false);
    channel->setSpeakerMix(5, 5, 5, 5, 5, 5, 5, 5);

    channels_.push_back(channel);
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::update(const float dt)
{
    //  update sound balls
    if (sounds_.size() >= 64) {
        sounds_.front().stop();
        sounds_.pop_front();
    }

    for (auto& sound : sounds_) {
        sound.update(dt);
    }

    //  remove finished channels of one shot sounds
    for(auto iter = channels_.begin(); iter != channels_.end();)
    {
        bool isPlaying = false;
        (*iter)->isPlaying(&isPlaying);

        if(!isPlaying) {
            iter = channels_.erase(iter);
        } else {
            ++iter;
        }
    }

    if (shouldListen_)
    {
        //  detect microphone input
        static sf::Clock clock;

        //  synchronize channel with recording
        unsigned int position;
        system_->getRecordPosition(0, &position);
        channel_->setPosition(position, FMOD_TIMEUNIT_PCM);
        channel_->setVolume(0);

        //  compute mean amplitude
        const int nsamples = 1000;
        const int thresh = -3;

        float data[nsamples];
        channel_->getWaveData(data, nsamples, 0);

        float max = -numeric_limits<float>::max();
        float min = numeric_limits<float>::max();

        for (int i = 0; i < nsamples; i++) {
            max = data[i] > max ? data[i] : max;
            min = data[i] < min ? data[i] : min;
        }

        amplitude_ = log(max - min);

        //  detect start of input
        if (!isRecording_ && amplitude_ > thresh)
        {
            //  wait a certain amount of time between shots
            if (clock.getElapsedTime().asSeconds() < 0.1f) {
                return;
            }

            //  record following audio to seperate buffer
            shotSound_ = createBuffer(10);

            system_->recordStop(0);
            system_->recordStart(0, shotSound_, false);

            channel_->stop();
            system_->playSound(FMOD_CHANNEL_REUSE, shotSound_, false, &channel_);

            shoot();

            isRecording_ = true;
    //        cout << "start" << endl;
        }
        //  detect end of input
        else if (isRecording_ && amplitude_ <= thresh && amplitude_ > -100)
        {
            //  switch back to listening
            system_->recordStop(0);
            system_->recordStart(0, sound_, true);

            channel_->stop();
            system_->playSound(FMOD_CHANNEL_FREE, sound_, false, &channel_);

            clock.restart();
            isRecording_ = false;
    //        cout << "end " << position << endl;
        }
    }

    result_ = system_->update(); FMOD::check(result_);
}

////////////////////////////////////////////////////////////////////////////////
std::ostream& operator<< (std::ostream& out, const FMOD_VECTOR& v) {
    out << v.x << ", " << v.y << ", " << v.z << std::endl;
    return out;
}

////////////////////////////////////////////////////////////////////////////////
namespace FMOD
{
    void check(FMOD_RESULT result)
    {
        if (result != FMOD_OK) {
            printf("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
            exit(-1);
        }
    }
}
<commit_msg>set not listening as default<commit_after>#include "SoundRenderer.h"
#include "Game.h"

////////////////////////////////////////////////////////////////////////////////
SoundRenderer::SoundRenderer()
{
    //  init fmod
    FMOD::System_Create(&system_);

    result_ = system_->setOutput(FMOD_OUTPUTTYPE_AUTODETECT); FMOD::check(result_);
    result_ = system_->setSpeakerMode(FMOD_SPEAKERMODE_STEREO); FMOD::check(result_);
    result_ = system_->init(64, FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED, 0); FMOD::check(result_);

    //  start listening
    sound_ = createBuffer();
    shootsRecording_ = false;
    amplitude_ = 0;

    shouldListen_ = true;
    toggleListening();

    //  add massive reverb
    FMOD::Reverb* reverb;
    system_->createReverb(&reverb);
    reverb->setActive(true);

    FMOD_VECTOR pos = { 0.0f, 0.0f, 0.0f };
    float mindist = 0.0f;
    float maxdist = 100.0f;
    reverb->set3DAttributes(&pos, mindist, maxdist);

    FMOD_REVERB_PROPERTIES properties;
    properties.DecayTime = 100;
    properties.Reverb = 100;
    reverb->setProperties(&properties);
}

////////////////////////////////////////////////////////////////////////////////
SoundRenderer::~SoundRenderer() {
    result_ = system_->release(); FMOD::check(result_);
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::shoot()
{
    if (shouldListen_)
    {
        //  spawn sound with recording
        game->shoot();

        if (shootsRecording_) {
            const float velocity = 2 * (amplitude_ + 8);
            sounds_.push_back(Sound(shotSound_, this));
            sounds_.back().setVelocity(velocity);
        } else {
            sounds_.push_back(createDSP());
        }
    }
    else
    {
        //  get path

        //  spawn and shoot sound
        createDSP();
        sounds_.back().setVelocity(10);
    }

    const vector<vec2i> path = game->getBoard().getPath(false);
    sounds_.back().setPath(path);
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::toggleListening()
{
    if (shouldListen_) {
        system_->recordStop(0);
        channel_->stop();
    } else {
        system_->recordStart(0, sound_, true);
        system_->playSound(FMOD_CHANNEL_FREE, sound_, false, &channel_);
    }

    shouldListen_ = !shouldListen_;
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::toggleAmmunition() {
    shootsRecording_ = !shootsRecording_;
}

////////////////////////////////////////////////////////////////////////////////
FMOD::Sound* SoundRenderer::createBuffer(const float duration) const
{
    FMOD_CREATESOUNDEXINFO exinfo;
    memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));

    exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
    exinfo.numchannels = 2;
    exinfo.defaultfrequency = 44100;
    exinfo.format = FMOD_SOUND_FORMAT_PCMFLOAT;
    exinfo.length = exinfo.defaultfrequency * sizeof(float) * exinfo.numchannels * duration;

    FMOD_RESULT result;
    FMOD::Sound* sound = 0;
    result = system_->createSound(0, FMOD_LOOP_NORMAL | FMOD_3D | FMOD_SOFTWARE | FMOD_OPENUSER, &exinfo, &sound);
    FMOD::check(result_);

    return sound;
}

////////////////////////////////////////////////////////////////////////////////
Sound& SoundRenderer::createDSP()
{
    FMOD::Sound* sound = createBuffer();

    FMOD::DSP* dsp = 0;
    result_ = system_->createDSPByType(FMOD_DSP_TYPE_OSCILLATOR, &dsp); FMOD::check(result_);
    result_ = dsp->setParameter(FMOD_DSP_OSCILLATOR_RATE, 440.0f); FMOD::check(result_);
    result_ = dsp->setParameter(FMOD_DSP_OSCILLATOR_TYPE, Sine); FMOD::check(result_);

    FMOD::Channel* channel = 0;
    result_ = system_->playDSP(FMOD_CHANNEL_FREE, dsp, false, &channel); FMOD::check(result_);
    result_ = channel->setMode(FMOD_3D); FMOD::check(result_);

    Sound soundObj(sound, channel, dsp);
    sounds_.push_back(soundObj);

    return sounds_.back();
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::setListenerState(const Renderer::State& state)
{
    vec3f fwd = state[1] - state[0];
    fwd /= fwd.norm();

    FMOD_VECTOR lpos = {state[0].x, state[0].y, state[0].z};
    FMOD_VECTOR lfwd = {fwd.x, fwd.y, fwd.z};
    FMOD_VECTOR lup = {state[2].x, state[2].y, state[2].z};
    FMOD_VECTOR lvel = {0, 0, 0};

    result_ = system_->set3DListenerAttributes(0, &lpos, &lvel, &lfwd, &lup);
    FMOD::check(result_);
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::clear() {
    sounds_.clear();
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::playSound(const vec3f &position, const vec3f& velocity, FMOD::Sound* sound)
{
    FMOD::Channel* channel;
    system_->playSound(FMOD_CHANNEL_FREE, sound, true, &channel);

    FMOD_VECTOR pos = {position.x, position.y, position.z};
    FMOD_VECTOR vel = {velocity.x, velocity.y, velocity.z};
    channel->set3DAttributes(&pos, &vel);
    channel->setMode(FMOD_3D | FMOD_LOOP_OFF);
    channel->setPaused(false);
    channel->setSpeakerMix(5, 5, 5, 5, 5, 5, 5, 5);

    channels_.push_back(channel);
}

////////////////////////////////////////////////////////////////////////////////
void SoundRenderer::update(const float dt)
{
    //  update sound balls
    if (sounds_.size() >= 64) {
        sounds_.front().stop();
        sounds_.pop_front();
    }

    for (auto& sound : sounds_) {
        sound.update(dt);
    }

    //  remove finished channels of one shot sounds
    for(auto iter = channels_.begin(); iter != channels_.end();)
    {
        bool isPlaying = false;
        (*iter)->isPlaying(&isPlaying);

        if(!isPlaying) {
            iter = channels_.erase(iter);
        } else {
            ++iter;
        }
    }

    if (shouldListen_)
    {
        //  detect microphone input
        static sf::Clock clock;

        //  synchronize channel with recording
        unsigned int position;
        system_->getRecordPosition(0, &position);
        channel_->setPosition(position, FMOD_TIMEUNIT_PCM);
        channel_->setVolume(0);

        //  compute mean amplitude
        const int nsamples = 100;
        const int thresh = -4;

        float data[nsamples];
        channel_->getWaveData(data, nsamples, 0);

        float max = -numeric_limits<float>::max();
        float min = numeric_limits<float>::max();

        for (int i = 0; i < nsamples; i++) {
            max = data[i] > max ? data[i] : max;
            min = data[i] < min ? data[i] : min;
        }

        amplitude_ = log(max - min);

        //  detect start of input
        if (!isRecording_ && amplitude_ > thresh)
        {
            //  wait a certain amount of time between shots
            if (clock.getElapsedTime().asSeconds() < 0.1f) {
                return;
            }

            //  record following audio to seperate buffer
            shotSound_ = createBuffer(10);

            system_->recordStop(0);
            system_->recordStart(0, shotSound_, false);

            channel_->stop();
            system_->playSound(FMOD_CHANNEL_REUSE, shotSound_, false, &channel_);

            shoot();

            isRecording_ = true;
    //        cout << "start" << endl;
        }
        //  detect end of input
        else if (isRecording_ && amplitude_ <= thresh && amplitude_ > -100)
        {
            //  switch back to listening
            system_->recordStop(0);
            system_->recordStart(0, sound_, true);

            channel_->stop();
            system_->playSound(FMOD_CHANNEL_FREE, sound_, false, &channel_);

            clock.restart();
            isRecording_ = false;
    //        cout << "end " << position << endl;
        }
    }

    result_ = system_->update(); FMOD::check(result_);
}

////////////////////////////////////////////////////////////////////////////////
std::ostream& operator<< (std::ostream& out, const FMOD_VECTOR& v) {
    out << v.x << ", " << v.y << ", " << v.z << std::endl;
    return out;
}

////////////////////////////////////////////////////////////////////////////////
namespace FMOD
{
    void check(FMOD_RESULT result)
    {
        if (result != FMOD_OK) {
            printf("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
            exit(-1);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#ifndef HEARTHSTONEPP_TORCH_POLICY_HPP
#define HEARTHSTONEPP_TORCH_POLICY_HPP

#include <hspp/Policies/BasicPolicy.hpp>

namespace HSppTorch
{
using namespace Hearthstonepp;

class TorchPolicy : public BasicPolicy
{
 public:
    TorchPolicy() = default;

 private:
    //! Method for MulliganTask requirement.
    TaskMeta RequireMulligan(Player& player) override;

    //! Method for PlaySpellTask requirement.
    TaskMeta RequirePlaySpell(Player& player) override;

    //! Method for PlayCardTask requirement.
    TaskMeta RequirePlayCard(Player& player) override;

    //! Method for PlayMinionTask requirement.
    TaskMeta RequirePlayMinion(Player& player) override;

    //! Method for CombatTask requirement.
    TaskMeta RequireCombat(Player& player) override;

    //! Method for OverDraw notifying.
    void NotifyOverDraw(const TaskMeta& meta) override;
};
}  // namespace Hearthstonepp

#endif<commit_msg>feat(TorchPolicy): Add include torch<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#ifndef HEARTHSTONEPP_TORCH_POLICY_HPP
#define HEARTHSTONEPP_TORCH_POLICY_HPP

#include <hspp/Policies/BasicPolicy.hpp>
#include <torch/torch.h>

namespace HSppTorch
{
using namespace Hearthstonepp;

class TorchPolicy : public BasicPolicy
{
 public:
    TorchPolicy() = default;

 private:
    //! Method for MulliganTask requirement.
    TaskMeta RequireMulligan(Player& player) override;

    //! Method for PlaySpellTask requirement.
    TaskMeta RequirePlaySpell(Player& player) override;

    //! Method for PlayCardTask requirement.
    TaskMeta RequirePlayCard(Player& player) override;

    //! Method for PlayMinionTask requirement.
    TaskMeta RequirePlayMinion(Player& player) override;

    //! Method for CombatTask requirement.
    TaskMeta RequireCombat(Player& player) override;

    //! Method for OverDraw notifying.
    void NotifyOverDraw(const TaskMeta& meta) override;
};
}  // namespace Hearthstonepp

#endif<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <cassert>
#include <string>
#include "plugin.hxx"
#include "compat.hxx"

//
// We don't like using C-style casts in C++ code
//

namespace {

bool hasCLanguageLinkageType(FunctionDecl const * decl) {
    return decl->isExternC() || compat::isInExternCContext(*decl);
}

QualType resolvePointers(QualType type) {
    while (type->isPointerType()) {
        type = type->getAs<PointerType>()->getPointeeType();
    }
    return type;
}

class CStyleCast:
    public RecursiveASTVisitor<CStyleCast>, public loplugin::Plugin
{
public:
    explicit CStyleCast(InstantiationData const & data):
        Plugin(data), externCFunction(false)
    {}

    virtual void run() override {
        if (compiler.getLangOpts().CPlusPlus) {
            TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
        }
    }

    bool TraverseFunctionDecl(FunctionDecl * decl);

    bool VisitCStyleCastExpr(const CStyleCastExpr * expr);

private:
    bool externCFunction;
};

static const char * recommendedFix(clang::CastKind ck) {
    switch(ck) {
        case CK_IntegralToPointer: return "reinterpret_cast";
        case CK_PointerToIntegral: return "reinterpret_cast";
        case CK_BaseToDerived: return "static_cast";
        default: return "???";
    }
}

bool CStyleCast::TraverseFunctionDecl(FunctionDecl * decl) {
    bool ext = hasCLanguageLinkageType(decl)
        && decl->isThisDeclarationADefinition();
    if (ext) {
        assert(!externCFunction);
        externCFunction = true;
    }
    bool ret = RecursiveASTVisitor::TraverseFunctionDecl(decl);
    if (ext) {
        externCFunction = false;
    }
    return ret;
}

bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) {
    if (ignoreLocation(expr)) {
        return true;
    }
    // casting to void is typically used when a parameter or field is only used in
    // debug mode, and we want to eliminate an "unused" warning
    if( expr->getCastKind() == CK_ToVoid ) {
        return true;
    }
    // ignore integral-type conversions for now, there is unsufficient agreement about
    // the merits of C++ style casting in this case
    if( expr->getCastKind() == CK_IntegralCast ) {
        return true;
    }
    if( expr->getCastKind() == CK_NoOp ) {
        QualType t1 = expr->getSubExpr()->getType();
        QualType t2 = expr->getType();
        if (t1->isPointerType() && t2->isPointerType()) {
            t1 = t1->getAs<PointerType>()->getPointeeType();
            t2 = t2->getAs<PointerType>()->getPointeeType();
        } else if (t1->isLValueReferenceType() && t2->isLValueReferenceType()) {
            t1 = t1->getAs<LValueReferenceType>()->getPointeeType();
            t2 = t2->getAs<LValueReferenceType>()->getPointeeType();
        } else {
            return true;
        }
        if (expr->getSubExprAsWritten()->getType() != expr->getType()
            && (!t1.isMoreQualifiedThan(t2)
                || (t1.getUnqualifiedType().getCanonicalType().getTypePtr()
                    != (t2.getUnqualifiedType().getCanonicalType()
                        .getTypePtr()))))
        {
            return true;
        }
    }
    std::string incompFrom;
    std::string incompTo;
    if( expr->getCastKind() == CK_BitCast ) {
        if (resolvePointers(expr->getSubExprAsWritten()->getType())
            ->isIncompleteType())
        {
            incompFrom = "incomplete ";
        }
        if (resolvePointers(expr->getType())->isIncompleteType()) {
            incompTo = "incomplete ";
        }
    }
    if (externCFunction || expr->getLocStart().isMacroID()) {
        SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(
            expr->getLocStart());
        StringRef filename = compiler.getSourceManager().getFilename(spellingLocation);
        // ignore C code
        if ( filename.endswith(".h") ) {
            return true;
        }
    }
    report(
        DiagnosticsEngine::Warning,
        "c-style cast, type=%0, from=%1%2, to=%3%4, recommendedFix=%5",
        expr->getSourceRange().getBegin())
      << expr->getCastKind()
      << incompFrom << expr->getSubExprAsWritten()->getType()
      << incompTo << expr->getType()
      << recommendedFix(expr->getCastKind())
      << expr->getSourceRange();
    return true;
}

loplugin::Plugin::Registration< CStyleCast > X("cstylecast");

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>loplugin:cstylecast: deal with those that are (technically) const_cast<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <cassert>
#include <string>
#include "plugin.hxx"
#include "compat.hxx"

//
// We don't like using C-style casts in C++ code
//

namespace {

bool areSimilar(QualType type1, QualType type2) {
    auto t1 = type1.getCanonicalType().getTypePtr();
    auto t2 = type2.getCanonicalType().getTypePtr();
    for (;;) {
        if (t1->isPointerType()) {
            if (!t2->isPointerType()) {
                return false;
            }
            auto t1a = t1->getAs<PointerType>();
            auto t2a = t2->getAs<PointerType>();
            t1 = t1a->getPointeeType().getTypePtr();
            t2 = t2a->getPointeeType().getTypePtr();
        } else if (t1->isMemberPointerType()) {
            if (!t2->isMemberPointerType()) {
                return false;
            }
            auto t1a = t1->getAs<MemberPointerType>();
            auto t2a = t2->getAs<MemberPointerType>();
            if (t1a->getClass()->getCanonicalTypeInternal()
                != t2a->getClass()->getCanonicalTypeInternal())
            {
                return false;
            }
            t1 = t1a->getPointeeType().getTypePtr();
            t2 = t2a->getPointeeType().getTypePtr();
        } else if (t1->isConstantArrayType()) {
            if (!t2->isConstantArrayType()) {
                return false;
            }
            auto t1a = static_cast<ConstantArrayType const *>(
                t1->getAsArrayTypeUnsafe());
            auto t2a = static_cast<ConstantArrayType const *>(
                t2->getAsArrayTypeUnsafe());
            if (t1a->getSize() != t2a->getSize()) {
                return false;
            }
            t1 = t1a->getElementType().getTypePtr();
            t2 = t2a->getElementType().getTypePtr();
        } else if (t1->isIncompleteArrayType()) {
            if (!t2->isIncompleteArrayType()) {
                return false;
            }
            auto t1a = static_cast<IncompleteArrayType const *>(
                t1->getAsArrayTypeUnsafe());
            auto t2a = static_cast<IncompleteArrayType const *>(
                t2->getAsArrayTypeUnsafe());
            t1 = t1a->getElementType().getTypePtr();
            t2 = t2a->getElementType().getTypePtr();
        } else {
            return false;
        }
        if (t1 == t2) {
            return true;
        }
    }
}

bool hasCLanguageLinkageType(FunctionDecl const * decl) {
    return decl->isExternC() || compat::isInExternCContext(*decl);
}

QualType resolvePointers(QualType type) {
    while (type->isPointerType()) {
        type = type->getAs<PointerType>()->getPointeeType();
    }
    return type;
}

class CStyleCast:
    public RecursiveASTVisitor<CStyleCast>, public loplugin::Plugin
{
public:
    explicit CStyleCast(InstantiationData const & data):
        Plugin(data), externCFunction(false)
    {}

    virtual void run() override {
        if (compiler.getLangOpts().CPlusPlus) {
            TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
        }
    }

    bool TraverseFunctionDecl(FunctionDecl * decl);

    bool VisitCStyleCastExpr(const CStyleCastExpr * expr);

private:
    bool isConstCast(QualType from, QualType to);

    bool externCFunction;
};

static const char * recommendedFix(clang::CastKind ck) {
    switch(ck) {
        case CK_IntegralToPointer: return "reinterpret_cast";
        case CK_PointerToIntegral: return "reinterpret_cast";
        case CK_BaseToDerived: return "static_cast";
        default: return nullptr;
    }
}

bool CStyleCast::TraverseFunctionDecl(FunctionDecl * decl) {
    bool ext = hasCLanguageLinkageType(decl)
        && decl->isThisDeclarationADefinition();
    if (ext) {
        assert(!externCFunction);
        externCFunction = true;
    }
    bool ret = RecursiveASTVisitor::TraverseFunctionDecl(decl);
    if (ext) {
        externCFunction = false;
    }
    return ret;
}

bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) {
    if (ignoreLocation(expr)) {
        return true;
    }
    // casting to void is typically used when a parameter or field is only used in
    // debug mode, and we want to eliminate an "unused" warning
    if( expr->getCastKind() == CK_ToVoid ) {
        return true;
    }
    // ignore integral-type conversions for now, there is unsufficient agreement about
    // the merits of C++ style casting in this case
    if( expr->getCastKind() == CK_IntegralCast ) {
        return true;
    }
    char const * perf = nullptr;
    if( expr->getCastKind() == CK_NoOp ) {
        QualType t1 = expr->getSubExpr()->getType();
        QualType t2 = expr->getType();
        if (t1->isPointerType() && t2->isPointerType()) {
            t1 = t1->getAs<PointerType>()->getPointeeType();
            t2 = t2->getAs<PointerType>()->getPointeeType();
        } else if (t1->isLValueReferenceType() && t2->isLValueReferenceType()) {
            t1 = t1->getAs<LValueReferenceType>()->getPointeeType();
            t2 = t2->getAs<LValueReferenceType>()->getPointeeType();
        } else {
            return true;
        }
        if (isConstCast(
                expr->getSubExprAsWritten()->getType(),
                expr->getTypeAsWritten()))
        {
            perf = "const_cast";
        } else if (expr->getSubExprAsWritten()->getType() != expr->getType()
                   && (!t1.isMoreQualifiedThan(t2)
                       || ((t1.getUnqualifiedType().getCanonicalType()
                            .getTypePtr())
                           != (t2.getUnqualifiedType().getCanonicalType()
                               .getTypePtr()))))
        {
            return true;
        }
    }
    std::string incompFrom;
    std::string incompTo;
    if( expr->getCastKind() == CK_BitCast ) {
        if (resolvePointers(expr->getSubExprAsWritten()->getType())
            ->isIncompleteType())
        {
            incompFrom = "incomplete ";
        }
        if (resolvePointers(expr->getType())->isIncompleteType()) {
            incompTo = "incomplete ";
        }
    }
    if (externCFunction || expr->getLocStart().isMacroID()) {
        SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(
            expr->getLocStart());
        StringRef filename = compiler.getSourceManager().getFilename(spellingLocation);
        // ignore C code
        if ( filename.endswith(".h") ) {
            return true;
        }
    }
    if (perf == nullptr) {
        perf = recommendedFix(expr->getCastKind());
    }
    std::string performs;
    if (perf != nullptr) {
        performs = std::string(" (performs: ") + perf + ")";
    }
    report(
        DiagnosticsEngine::Warning, "%0 C-style cast from %1%2 to %3%4%5",
        expr->getSourceRange().getBegin())
      << expr->getCastKindName() << incompFrom
      << expr->getSubExprAsWritten()->getType() << incompTo << expr->getType()
      << performs << expr->getSourceRange();
    return true;
}

bool CStyleCast::isConstCast(QualType from, QualType to) {
    if (to->isReferenceType()
        && to->getAs<ReferenceType>()->getPointeeType()->isObjectType())
    {
        if (!from->isObjectType()) {
            return false;
        }
        from = compiler.getASTContext().getPointerType(from);
        to = compiler.getASTContext().getPointerType(
            to->getAs<ReferenceType>()->getPointeeType());
    } else {
        if (from->isArrayType()) {
            from = compiler.getASTContext().getPointerType(
                from->getAsArrayTypeUnsafe()->getElementType());
        } else if (from->isFunctionType()) {
            compiler.getASTContext().getPointerType(from);
        }
    }
    return areSimilar(from, to);
}

loplugin::Plugin::Registration< CStyleCast > X("cstylecast");

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "VuMeter.h"

#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3

using namespace bgslibrary::algorithms;

VuMeter::VuMeter() :
  IBGS(quote(VuMeter)),
  enableFilter(true), binSize(8),
  alpha(0.995), threshold(0.03)
{
  debug_construction(VuMeter);
  initLoadSaveConfig(algorithmName);
}

VuMeter::~VuMeter() {
  debug_destruction(VuMeter);
  cvReleaseImage(&mask);
  cvReleaseImage(&background);
  cvReleaseImage(&gray);
}

void VuMeter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
{
  init(img_input, img_output, img_bgmodel);

  IplImage _frame = cvIplImage(img_input);
  frame = cvCloneImage(&_frame);

  if (firstTime) {
    int w = img_input.size().width;
    int h = img_input.size().height;

    bgs.SetAlpha(alpha);
    bgs.SetBinSize(binSize);
    bgs.SetThreshold(threshold);

    gray = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
    cvCvtColor(frame, gray, CV_RGB2GRAY);

    background = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
    cvCopy(gray, background);

    mask = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
    cvZero(mask);
  }
  else
    cvCvtColor(frame, gray, CV_RGB2GRAY);

  bgs.UpdateBackground(gray, background, mask);
  img_foreground = cv::cvarrToMat(mask);
  img_background = cv::cvarrToMat(background);

  if (enableFilter) {
    cv::erode(img_foreground, img_foreground, cv::Mat());
    cv::medianBlur(img_foreground, img_foreground, 5);
  }

#ifndef MEX_COMPILE_FLAG
  if (showOutput) {
    cv::imshow(algorithmName + "_FG", img_foreground);
    cv::imshow(algorithmName + "_BG", img_background);
  }
#endif

  img_foreground.copyTo(img_output);
  img_background.copyTo(img_bgmodel);

  firstTime = false;
}

void VuMeter::save_config(cv::FileStorage &fs) {
  fs << "enableFilter" << enableFilter;
  fs << "binSize" << binSize;
  fs << "alpha" << alpha;
  fs << "threshold" << threshold;
  fs << "showOutput" << showOutput;
}

void VuMeter::load_config(cv::FileStorage &fs) {
  fs["enableFilter"] >> enableFilter;
  fs["binSize"] >> binSize;
  fs["alpha"] >> alpha;
  fs["threshold"] >> threshold;
  fs["showOutput"] >> showOutput;
}

#endif
<commit_msg>[important] Fixed memory leak on VuMeter<commit_after>#include "VuMeter.h"

#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3

using namespace bgslibrary::algorithms;

VuMeter::VuMeter() :
  IBGS(quote(VuMeter)),
  enableFilter(true), binSize(8),
  alpha(0.995), threshold(0.03)
{
  debug_construction(VuMeter);
  initLoadSaveConfig(algorithmName);
}

VuMeter::~VuMeter() {
  debug_destruction(VuMeter);
  cvReleaseImage(&mask);
  cvReleaseImage(&background);
  cvReleaseImage(&gray);
}

void VuMeter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
{
  init(img_input, img_output, img_bgmodel);

  IplImage _frame = cvIplImage(img_input);
  frame = cvCloneImage(&_frame);

  if (firstTime) {
    int w = img_input.size().width;
    int h = img_input.size().height;

    bgs.SetAlpha(alpha);
    bgs.SetBinSize(binSize);
    bgs.SetThreshold(threshold);

    gray = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
    cvCvtColor(frame, gray, CV_RGB2GRAY);

    background = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
    cvCopy(gray, background);

    mask = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
    cvZero(mask);
  }
  else
    cvCvtColor(frame, gray, CV_RGB2GRAY);

  bgs.UpdateBackground(gray, background, mask);
  img_foreground = cv::cvarrToMat(mask);
  img_background = cv::cvarrToMat(background);

  if (enableFilter) {
    cv::erode(img_foreground, img_foreground, cv::Mat());
    cv::medianBlur(img_foreground, img_foreground, 5);
  }

#ifndef MEX_COMPILE_FLAG
  if (showOutput) {
    cv::imshow(algorithmName + "_FG", img_foreground);
    cv::imshow(algorithmName + "_BG", img_background);
  }
#endif

  img_foreground.copyTo(img_output);
  img_background.copyTo(img_bgmodel);
  cvReleaseImage(&frame);

  firstTime = false;
}

void VuMeter::save_config(cv::FileStorage &fs) {
  fs << "enableFilter" << enableFilter;
  fs << "binSize" << binSize;
  fs << "alpha" << alpha;
  fs << "threshold" << threshold;
  fs << "showOutput" << showOutput;
}

void VuMeter::load_config(cv::FileStorage &fs) {
  fs["enableFilter"] >> enableFilter;
  fs["binSize"] >> binSize;
  fs["alpha"] >> alpha;
  fs["threshold"] >> threshold;
  fs["showOutput"] >> showOutput;
}

#endif
<|endoftext|>


<commit_before>/************** <auto-copyright.pl BEGIN do not edit this line> **************
 *
 * VR Juggler is (C) Copyright 1998-2007 by Iowa State University
 *
 * Original Authors:
 *   Allen Bierbaum, Christopher Just,
 *   Patrick Hartling, Kevin Meinert,
 *   Carolina Cruz-Neira, Albert Baker
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 *************** <auto-copyright.pl END do not edit this line> ***************/

// ---------------------------------------
// Performance Monitoring OpenGL sample application
//
// main.cpp
//  --------------------------------------

#include <collideApp.h>

#include <vrj/Kernel/Kernel.h>

using namespace vrj;

int main(int argc, char* argv[])
{
   Kernel* kernel = Kernel::instance();
   collideApp* application = new collideApp();

   if (argc <= 1)
   {
      std::cout << "\n\n";
      std::cout << "Usage: " << argv[0] << "vjconfigfile[0] vjconfigfile[1] ...  vjconfigfile[n] " << std::endl;
      exit(1);
   }

   for (int i=1; i< argc; ++i)
   {
      kernel->loadConfigFile(argv[i]);
   }

   kernel->start();

   kernel->setApplication(application);

   kernel->waitForKernelStop();

   delete application;

   return 0;
}
<commit_msg>When using Cocoa, it is not necessary to identify the configuration files to load on the command line. One of the fun thinks (at least in my opinion) about the way that I have put the Cocoa stuff together is that we can leverage run-time reconfiguration of VR Juggler and load config files through the application's built-in "File -> Open..." menu item.<commit_after>/************** <auto-copyright.pl BEGIN do not edit this line> **************
 *
 * VR Juggler is (C) Copyright 1998-2007 by Iowa State University
 *
 * Original Authors:
 *   Allen Bierbaum, Christopher Just,
 *   Patrick Hartling, Kevin Meinert,
 *   Carolina Cruz-Neira, Albert Baker
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 *************** <auto-copyright.pl END do not edit this line> ***************/

// ---------------------------------------
// Performance Monitoring OpenGL sample application
//
// main.cpp
//  --------------------------------------

#include <collideApp.h>

#include <vrj/Kernel/Kernel.h>

using namespace vrj;

int main(int argc, char* argv[])
{
   Kernel* kernel = Kernel::instance();
   collideApp* application = new collideApp();

#if ! defined(VRJ_USE_COCOA)
   if (argc <= 1)
   {
      std::cout << "\n\n";
      std::cout << "Usage: " << argv[0] << "vjconfigfile[0] vjconfigfile[1] ...  vjconfigfile[n] " << std::endl;
      exit(1);
   }
#endif

   for (int i=1; i< argc; ++i)
   {
      kernel->loadConfigFile(argv[i]);
   }

   kernel->start();

   kernel->setApplication(application);

   kernel->waitForKernelStop();

   delete application;

   return 0;
}
<|endoftext|>


<commit_before>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// 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.

#ifndef RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_
#define RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_

#include <algorithm>
#include <atomic>
#include <cstring>
#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>

#include "rclcpp/macros.hpp"
#include "rclcpp/mapped_ring_buffer.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/subscription.hpp"
#include "rclcpp/visibility_control.hpp"

namespace rclcpp
{
namespace intra_process_manager
{

class IntraProcessManagerImplBase
{
public:
  RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(IntraProcessManagerImplBase)

  IntraProcessManagerImplBase() = default;
  ~IntraProcessManagerImplBase() = default;

  virtual void
  add_subscription(uint64_t id, subscription::SubscriptionBase::SharedPtr subscription) = 0;

  virtual void
  remove_subscription(uint64_t intra_process_subscription_id) = 0;

  virtual void add_publisher(uint64_t id,
    publisher::PublisherBase::WeakPtr publisher,
    mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
    size_t size) = 0;

  virtual void
  remove_publisher(uint64_t intra_process_publisher_id) = 0;

  virtual mapped_ring_buffer::MappedRingBufferBase::SharedPtr
  get_publisher_info_for_id(
    uint64_t intra_process_publisher_id,
    uint64_t & message_seq) = 0;

  virtual void
  store_intra_process_message(uint64_t intra_process_publisher_id, uint64_t message_seq) = 0;

  virtual mapped_ring_buffer::MappedRingBufferBase::SharedPtr
  take_intra_process_message(uint64_t intra_process_publisher_id,
    uint64_t message_sequence_number,
    uint64_t requesting_subscriptions_intra_process_id,
    size_t & size) = 0;

  virtual bool
  matches_any_publishers(const rmw_gid_t * id) const = 0;

private:
  RCLCPP_DISABLE_COPY(IntraProcessManagerImplBase)
};

template<typename Allocator = std::allocator<void>>
class IntraProcessManagerImpl : public IntraProcessManagerImplBase
{
public:
  IntraProcessManagerImpl() = default;
  ~IntraProcessManagerImpl() = default;

  void
  add_subscription(uint64_t id, subscription::SubscriptionBase::SharedPtr subscription)
  {
    subscriptions_[id] = subscription;
    // subscription->get_topic_name() -> const char * can be used as the key,
    // since subscriptions_ shares the ownership of subscription
    subscription_ids_by_topic_[subscription->get_topic_name()].insert(id);
  }

  void
  remove_subscription(uint64_t intra_process_subscription_id)
  {
    subscriptions_.erase(intra_process_subscription_id);
    for (auto & pair : subscription_ids_by_topic_) {
      pair.second.erase(intra_process_subscription_id);
    }
    // Iterate over all publisher infos and all stored subscription id's and
    // remove references to this subscription's id.
    for (auto & publisher_pair : publishers_) {
      for (auto & sub_pair : publisher_pair.second.target_subscriptions_by_message_sequence) {
        sub_pair.second.erase(intra_process_subscription_id);
      }
    }
  }

  void add_publisher(uint64_t id,
    publisher::PublisherBase::WeakPtr publisher,
    mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
    size_t size)
  {
    publishers_[id].publisher = publisher;
    // As long as the size of the ring buffer is less than the max sequence number, we're safe.
    if (size > std::numeric_limits<uint64_t>::max()) {
      throw std::invalid_argument("the calculated buffer size is too large");
    }
    publishers_[id].sequence_number.store(0);

    publishers_[id].buffer = mrb;
    publishers_[id].target_subscriptions_by_message_sequence.reserve(size);
  }

  void
  remove_publisher(uint64_t intra_process_publisher_id)
  {
    publishers_.erase(intra_process_publisher_id);
  }

  // return message_seq and mrb
  mapped_ring_buffer::MappedRingBufferBase::SharedPtr
  get_publisher_info_for_id(
    uint64_t intra_process_publisher_id,
    uint64_t & message_seq)
  {
    std::lock_guard<std::mutex> lock(runtime_mutex_);
    auto it = publishers_.find(intra_process_publisher_id);
    if (it == publishers_.end()) {
      throw std::runtime_error("get_publisher_info_for_id called with invalid publisher id");
    }
    PublisherInfo & info = it->second;
    // Calculate the next message sequence number.
    message_seq = info.sequence_number.fetch_add(1);

    return info.buffer;
  }

  void
  store_intra_process_message(uint64_t intra_process_publisher_id, uint64_t message_seq)
  {
    std::lock_guard<std::mutex> lock(runtime_mutex_);
    auto it = publishers_.find(intra_process_publisher_id);
    if (it == publishers_.end()) {
      throw std::runtime_error("store_intra_process_message called with invalid publisher id");
    }
    PublisherInfo & info = it->second;
    auto publisher = info.publisher.lock();
    if (!publisher) {
      throw std::runtime_error("publisher has unexpectedly gone out of scope");
    }

    // Figure out what subscriptions should receive the message.
    auto & destined_subscriptions = subscription_ids_by_topic_[publisher->get_topic_name()];
    // Store the list for later comparison.
    if (info.target_subscriptions_by_message_sequence.count(message_seq) == 0) {
      info.target_subscriptions_by_message_sequence.emplace(
        message_seq, AllocSet(std::less<uint64_t>(), uint64_allocator));
    } else {
      info.target_subscriptions_by_message_sequence[message_seq].clear();
    }
    std::copy(
      destined_subscriptions.begin(), destined_subscriptions.end(),
      // Memory allocation occurs in info.target_subscriptions_by_message_sequence[message_seq]
      std::inserter(
        info.target_subscriptions_by_message_sequence[message_seq],
        // This ends up only being a hint to std::set, could also be .begin().
        info.target_subscriptions_by_message_sequence[message_seq].end()
      )
    );
  }

  mapped_ring_buffer::MappedRingBufferBase::SharedPtr
  take_intra_process_message(uint64_t intra_process_publisher_id,
    uint64_t message_sequence_number,
    uint64_t requesting_subscriptions_intra_process_id,
    size_t & size
  )
  {
    std::lock_guard<std::mutex> lock(runtime_mutex_);
    PublisherInfo * info;
    {
      auto it = publishers_.find(intra_process_publisher_id);
      if (it == publishers_.end()) {
        // Publisher is either invalid or no longer exists.
        return 0;
      }
      info = &it->second;
    }
    // Figure out how many subscriptions are left.
    AllocSet * target_subs;
    {
      auto it = info->target_subscriptions_by_message_sequence.find(message_sequence_number);
      if (it == info->target_subscriptions_by_message_sequence.end()) {
        // Message is no longer being stored by this publisher.
        return 0;
      }
      target_subs = &it->second;
    }
    {
      auto it = std::find(
        target_subs->begin(), target_subs->end(),
        requesting_subscriptions_intra_process_id);
      if (it == target_subs->end()) {
        // This publisher id/message seq pair was not intended for this subscription.
        return 0;
      }
      target_subs->erase(it);
    }
    size = target_subs->size();
    return info->buffer;
  }

  bool
  matches_any_publishers(const rmw_gid_t * id) const
  {
    for (auto & publisher_pair : publishers_) {
      auto publisher = publisher_pair.second.publisher.lock();
      if (!publisher) {
        continue;
      }
      if (*publisher.get() == id) {
        return true;
      }
    }
    return false;
  }

private:
  RCLCPP_DISABLE_COPY(IntraProcessManagerImpl)

  template<typename T>
  using RebindAlloc = typename std::allocator_traits<Allocator>::template rebind_alloc<T>;

  RebindAlloc<uint64_t> uint64_allocator;

  using AllocSet = std::set<uint64_t, std::less<uint64_t>, RebindAlloc<uint64_t>>;
  using SubscriptionMap = std::unordered_map<uint64_t, subscription::SubscriptionBase::WeakPtr,
      std::hash<uint64_t>, std::equal_to<uint64_t>,
      RebindAlloc<std::pair<const uint64_t, subscription::SubscriptionBase::WeakPtr>>>;

  struct strcmp_wrapper : public std::binary_function<const char *, const char *, bool>
  {
    bool
    operator()(const char * lhs, const char * rhs) const
    {
      return std::strcmp(lhs, rhs) < 0;
    }
  };
  using IDTopicMap = std::map<
      const char *,
      AllocSet,
      strcmp_wrapper,
      RebindAlloc<std::pair<const std::string, AllocSet>>>;

  SubscriptionMap subscriptions_;

  IDTopicMap subscription_ids_by_topic_;

  struct PublisherInfo
  {
    RCLCPP_DISABLE_COPY(PublisherInfo)

    PublisherInfo() = default;

    publisher::PublisherBase::WeakPtr publisher;
    std::atomic<uint64_t> sequence_number;
    mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer;

    using TargetSubscriptionsMap = std::unordered_map<uint64_t, AllocSet,
        std::hash<uint64_t>, std::equal_to<uint64_t>,
        RebindAlloc<std::pair<const uint64_t, AllocSet>>>;
    TargetSubscriptionsMap target_subscriptions_by_message_sequence;
  };

  using PublisherMap = std::unordered_map<uint64_t, PublisherInfo,
      std::hash<uint64_t>, std::equal_to<uint64_t>,
      RebindAlloc<std::pair<const uint64_t, PublisherInfo>>>;

  PublisherMap publishers_;

  std::mutex runtime_mutex_;
};

RCLCPP_PUBLIC
IntraProcessManagerImplBase::SharedPtr
create_default_impl();

}  // namespace intra_process_manager
}  // namespace rclcpp

#endif  // RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_
<commit_msg>Fix static assertion on xcode 9 (#379)<commit_after>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// 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.

#ifndef RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_
#define RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_

#include <algorithm>
#include <atomic>
#include <cstring>
#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>

#include "rclcpp/macros.hpp"
#include "rclcpp/mapped_ring_buffer.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/subscription.hpp"
#include "rclcpp/visibility_control.hpp"

namespace rclcpp
{
namespace intra_process_manager
{

class IntraProcessManagerImplBase
{
public:
  RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(IntraProcessManagerImplBase)

  IntraProcessManagerImplBase() = default;
  ~IntraProcessManagerImplBase() = default;

  virtual void
  add_subscription(uint64_t id, subscription::SubscriptionBase::SharedPtr subscription) = 0;

  virtual void
  remove_subscription(uint64_t intra_process_subscription_id) = 0;

  virtual void add_publisher(uint64_t id,
    publisher::PublisherBase::WeakPtr publisher,
    mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
    size_t size) = 0;

  virtual void
  remove_publisher(uint64_t intra_process_publisher_id) = 0;

  virtual mapped_ring_buffer::MappedRingBufferBase::SharedPtr
  get_publisher_info_for_id(
    uint64_t intra_process_publisher_id,
    uint64_t & message_seq) = 0;

  virtual void
  store_intra_process_message(uint64_t intra_process_publisher_id, uint64_t message_seq) = 0;

  virtual mapped_ring_buffer::MappedRingBufferBase::SharedPtr
  take_intra_process_message(uint64_t intra_process_publisher_id,
    uint64_t message_sequence_number,
    uint64_t requesting_subscriptions_intra_process_id,
    size_t & size) = 0;

  virtual bool
  matches_any_publishers(const rmw_gid_t * id) const = 0;

private:
  RCLCPP_DISABLE_COPY(IntraProcessManagerImplBase)
};

template<typename Allocator = std::allocator<void>>
class IntraProcessManagerImpl : public IntraProcessManagerImplBase
{
public:
  IntraProcessManagerImpl() = default;
  ~IntraProcessManagerImpl() = default;

  void
  add_subscription(uint64_t id, subscription::SubscriptionBase::SharedPtr subscription)
  {
    subscriptions_[id] = subscription;
    // subscription->get_topic_name() -> const char * can be used as the key,
    // since subscriptions_ shares the ownership of subscription
    subscription_ids_by_topic_[subscription->get_topic_name()].insert(id);
  }

  void
  remove_subscription(uint64_t intra_process_subscription_id)
  {
    subscriptions_.erase(intra_process_subscription_id);
    for (auto & pair : subscription_ids_by_topic_) {
      pair.second.erase(intra_process_subscription_id);
    }
    // Iterate over all publisher infos and all stored subscription id's and
    // remove references to this subscription's id.
    for (auto & publisher_pair : publishers_) {
      for (auto & sub_pair : publisher_pair.second.target_subscriptions_by_message_sequence) {
        sub_pair.second.erase(intra_process_subscription_id);
      }
    }
  }

  void add_publisher(uint64_t id,
    publisher::PublisherBase::WeakPtr publisher,
    mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
    size_t size)
  {
    publishers_[id].publisher = publisher;
    // As long as the size of the ring buffer is less than the max sequence number, we're safe.
    if (size > std::numeric_limits<uint64_t>::max()) {
      throw std::invalid_argument("the calculated buffer size is too large");
    }
    publishers_[id].sequence_number.store(0);

    publishers_[id].buffer = mrb;
    publishers_[id].target_subscriptions_by_message_sequence.reserve(size);
  }

  void
  remove_publisher(uint64_t intra_process_publisher_id)
  {
    publishers_.erase(intra_process_publisher_id);
  }

  // return message_seq and mrb
  mapped_ring_buffer::MappedRingBufferBase::SharedPtr
  get_publisher_info_for_id(
    uint64_t intra_process_publisher_id,
    uint64_t & message_seq)
  {
    std::lock_guard<std::mutex> lock(runtime_mutex_);
    auto it = publishers_.find(intra_process_publisher_id);
    if (it == publishers_.end()) {
      throw std::runtime_error("get_publisher_info_for_id called with invalid publisher id");
    }
    PublisherInfo & info = it->second;
    // Calculate the next message sequence number.
    message_seq = info.sequence_number.fetch_add(1);

    return info.buffer;
  }

  void
  store_intra_process_message(uint64_t intra_process_publisher_id, uint64_t message_seq)
  {
    std::lock_guard<std::mutex> lock(runtime_mutex_);
    auto it = publishers_.find(intra_process_publisher_id);
    if (it == publishers_.end()) {
      throw std::runtime_error("store_intra_process_message called with invalid publisher id");
    }
    PublisherInfo & info = it->second;
    auto publisher = info.publisher.lock();
    if (!publisher) {
      throw std::runtime_error("publisher has unexpectedly gone out of scope");
    }

    // Figure out what subscriptions should receive the message.
    auto & destined_subscriptions = subscription_ids_by_topic_[publisher->get_topic_name()];
    // Store the list for later comparison.
    if (info.target_subscriptions_by_message_sequence.count(message_seq) == 0) {
      info.target_subscriptions_by_message_sequence.emplace(
        message_seq, AllocSet(std::less<uint64_t>(), uint64_allocator));
    } else {
      info.target_subscriptions_by_message_sequence[message_seq].clear();
    }
    std::copy(
      destined_subscriptions.begin(), destined_subscriptions.end(),
      // Memory allocation occurs in info.target_subscriptions_by_message_sequence[message_seq]
      std::inserter(
        info.target_subscriptions_by_message_sequence[message_seq],
        // This ends up only being a hint to std::set, could also be .begin().
        info.target_subscriptions_by_message_sequence[message_seq].end()
      )
    );
  }

  mapped_ring_buffer::MappedRingBufferBase::SharedPtr
  take_intra_process_message(uint64_t intra_process_publisher_id,
    uint64_t message_sequence_number,
    uint64_t requesting_subscriptions_intra_process_id,
    size_t & size
  )
  {
    std::lock_guard<std::mutex> lock(runtime_mutex_);
    PublisherInfo * info;
    {
      auto it = publishers_.find(intra_process_publisher_id);
      if (it == publishers_.end()) {
        // Publisher is either invalid or no longer exists.
        return 0;
      }
      info = &it->second;
    }
    // Figure out how many subscriptions are left.
    AllocSet * target_subs;
    {
      auto it = info->target_subscriptions_by_message_sequence.find(message_sequence_number);
      if (it == info->target_subscriptions_by_message_sequence.end()) {
        // Message is no longer being stored by this publisher.
        return 0;
      }
      target_subs = &it->second;
    }
    {
      auto it = std::find(
        target_subs->begin(), target_subs->end(),
        requesting_subscriptions_intra_process_id);
      if (it == target_subs->end()) {
        // This publisher id/message seq pair was not intended for this subscription.
        return 0;
      }
      target_subs->erase(it);
    }
    size = target_subs->size();
    return info->buffer;
  }

  bool
  matches_any_publishers(const rmw_gid_t * id) const
  {
    for (auto & publisher_pair : publishers_) {
      auto publisher = publisher_pair.second.publisher.lock();
      if (!publisher) {
        continue;
      }
      if (*publisher.get() == id) {
        return true;
      }
    }
    return false;
  }

private:
  RCLCPP_DISABLE_COPY(IntraProcessManagerImpl)

  template<typename T>
  using RebindAlloc = typename std::allocator_traits<Allocator>::template rebind_alloc<T>;

  RebindAlloc<uint64_t> uint64_allocator;

  using AllocSet = std::set<uint64_t, std::less<uint64_t>, RebindAlloc<uint64_t>>;
  using SubscriptionMap = std::unordered_map<uint64_t, subscription::SubscriptionBase::WeakPtr,
      std::hash<uint64_t>, std::equal_to<uint64_t>,
      RebindAlloc<std::pair<const uint64_t, subscription::SubscriptionBase::WeakPtr>>>;

  struct strcmp_wrapper : public std::binary_function<const char *, const char *, bool>
  {
    bool
    operator()(const char * lhs, const char * rhs) const
    {
      return std::strcmp(lhs, rhs) < 0;
    }
  };
  using IDTopicMap = std::map<
      const char *,
      AllocSet,
      strcmp_wrapper,
      RebindAlloc<std::pair<const char * const, AllocSet>>>;

  SubscriptionMap subscriptions_;

  IDTopicMap subscription_ids_by_topic_;

  struct PublisherInfo
  {
    RCLCPP_DISABLE_COPY(PublisherInfo)

    PublisherInfo() = default;

    publisher::PublisherBase::WeakPtr publisher;
    std::atomic<uint64_t> sequence_number;
    mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer;

    using TargetSubscriptionsMap = std::unordered_map<uint64_t, AllocSet,
        std::hash<uint64_t>, std::equal_to<uint64_t>,
        RebindAlloc<std::pair<const uint64_t, AllocSet>>>;
    TargetSubscriptionsMap target_subscriptions_by_message_sequence;
  };

  using PublisherMap = std::unordered_map<uint64_t, PublisherInfo,
      std::hash<uint64_t>, std::equal_to<uint64_t>,
      RebindAlloc<std::pair<const uint64_t, PublisherInfo>>>;

  PublisherMap publishers_;

  std::mutex runtime_mutex_;
};

RCLCPP_PUBLIC
IntraProcessManagerImplBase::SharedPtr
create_default_impl();

}  // namespace intra_process_manager
}  // namespace rclcpp

#endif  // RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_
<|endoftext|>


<commit_before>//
// PROJECT:         Aspia Remote Desktop
// FILE:            host/desktop_session.cc
// LICENSE:         See top-level directory
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "host/desktop_session.h"
#include "host/desktop_session_launcher.h"
#include "base/version_helpers.h"
#include "base/scoped_privilege.h"

namespace aspia {

static const std::chrono::milliseconds kAttachTimeout{ 30000 };

// static
std::unique_ptr<DesktopSession> DesktopSession::Create(HostSession::Delegate* delegate)
{
    return std::unique_ptr<DesktopSession>(new DesktopSession(delegate));
}

DesktopSession::DesktopSession(HostSession::Delegate* delegate) :
    HostSession(delegate)
{
    ui_thread_.Start(MessageLoop::TYPE_UI, this);
}

DesktopSession::~DesktopSession()
{
    ui_thread_.Stop();
}

void DesktopSession::OnBeforeThreadRunning()
{
    runner_ = ui_thread_.message_loop_proxy();
    DCHECK(runner_);

    timer_.Start(kAttachTimeout,
                 std::bind(&DesktopSession::OnSessionAttachTimeout, this));

    OnSessionAttached(WTSGetActiveConsoleSessionId());

    // In Windows XP, the console session always has a ID equal to 0.
    // We do not need to watch the session.
    if (IsWindowsVistaOrGreater())
    {
        bool ret = session_watcher_.StartWatching(this);
        DCHECK(ret);
    }
}

void DesktopSession::OnAfterThreadRunning()
{
    session_watcher_.StopWatching();
    OnSessionDetached();
    timer_.Stop();
}

void DesktopSession::OnSessionAttached(uint32_t session_id)
{
    DCHECK(runner_->BelongsToCurrentThread());
    DCHECK(state_ == State::Detached);
    DCHECK(!process_.IsValid());
    DCHECK(!ipc_channel_);

    {
        std::unique_lock<std::mutex> lock(ipc_channel_lock_);

        state_ = State::Starting;

        std::wstring input_channel_id;
        std::wstring output_channel_id;

        ipc_channel_ = PipeChannel::CreateServer(input_channel_id,
                                                 output_channel_id);
        if (ipc_channel_)
        {
            if (DesktopSessionLauncher::LaunchSession(session_id,
                                                      input_channel_id,
                                                      output_channel_id))
            {
                if (ipc_channel_->Connect(this))
                    return;
            }
        }
    }

    session_watcher_.StopWatching();
    timer_.Stop();

    delegate_->OnSessionTerminate();
}

void DesktopSession::OnSessionDetached()
{
    DCHECK(runner_->BelongsToCurrentThread());

    if (state_ == State::Detached)
        return;

    state_ = State::Detached;

    std::unique_lock<std::mutex> lock(ipc_channel_lock_);

    process_watcher_.StopWatching();

    process_.Terminate(0, false);
    process_.Close();

    ipc_channel_.reset();

    // If the new session is not connected within the specified time interval,
    // an error occurred.
    timer_.Start(kAttachTimeout,
                 std::bind(&DesktopSession::OnSessionAttachTimeout, this));
}

void DesktopSession::OnObjectSignaled(HANDLE object)
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&DesktopSession::OnObjectSignaled, this, object));
        return;
    }

    DCHECK_EQ(object, process_.Handle());

    switch (state_)
    {
        case State::Attached:
        case State::Starting:
            OnSessionDetached();
            break;

        case State::Detached:
            break;
    }
}

void DesktopSession::OnPipeChannelConnect(ProcessId peer_pid)
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&DesktopSession::OnPipeChannelConnect, this, peer_pid));
        return;
    }

    // To open a host process and terminate it, additional privileges are required.
    // If the current process is running from the service, then the privilege
    // already exists, if not, then enable it.
    ScopedProcessPrivilege privilege(SE_DEBUG_NAME);

    process_ = Process::Open(peer_pid);

    bool ok = process_.IsValid();
    if (!ok)
    {
        LOG(ERROR) << "Unable to open session process: " << GetLastError();
    }

    if (ok)
    {
        ok = process_watcher_.StartWatching(process_.Handle(), this);
        if (!ok)
        {
            LOG(ERROR) << "Process watcher not started";
            process_.Close();
        }
    }

    timer_.Stop();

    if (!ok)
    {
        state_ = State::Detached;
        delegate_->OnSessionTerminate();
        return;
    }

    state_ = State::Attached;
}

void DesktopSession::OnPipeChannelDisconnect()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&DesktopSession::OnPipeChannelDisconnect, this));
        return;
    }

    switch (state_)
    {
        case State::Detached:
            break;

        case State::Attached:
            OnSessionDetached();
            break;

        case State::Starting:
        {
            DCHECK(!process_.IsValid());

            state_ = State::Detached;

            timer_.Stop();
            delegate_->OnSessionTerminate();
        }
        break;
    }
}

void DesktopSession::OnPipeChannelMessage(const IOBuffer& buffer)
{
    delegate_->OnSessionMessage(buffer);
}

void DesktopSession::OnSessionAttachTimeout()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&DesktopSession::OnSessionAttachTimeout, this));
        return;
    }

    switch (state_)
    {
        case State::Detached:
        case State::Starting:
            delegate_->OnSessionTerminate();
            break;

        case State::Attached:
            LOG(FATAL) << "In the attached state, the timer must me stopped";
            break;
    }
}

void DesktopSession::Send(const IOBuffer& buffer)
{
    std::unique_lock<std::mutex> lock(ipc_channel_lock_);

    if (!ipc_channel_)
        return;

    ipc_channel_->Send(buffer);
}

} // namespace aspia
<commit_msg>- Do not start the timer when starting the thread<commit_after>//
// PROJECT:         Aspia Remote Desktop
// FILE:            host/desktop_session.cc
// LICENSE:         See top-level directory
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "host/desktop_session.h"
#include "host/desktop_session_launcher.h"
#include "base/version_helpers.h"
#include "base/scoped_privilege.h"

namespace aspia {

static const std::chrono::milliseconds kAttachTimeout{ 30000 };

// static
std::unique_ptr<DesktopSession> DesktopSession::Create(HostSession::Delegate* delegate)
{
    return std::unique_ptr<DesktopSession>(new DesktopSession(delegate));
}

DesktopSession::DesktopSession(HostSession::Delegate* delegate) :
    HostSession(delegate)
{
    ui_thread_.Start(MessageLoop::TYPE_UI, this);
}

DesktopSession::~DesktopSession()
{
    ui_thread_.Stop();
}

void DesktopSession::OnBeforeThreadRunning()
{
    runner_ = ui_thread_.message_loop_proxy();
    DCHECK(runner_);

    OnSessionAttached(WTSGetActiveConsoleSessionId());

    // In Windows XP, the console session always has a ID equal to 0.
    // We do not need to watch the session.
    if (IsWindowsVistaOrGreater())
    {
        bool ret = session_watcher_.StartWatching(this);
        DCHECK(ret);
    }
}

void DesktopSession::OnAfterThreadRunning()
{
    session_watcher_.StopWatching();
    OnSessionDetached();
    timer_.Stop();
}

void DesktopSession::OnSessionAttached(uint32_t session_id)
{
    DCHECK(runner_->BelongsToCurrentThread());
    DCHECK(state_ == State::Detached);
    DCHECK(!process_.IsValid());
    DCHECK(!ipc_channel_);

    {
        std::unique_lock<std::mutex> lock(ipc_channel_lock_);

        state_ = State::Starting;

        std::wstring input_channel_id;
        std::wstring output_channel_id;

        ipc_channel_ = PipeChannel::CreateServer(input_channel_id,
                                                 output_channel_id);
        if (ipc_channel_)
        {
            if (DesktopSessionLauncher::LaunchSession(session_id,
                                                      input_channel_id,
                                                      output_channel_id))
            {
                if (ipc_channel_->Connect(this))
                    return;
            }
        }
    }

    session_watcher_.StopWatching();
    timer_.Stop();

    delegate_->OnSessionTerminate();
}

void DesktopSession::OnSessionDetached()
{
    DCHECK(runner_->BelongsToCurrentThread());

    if (state_ == State::Detached)
        return;

    state_ = State::Detached;

    std::unique_lock<std::mutex> lock(ipc_channel_lock_);

    process_watcher_.StopWatching();

    process_.Terminate(0, false);
    process_.Close();

    ipc_channel_.reset();

    // If the new session is not connected within the specified time interval,
    // an error occurred.
    timer_.Start(kAttachTimeout,
                 std::bind(&DesktopSession::OnSessionAttachTimeout, this));
}

void DesktopSession::OnObjectSignaled(HANDLE object)
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&DesktopSession::OnObjectSignaled, this, object));
        return;
    }

    DCHECK_EQ(object, process_.Handle());

    switch (state_)
    {
        case State::Attached:
        case State::Starting:
            OnSessionDetached();
            break;

        case State::Detached:
            break;
    }
}

void DesktopSession::OnPipeChannelConnect(ProcessId peer_pid)
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&DesktopSession::OnPipeChannelConnect, this, peer_pid));
        return;
    }

    // To open a host process and terminate it, additional privileges are required.
    // If the current process is running from the service, then the privilege
    // already exists, if not, then enable it.
    ScopedProcessPrivilege privilege(SE_DEBUG_NAME);

    process_ = Process::Open(peer_pid);

    bool ok = process_.IsValid();
    if (!ok)
    {
        LOG(ERROR) << "Unable to open session process: " << GetLastError();
    }

    if (ok)
    {
        ok = process_watcher_.StartWatching(process_.Handle(), this);
        if (!ok)
        {
            LOG(ERROR) << "Process watcher not started";
            process_.Close();
        }
    }

    timer_.Stop();

    if (!ok)
    {
        state_ = State::Detached;
        delegate_->OnSessionTerminate();
        return;
    }

    state_ = State::Attached;
}

void DesktopSession::OnPipeChannelDisconnect()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&DesktopSession::OnPipeChannelDisconnect, this));
        return;
    }

    switch (state_)
    {
        case State::Detached:
            break;

        case State::Attached:
            OnSessionDetached();
            break;

        case State::Starting:
        {
            DCHECK(!process_.IsValid());

            state_ = State::Detached;

            timer_.Stop();
            delegate_->OnSessionTerminate();
        }
        break;
    }
}

void DesktopSession::OnPipeChannelMessage(const IOBuffer& buffer)
{
    delegate_->OnSessionMessage(buffer);
}

void DesktopSession::OnSessionAttachTimeout()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&DesktopSession::OnSessionAttachTimeout, this));
        return;
    }

    switch (state_)
    {
        case State::Detached:
        case State::Starting:
            delegate_->OnSessionTerminate();
            break;

        case State::Attached:
            LOG(FATAL) << "In the attached state, the timer must me stopped";
            break;
    }
}

void DesktopSession::Send(const IOBuffer& buffer)
{
    std::unique_lock<std::mutex> lock(ipc_channel_lock_);

    if (!ipc_channel_)
        return;

    ipc_channel_->Send(buffer);
}

} // namespace aspia
<|endoftext|>


<commit_before>// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "imguisystem.hpp"

#include "../../lib/imgui.h"

void ImGuiSystem::update(World& world, float delta) {
	ImGui::Text("Entities:");
	for (std::shared_ptr<Entity> entity : world.getEntities()) {
		if (ImGui::TreeNode(entity->getName().c_str())) {
			ImGui::Text("Actions:");
			entity->registerImGui();

			ImGui::Text("Component:");
			for (std::shared_ptr<IComponent> component : entity->getComponents()) {
				if (ImGui::TreeNode(component->name().c_str())) {
					component->registerImGui();
					ImGui::TreePop();
				}
			}

			ImGui::TreePop();
		}
	}
	ImGui::Selectable("");
	ImGui::Text("Systems:");
	for (std::unique_ptr<System>& system : world.getSystems()) {
		if (ImGui::TreeNode(system->name().c_str())) {
			ImGui::Text("Actions:");
			system->registerImGui();
			ImGui::TreePop();
		}
	}
}

void ImGuiSystem::registerImGui() {}
<commit_msg>Made settings better behave better<commit_after>// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "imguisystem.hpp"

#include "../../lib/imgui.h"

void ImGuiSystem::update(World& world, float delta) {
	ImGui::SetNextWindowPos(ImVec2(8, 48), ImGuiSetCond_Once);
	ImGui::SetNextWindowSize(ImVec2(384, 512), ImGuiSetCond_Once);
	ImGui::SetNextWindowCollapsed(true, ImGuiSetCond_Once);
	ImGui::Begin("Settings Window");

	ImGui::Text("Entities:");
	for (std::shared_ptr<Entity> entity : world.getEntities()) {
		if (ImGui::TreeNode(entity->getName().c_str())) {
			ImGui::Text("Actions:");
			entity->registerImGui();

			ImGui::Text("Component:");
			for (std::shared_ptr<IComponent> component : entity->getComponents()) {
				if (ImGui::TreeNode(component->name().c_str())) {
					component->registerImGui();
					ImGui::TreePop();
				}
			}

			ImGui::TreePop();
		}
	}
	ImGui::Selectable("");
	ImGui::Text("Systems:");
	for (std::unique_ptr<System>& system : world.getSystems()) {
		if (ImGui::TreeNode(system->name().c_str())) {
			ImGui::Text("Actions:");
			system->registerImGui();
			ImGui::TreePop();
		}
	}

	ImGui::End();
}

void ImGuiSystem::registerImGui() {}
<|endoftext|>


<commit_before>#ifndef LIGHTGBM_METRIC_MAP_METRIC_HPP_
#define LIGHTGBM_METRIC_MAP_METRIC_HPP_

#include <LightGBM/utils/common.h>
#include <LightGBM/utils/log.h>

#include <LightGBM/metric.h>

#include <LightGBM/utils/openmp_wrapper.h>

#include <sstream>
#include <vector>

namespace LightGBM {

class MapMetric:public Metric {
public:
  explicit MapMetric(const MetricConfig& config) {
    // get eval position
    for (auto k : config.eval_at) {
      eval_at_.push_back(static_cast<data_size_t>(k));
    }
    // get number of threads
    #pragma omp parallel
    #pragma omp master
    {
      num_threads_ = omp_get_num_threads();
    }
  }

  ~MapMetric() {
  }

  void Init(const Metadata& metadata, data_size_t num_data) override {
    std::stringstream str_buf;
    for (auto k : eval_at_) {
      name_.emplace_back(std::string("map@") + std::to_string(k));
    }
    num_data_ = num_data;
    // get label
    label_ = metadata.label();
    // get query boundaries
    query_boundaries_ = metadata.query_boundaries();
    if (query_boundaries_ == nullptr) {
      Log::Fatal("For MAP metric, there should be query information");
    }
    num_queries_ = metadata.num_queries();
    Log::Info("total groups: %d , total data: %d", num_queries_, num_data_);
    // get query weights
    query_weights_ = metadata.query_weights();
    if (query_weights_ == nullptr) {
      sum_query_weights_ = static_cast<double>(num_queries_);
    } else {
      sum_query_weights_ = 0.0f;
      for (data_size_t i = 0; i < num_queries_; ++i) {
        sum_query_weights_ += query_weights_[i];
      }
    }
  }

  const std::vector<std::string>& GetName() const override {
    return name_;
  }

  double factor_to_bigger_better() const override {
    return 1.0f;
  }

  void CalMapAtK(std::vector<int> ks, const float* label,
                 const double* score, data_size_t num_data, std::vector<double>* out) const {
    // get sorted indices by score
    std::vector<data_size_t> sorted_idx;
    for (data_size_t i = 0; i < num_data; ++i) {
      sorted_idx.emplace_back(i);
    }
    std::sort(sorted_idx.begin(), sorted_idx.end(),
              [score](data_size_t a, data_size_t b) {return score[a] > score[b]; });

    int num_hit = 0;
    double sum_ap = 0.0f;
    data_size_t cur_left = 0;
    for (size_t i = 0; i < ks.size(); ++i) {
      data_size_t cur_k = ks[i];
      if (cur_k > num_data) { cur_k = num_data; }
      for (data_size_t j = cur_left; j < cur_k; ++j) {
        data_size_t idx = sorted_idx[j];
        if (label[idx] > 0.5f) {
          ++num_hit;
          sum_ap += static_cast<double>(num_hit) / (j + 1.0f);
        }
      }
      (*out)[i] = sum_ap / cur_k;
      cur_left = cur_k;
    }
  }
  std::vector<double> Eval(const double* score, const ObjectiveFunction*) const override {
    // some buffers for multi-threading sum up
    std::vector<std::vector<double>> result_buffer_;
    for (int i = 0; i < num_threads_; ++i) {
      result_buffer_.emplace_back(eval_at_.size(), 0.0f);
    }
    std::vector<double> tmp_map(eval_at_.size(), 0.0f);
    if (query_weights_ == nullptr) {
      #pragma omp parallel for schedule(guided) firstprivate(tmp_map)
      for (data_size_t i = 0; i < num_queries_; ++i) {
        const int tid = omp_get_thread_num();
        CalMapAtK(eval_at_, label_ + query_boundaries_[i],
                  score + query_boundaries_[i], query_boundaries_[i + 1] - query_boundaries_[i], &tmp_map);
        for (size_t j = 0; j < eval_at_.size(); ++j) {
          result_buffer_[tid][j] += tmp_map[j];
        }
      }
    } else {
      #pragma omp parallel for schedule(guided) firstprivate(tmp_map)
      for (data_size_t i = 0; i < num_queries_; ++i) {
        const int tid = omp_get_thread_num();
        CalMapAtK(eval_at_, label_ + query_boundaries_[i],
                  score + query_boundaries_[i], query_boundaries_[i + 1] - query_boundaries_[i], &tmp_map);
        for (size_t j = 0; j < eval_at_.size(); ++j) {
          result_buffer_[tid][j] += tmp_map[j] * query_weights_[i];
        }
      }
    }
    // Get final average MAP
    std::vector<double> result(eval_at_.size(), 0.0f);
    for (size_t j = 0; j < result.size(); ++j) {
      for (int i = 0; i < num_threads_; ++i) {
        result[j] += result_buffer_[i][j];
      }
      result[j] /= sum_query_weights_;
    }
    return result;
  }

private:
  /*! \brief Number of data */
  data_size_t num_data_;
  /*! \brief Pointer of label */
  const float* label_;
  /*! \brief Query boundaries information */
  const data_size_t* query_boundaries_;
  /*! \brief Number of queries */
  data_size_t num_queries_;
  /*! \brief Weights of queries */
  const float* query_weights_;
  /*! \brief Sum weights of queries */
  double sum_query_weights_;
  /*! \brief Evaluate position of Nmap */
  std::vector<data_size_t> eval_at_;
  /*! \brief Number of threads */
  int num_threads_;
  std::vector<std::string> name_;
};

}  // namespace LightGBM

#endif   // LIGHTGBM_METRIC_MAP_METRIC_HPP_
<commit_msg>fix map metric<commit_after>#ifndef LIGHTGBM_METRIC_MAP_METRIC_HPP_
#define LIGHTGBM_METRIC_MAP_METRIC_HPP_

#include <LightGBM/utils/common.h>
#include <LightGBM/utils/log.h>

#include <LightGBM/metric.h>

#include <LightGBM/utils/openmp_wrapper.h>

#include <sstream>
#include <vector>

namespace LightGBM {

class MapMetric:public Metric {
public:
  explicit MapMetric(const MetricConfig& config) {
    // get eval position
    for (auto k : config.eval_at) {
      eval_at_.push_back(static_cast<data_size_t>(k));
    }
    // get number of threads
    #pragma omp parallel
    #pragma omp master
    {
      num_threads_ = omp_get_num_threads();
    }
  }

  ~MapMetric() {
  }

  void Init(const Metadata& metadata, data_size_t num_data) override {
    std::stringstream str_buf;
    for (auto k : eval_at_) {
      name_.emplace_back(std::string("map@") + std::to_string(k));
    }
    num_data_ = num_data;
    // get label
    label_ = metadata.label();
    // get query boundaries
    query_boundaries_ = metadata.query_boundaries();
    if (query_boundaries_ == nullptr) {
      Log::Fatal("For MAP metric, there should be query information");
    }
    num_queries_ = metadata.num_queries();
    Log::Info("total groups: %d , total data: %d", num_queries_, num_data_);
    // get query weights
    query_weights_ = metadata.query_weights();
    if (query_weights_ == nullptr) {
      sum_query_weights_ = static_cast<double>(num_queries_);
    } else {
      sum_query_weights_ = 0.0f;
      for (data_size_t i = 0; i < num_queries_; ++i) {
        sum_query_weights_ += query_weights_[i];
      }
    }

    npos_per_query_.resize(num_queries_, 0);
    for (data_size_t i = 0; i < num_queries_; ++i) {
      for (data_size_t j = query_boundaries_[i]; j < query_boundaries_[i + 1]; ++j) {
        if (label_[j] > 0.5f) {
          ++npos_per_query_[i];
        }
      }
    }
  }

  const std::vector<std::string>& GetName() const override {
    return name_;
  }

  double factor_to_bigger_better() const override {
    return 1.0f;
  }

  void CalMapAtK(std::vector<int> ks, data_size_t npos, const float* label,
                 const double* score, data_size_t num_data, std::vector<double>* out) const {
    // get sorted indices by score
    std::vector<data_size_t> sorted_idx;
    for (data_size_t i = 0; i < num_data; ++i) {
      sorted_idx.emplace_back(i);
    }
    std::sort(sorted_idx.begin(), sorted_idx.end(),
              [score](data_size_t a, data_size_t b) {return score[a] > score[b]; });

    int num_hit = 0;
    double sum_ap = 0.0f;
    data_size_t cur_left = 0;
    for (size_t i = 0; i < ks.size(); ++i) {
      data_size_t cur_k = static_cast<data_size_t>(ks[i]);
      if (cur_k > num_data) { cur_k = num_data; }
      for (data_size_t j = cur_left; j < cur_k; ++j) {
        data_size_t idx = sorted_idx[j];
        if (label[idx] > 0.5f) {
          ++num_hit;
          sum_ap += static_cast<double>(num_hit) / (j + 1.0f);
        }
      }
      if (npos > 0) {
        (*out)[i] = sum_ap / std::min(npos, cur_k);
      } else {
        (*out)[i] = 1.0f;
      }
      cur_left = cur_k;
    }
  }
  std::vector<double> Eval(const double* score, const ObjectiveFunction*) const override {
    // some buffers for multi-threading sum up
    std::vector<std::vector<double>> result_buffer_;
    for (int i = 0; i < num_threads_; ++i) {
      result_buffer_.emplace_back(eval_at_.size(), 0.0f);
    }
    std::vector<double> tmp_map(eval_at_.size(), 0.0f);
    if (query_weights_ == nullptr) {
      #pragma omp parallel for schedule(guided) firstprivate(tmp_map)
      for (data_size_t i = 0; i < num_queries_; ++i) {
        const int tid = omp_get_thread_num();
        CalMapAtK(eval_at_, npos_per_query_[i], label_ + query_boundaries_[i],
                  score + query_boundaries_[i], query_boundaries_[i + 1] - query_boundaries_[i], &tmp_map);
        for (size_t j = 0; j < eval_at_.size(); ++j) {
          result_buffer_[tid][j] += tmp_map[j];
        }
      }
    } else {
      #pragma omp parallel for schedule(guided) firstprivate(tmp_map)
      for (data_size_t i = 0; i < num_queries_; ++i) {
        const int tid = omp_get_thread_num();
        CalMapAtK(eval_at_, npos_per_query_[i], label_ + query_boundaries_[i],
                  score + query_boundaries_[i], query_boundaries_[i + 1] - query_boundaries_[i], &tmp_map);
        for (size_t j = 0; j < eval_at_.size(); ++j) {
          result_buffer_[tid][j] += tmp_map[j] * query_weights_[i];
        }
      }
    }
    // Get final average MAP
    std::vector<double> result(eval_at_.size(), 0.0f);
    for (size_t j = 0; j < result.size(); ++j) {
      for (int i = 0; i < num_threads_; ++i) {
        result[j] += result_buffer_[i][j];
      }
      result[j] /= sum_query_weights_;
    }
    return result;
  }

private:
  /*! \brief Number of data */
  data_size_t num_data_;
  /*! \brief Pointer of label */
  const float* label_;
  /*! \brief Query boundaries information */
  const data_size_t* query_boundaries_;
  /*! \brief Number of queries */
  data_size_t num_queries_;
  /*! \brief Weights of queries */
  const float* query_weights_;
  /*! \brief Sum weights of queries */
  double sum_query_weights_;
  /*! \brief Evaluate position of Nmap */
  std::vector<data_size_t> eval_at_;
  /*! \brief Number of threads */
  int num_threads_;
  std::vector<std::string> name_;
  std::vector<data_size_t> npos_per_query_;
};

}  // namespace LightGBM

#endif   // LIGHTGBM_METRIC_MAP_METRIC_HPP_
<|endoftext|>