<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ComponentDefinition.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 10:13:40 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser 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
 *
 ************************************************************************/

#ifndef DBA_COREDATAACESS_COMPONENTDEFINITION_HXX
#define DBA_COREDATAACESS_COMPONENTDEFINITION_HXX

#ifndef _DBA_CORE_COMMANDBASE_HXX_
#include "commandbase.hxx"
#endif
#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_
#include <comphelper/propertycontainer.hxx>
#endif
#ifndef _DBA_REGHELPER_HXX_
#include "dba_reghelper.hxx"
#endif
#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_
#include <com/sun/star/sdbcx/XRename.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _DBA_CORE_DATASETTINGS_HXX_
#include "datasettings.hxx"
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#endif
#ifndef DBA_CONTENTHELPER_HXX
#include "ContentHelper.hxx"
#endif
#ifndef _DBA_COREAPI_COLUMN_HXX_
#include <column.hxx>
#endif
#include <memory>
//........................................................................
namespace dbaccess
{
//........................................................................

    typedef ::cppu::ImplHelper1< ::com::sun::star::sdbcx::XColumnsSupplier > OComponentDefinition_BASE;

    class OComponentDefinition_Impl : public OContentHelper_Impl
                                     ,public ODataSettings_Base
    {
    public:
        DECLARE_STL_USTRINGACCESS_MAP(::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> , TColumns);
        DECLARE_STL_VECTOR(TColumns::iterator, TColumnsIndexAccess);

        TColumnsIndexAccess m_aColumns;             // for a efficient index access
        TColumns            m_aColumnNames;             // for a efficient name access
        ::rtl::OUString     m_sSchemaName;
        ::rtl::OUString     m_sCatalogName;
    };

//=========================================================================
//= OComponentDefinition - a database "document" which describes a query
//=========================================================================

class OComponentDefinition  :public OContentHelper
                            ,public ODataSettings
                            ,public IColumnFactory
                            ,public OComponentDefinition_BASE
                            ,public ::comphelper::OPropertyArrayUsageHelper< OComponentDefinition >
{
    OComponentDefinition();

protected:
    ::std::auto_ptr<OColumns>   m_pColumns;

    sal_Bool                    m_bTable;

    virtual ~OComponentDefinition();
    virtual void SAL_CALL disposing();
protected:
    OComponentDefinition(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&
        ,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&   _xParentContainer
        ,const TContentPtr& _pImpl
        ,sal_Bool _bTable = sal_True);

public:

    OComponentDefinition(
             const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContainer
            ,const ::rtl::OUString& _rElementName
            ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&
            ,const TContentPtr& _pImpl
            ,sal_Bool _bTable = sal_True
        );

// com::sun::star::lang::XTypeProvider
    DECLARE_TYPEPROVIDER( );

// ::com::sun::star::uno::XInterface
    DECLARE_XINTERFACE( )

// ::com::sun::star::lang::XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw( ::com::sun::star::uno::RuntimeException );
    static ::rtl::OUString getImplementationName_Static(void) throw( ::com::sun::star::uno::RuntimeException );
    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
        Create(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&);

// ::com::sun::star::beans::XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw(::com::sun::star::uno::RuntimeException);

    // XColumnsSupplier
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns(  ) throw (::com::sun::star::uno::RuntimeException);

    // OPropertySetHelper
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();

    // IColumnFactory
    virtual OColumn*    createColumn(const ::rtl::OUString& _rName) const;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createEmptyObject();
    virtual void columnDropped(const ::rtl::OUString& _sName);
    virtual void columnCloned(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xClone);

protected:
// OPropertyArrayUsageHelper
    virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;

    virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
                                    sal_Int32 nHandle,
                                    const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception);
private:
    void registerProperties();

};

//........................................................................
}   // namespace dbaccess
//........................................................................

#endif // DBA_COREDATAACESS_COMPONENTDEFINITION_HXX

<commit_msg>INTEGRATION: CWS warnings01 (1.3.50); FILE MERGED 2006/03/24 15:35:51 fs 1.3.50.1: #i57457# warning-free code (unxlngi6/.pro + unxsoli4.pro)<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ComponentDefinition.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 02:42:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser 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
 *
 ************************************************************************/

#ifndef DBA_COREDATAACESS_COMPONENTDEFINITION_HXX
#define DBA_COREDATAACESS_COMPONENTDEFINITION_HXX

#ifndef _DBA_CORE_COMMANDBASE_HXX_
#include "commandbase.hxx"
#endif
#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_
#include <comphelper/propertycontainer.hxx>
#endif
#ifndef _DBA_REGHELPER_HXX_
#include "dba_reghelper.hxx"
#endif
#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_
#include <com/sun/star/sdbcx/XRename.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _DBA_CORE_DATASETTINGS_HXX_
#include "datasettings.hxx"
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#endif
#ifndef DBA_CONTENTHELPER_HXX
#include "ContentHelper.hxx"
#endif
#ifndef _DBA_COREAPI_COLUMN_HXX_
#include <column.hxx>
#endif
#include <memory>
//........................................................................
namespace dbaccess
{
//........................................................................

    typedef ::cppu::ImplHelper1< ::com::sun::star::sdbcx::XColumnsSupplier > OComponentDefinition_BASE;

    class OComponentDefinition_Impl : public OContentHelper_Impl
                                     ,public ODataSettings_Base
    {
    public:
        DECLARE_STL_USTRINGACCESS_MAP(::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> , TColumns);
        DECLARE_STL_VECTOR(TColumns::iterator, TColumnsIndexAccess);

        TColumnsIndexAccess m_aColumns;             // for a efficient index access
        TColumns            m_aColumnNames;             // for a efficient name access
        ::rtl::OUString     m_sSchemaName;
        ::rtl::OUString     m_sCatalogName;
    };

//=========================================================================
//= OComponentDefinition - a database "document" which describes a query
//=========================================================================

class OComponentDefinition  :public OContentHelper
                            ,public ODataSettings
                            ,public IColumnFactory
                            ,public OComponentDefinition_BASE
                            ,public ::comphelper::OPropertyArrayUsageHelper< OComponentDefinition >
{
    OComponentDefinition();

protected:
    ::std::auto_ptr<OColumns>   m_pColumns;

    sal_Bool                    m_bTable;

    virtual ~OComponentDefinition();
    virtual void SAL_CALL disposing();
protected:
    OComponentDefinition(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&
        ,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&   _xParentContainer
        ,const TContentPtr& _pImpl
        ,sal_Bool _bTable = sal_True);

public:

    OComponentDefinition(
             const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContainer
            ,const ::rtl::OUString& _rElementName
            ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&
            ,const TContentPtr& _pImpl
            ,sal_Bool _bTable = sal_True
        );

// com::sun::star::lang::XTypeProvider
    DECLARE_TYPEPROVIDER( );

// ::com::sun::star::uno::XInterface
    DECLARE_XINTERFACE( )

// ::com::sun::star::lang::XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw( ::com::sun::star::uno::RuntimeException );
    static ::rtl::OUString getImplementationName_Static(void) throw( ::com::sun::star::uno::RuntimeException );
    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
        Create(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&);

// ::com::sun::star::beans::XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw(::com::sun::star::uno::RuntimeException);

    // XColumnsSupplier
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns(  ) throw (::com::sun::star::uno::RuntimeException);

    // OPropertySetHelper
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();

    // IColumnFactory
    virtual OColumn*    createColumn(const ::rtl::OUString& _rName) const;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createEmptyObject();
    virtual void columnDropped(const ::rtl::OUString& _sName);
    virtual void columnCloned(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xClone);

protected:
// OPropertyArrayUsageHelper
    virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;

    virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
                                    sal_Int32 nHandle,
                                    const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception);
private:
    void registerProperties();
};

//........................................................................
}   // namespace dbaccess
//........................................................................

#endif // DBA_COREDATAACESS_COMPONENTDEFINITION_HXX
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"

#include <cstdint>

#include "rtc_base/checks.h"

namespace webrtc {

constexpr int RtpGenericFrameDescriptor::kMaxNumFrameDependencies;
constexpr int RtpGenericFrameDescriptor::kMaxTemporalLayers;
constexpr int RtpGenericFrameDescriptor::kMaxSpatialLayers;

RtpGenericFrameDescriptor::RtpGenericFrameDescriptor() = default;
RtpGenericFrameDescriptor::RtpGenericFrameDescriptor(
    const RtpGenericFrameDescriptor&) = default;
RtpGenericFrameDescriptor::~RtpGenericFrameDescriptor() = default;

int RtpGenericFrameDescriptor::TemporalLayer() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  return temporal_layer_;
}

void RtpGenericFrameDescriptor::SetTemporalLayer(int temporal_layer) {
  RTC_DCHECK_GE(temporal_layer, 0);
  RTC_DCHECK_LT(temporal_layer, kMaxTemporalLayers);
  temporal_layer_ = temporal_layer;
}

int RtpGenericFrameDescriptor::SpatialLayer() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  int layer = 0;
  uint8_t spatial_layers = spatial_layers_;
  while (spatial_layers_ != 0 && !(spatial_layers & 1)) {
    spatial_layers >>= 1;
    layer++;
  }
  return layer;
}

uint8_t RtpGenericFrameDescriptor::SpatialLayersBitmask() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  return spatial_layers_;
}

void RtpGenericFrameDescriptor::SetSpatialLayersBitmask(
    uint8_t spatial_layers) {
  RTC_DCHECK(FirstPacketInSubFrame());
  spatial_layers_ = spatial_layers;
}

void RtpGenericFrameDescriptor::SetResolution(int width, int height) {
  RTC_DCHECK(FirstPacketInSubFrame());
  RTC_DCHECK_GE(width, 0);
  RTC_DCHECK_LE(width, 0xFFFF);
  RTC_DCHECK_GE(height, 0);
  RTC_DCHECK_LE(height, 0xFFFF);
  width_ = width;
  height_ = height;
}

uint16_t RtpGenericFrameDescriptor::FrameId() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  return frame_id_;
}

void RtpGenericFrameDescriptor::SetFrameId(uint16_t frame_id) {
  RTC_DCHECK(FirstPacketInSubFrame());
  frame_id_ = frame_id;
}

rtc::ArrayView<const uint16_t>
RtpGenericFrameDescriptor::FrameDependenciesDiffs() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  return rtc::MakeArrayView(frame_deps_id_diffs_, num_frame_deps_);
}

bool RtpGenericFrameDescriptor::AddFrameDependencyDiff(uint16_t fdiff) {
  RTC_DCHECK(FirstPacketInSubFrame());
  if (num_frame_deps_ == kMaxNumFrameDependencies)
    return false;
  if (fdiff == 0)
    return false;
  RTC_DCHECK_LT(fdiff, 1 << 14);
  RTC_DCHECK_GT(fdiff, 0);
  frame_deps_id_diffs_[num_frame_deps_] = fdiff;
  num_frame_deps_++;
  return true;
}

void RtpGenericFrameDescriptor::SetByteRepresentation(
    rtc::ArrayView<const uint8_t> byte_representation) {
  byte_representation_.assign(byte_representation.begin(),
                              byte_representation.end());
}

rtc::ArrayView<const uint8_t>
RtpGenericFrameDescriptor::GetByteRepresentation() {
  return byte_representation_;
}

}  // namespace webrtc
<commit_msg>Ensure GenericFrameDescriptor byte representation match<commit_after>/*
 *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"

#include <cstdint>

#include "rtc_base/checks.h"

namespace webrtc {

constexpr int RtpGenericFrameDescriptor::kMaxNumFrameDependencies;
constexpr int RtpGenericFrameDescriptor::kMaxTemporalLayers;
constexpr int RtpGenericFrameDescriptor::kMaxSpatialLayers;

RtpGenericFrameDescriptor::RtpGenericFrameDescriptor() = default;
RtpGenericFrameDescriptor::RtpGenericFrameDescriptor(
    const RtpGenericFrameDescriptor&) = default;
RtpGenericFrameDescriptor::~RtpGenericFrameDescriptor() = default;

int RtpGenericFrameDescriptor::TemporalLayer() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  return temporal_layer_;
}

void RtpGenericFrameDescriptor::SetTemporalLayer(int temporal_layer) {
  RTC_DCHECK_GE(temporal_layer, 0);
  RTC_DCHECK_LT(temporal_layer, kMaxTemporalLayers);
  temporal_layer_ = temporal_layer;
}

int RtpGenericFrameDescriptor::SpatialLayer() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  int layer = 0;
  uint8_t spatial_layers = spatial_layers_;
  while (spatial_layers_ != 0 && !(spatial_layers & 1)) {
    spatial_layers >>= 1;
    layer++;
  }
  return layer;
}

uint8_t RtpGenericFrameDescriptor::SpatialLayersBitmask() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  return spatial_layers_;
}

void RtpGenericFrameDescriptor::SetSpatialLayersBitmask(
    uint8_t spatial_layers) {
  RTC_DCHECK(FirstPacketInSubFrame());
  spatial_layers_ = spatial_layers;
}

void RtpGenericFrameDescriptor::SetResolution(int width, int height) {
  RTC_DCHECK(FirstPacketInSubFrame());
  RTC_DCHECK_GE(width, 0);
  RTC_DCHECK_LE(width, 0xFFFF);
  RTC_DCHECK_GE(height, 0);
  RTC_DCHECK_LE(height, 0xFFFF);
  width_ = width;
  height_ = height;
}

uint16_t RtpGenericFrameDescriptor::FrameId() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  return frame_id_;
}

void RtpGenericFrameDescriptor::SetFrameId(uint16_t frame_id) {
  RTC_DCHECK(FirstPacketInSubFrame());
  frame_id_ = frame_id;
}

rtc::ArrayView<const uint16_t>
RtpGenericFrameDescriptor::FrameDependenciesDiffs() const {
  RTC_DCHECK(FirstPacketInSubFrame());
  return rtc::MakeArrayView(frame_deps_id_diffs_, num_frame_deps_);
}

bool RtpGenericFrameDescriptor::AddFrameDependencyDiff(uint16_t fdiff) {
  RTC_DCHECK(FirstPacketInSubFrame());
  if (num_frame_deps_ == kMaxNumFrameDependencies)
    return false;
  if (fdiff == 0)
    return false;
  RTC_DCHECK_LT(fdiff, 1 << 14);
  RTC_DCHECK_GT(fdiff, 0);
  frame_deps_id_diffs_[num_frame_deps_] = fdiff;
  num_frame_deps_++;
  return true;
}

void RtpGenericFrameDescriptor::SetByteRepresentation(
    rtc::ArrayView<const uint8_t> byte_representation) {
  RTC_CHECK(!byte_representation.empty());
  byte_representation_.assign(byte_representation.begin(),
                              byte_representation.end());
  // Clear end_of_subframe bit.
  // Because ByteRepresentation is used for frame authentication, bit describing
  // position of the packet in the frame shouldn't be part of it.
  // This match RtpVideoSender where descriptor is passed for authentication
  // before end_of_subframe bit is decided and set, i.e. it is always 0.
  byte_representation_[0] &= ~0x40;
}

rtc::ArrayView<const uint8_t>
RtpGenericFrameDescriptor::GetByteRepresentation() {
  return byte_representation_;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library 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; either version 2.1 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 Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_TOPOLOGY_TOPOLOGYDATAHANDLER_INL
#define SOFA_COMPONENT_TOPOLOGY_TOPOLOGYDATAHANDLER_INL

#include <sofa/component/topology/TopologyDataHandler.h>
//#include <sofa/core/topology/TopologyHandler.inl>

namespace sofa
{

namespace component
{

namespace topology
{

///////////////////// Private functions on TopologyDataHandler changes /////////////////////////////
template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::swap( unsigned int i1, unsigned int i2 )
{
    container_type& data = *(m_topologyData->beginEdit());
    value_type tmp = data[i1];
    data[i1] = data[i2];
    data[i2] = tmp;
    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::add(unsigned int nbElements,
        const sofa::helper::vector<sofa::helper::vector<unsigned int> > &ancestors,
        const sofa::helper::vector<sofa::helper::vector<double> > &coefs)
{
    // Using default values
    container_type& data = *(m_topologyData->beginEdit());
    unsigned int i0 = data.size();
    data.resize(i0+nbElements);

    for (unsigned int i = 0; i < nbElements; ++i)
    {
        value_type& t = data[i0+i];
        if (ancestors.empty() || coefs.empty())
        {
            const sofa::helper::vector< unsigned int > empty_vecint;
            const sofa::helper::vector< double > empty_vecdouble;
            this->applyCreateFunction( i0+i, t, empty_vecint, empty_vecdouble);
        }
        else
            this->applyCreateFunction( i0+i, t, ancestors[i], coefs[i] );
    }
    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::add(unsigned int nbElements,
        const sofa::helper::vector< TopologyElementType >& elems,
        const sofa::helper::vector<sofa::helper::vector<unsigned int> > &ancestors,
        const sofa::helper::vector<sofa::helper::vector<double> > &coefs)
{
    // Using default values
    container_type& data = *(m_topologyData->beginEdit());
    unsigned int i0 = data.size();
    data.resize(i0+nbElements);

    for (unsigned int i = 0; i < nbElements; ++i)
    {
        value_type& t = data[i0+i];
        if (ancestors.empty() || coefs.empty())
        {
            const sofa::helper::vector< unsigned int > empty_vecint;
            const sofa::helper::vector< double > empty_vecdouble;
            this->applyCreateFunction( i0+i, t, elems[i], empty_vecint, empty_vecdouble);
        }
        else
            this->applyCreateFunction( i0+i, t, elems[i], ancestors[i], coefs[i] );
    }
    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::move( const sofa::helper::vector<unsigned int> &indexList,
        const sofa::helper::vector< sofa::helper::vector< unsigned int > >& ancestors,
        const sofa::helper::vector< sofa::helper::vector< double > >& coefs)
{
    container_type& data = *(m_topologyData->beginEdit());

    for (unsigned int i = 0; i <indexList.size(); i++)
    {
        this->applyDestroyFunction( indexList[i], data[indexList[i]] );
        this->applyCreateFunction( indexList[i], data[indexList[i]], ancestors[i], coefs[i] );
    }

    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::remove( const sofa::helper::vector<unsigned int> &index )
{

    container_type& data = *(m_topologyData->beginEdit());
    unsigned int last = data.size() -1;

    for (unsigned int i = 0; i < index.size(); ++i)
    {
        this->applyDestroyFunction( index[i], data[index[i]] );
        this->swap( index[i], last );
        --last;
    }

    data.resize( data.size() - index.size() );
    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::renumber( const sofa::helper::vector<unsigned int> &index )
{
    container_type& data = *(m_topologyData->beginEdit());

    container_type copy = m_topologyData->getValue(); // not very efficient memory-wise, but I can see no better solution...
    for (unsigned int i = 0; i < index.size(); ++i)
        data[i] = copy[ index[i] ];

    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::addOnMovedPosition(const sofa::helper::vector<unsigned int> &indexList,
        const sofa::helper::vector<TopologyElementType> &elems)
{
    container_type& data = *(m_topologyData->beginEdit());

    // Recompute data
    sofa::helper::vector< unsigned int > ancestors;
    sofa::helper::vector< double >  coefs;
    coefs.push_back (1.0);
    ancestors.resize(1);

    for (unsigned int i = 0; i <indexList.size(); i++)
    {
        ancestors[0] = indexList[i];
        this->applyCreateFunction( indexList[i], data[indexList[i]], elems[i], ancestors, coefs );
    }
    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::removeOnMovedPosition(const sofa::helper::vector<unsigned int> &indices)
{
    container_type& data = *(m_topologyData->beginEdit());

    for (unsigned int i = 0; i <indices.size(); i++)
        this->applyDestroyFunction( indices[i], data[indices[i]] );

    m_topologyData->endEdit();

    // TODO check why this call.
    //this->remove( indices );
}

} // namespace topology

} // namespace component

} // namespace sofa

#endif // SOFA_COMPONENT_TOPOLOGY_TOPOLOGYDATAHANDLER_INL
<commit_msg>r9909/sofa : FIX: Error which causes crash when removing points in a topology<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library 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; either version 2.1 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 Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_TOPOLOGY_TOPOLOGYDATAHANDLER_INL
#define SOFA_COMPONENT_TOPOLOGY_TOPOLOGYDATAHANDLER_INL

#include <sofa/component/topology/TopologyDataHandler.h>
//#include <sofa/core/topology/TopologyHandler.inl>

namespace sofa
{

namespace component
{

namespace topology
{

///////////////////// Private functions on TopologyDataHandler changes /////////////////////////////
template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::swap( unsigned int i1, unsigned int i2 )
{
    container_type& data = *(m_topologyData->beginEdit());
    value_type tmp = data[i1];
    data[i1] = data[i2];
    data[i2] = tmp;
    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::add(unsigned int nbElements,
        const sofa::helper::vector<sofa::helper::vector<unsigned int> > &ancestors,
        const sofa::helper::vector<sofa::helper::vector<double> > &coefs)
{
    // Using default values
    container_type& data = *(m_topologyData->beginEdit());
    unsigned int i0 = data.size();
    data.resize(i0+nbElements);

    for (unsigned int i = 0; i < nbElements; ++i)
    {
        value_type& t = data[i0+i];
        if (ancestors.empty() || coefs.empty())
        {
            const sofa::helper::vector< unsigned int > empty_vecint;
            const sofa::helper::vector< double > empty_vecdouble;
            this->applyCreateFunction( i0+i, t, empty_vecint, empty_vecdouble);
        }
        else
            this->applyCreateFunction( i0+i, t, ancestors[i], coefs[i] );
    }
    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::add(unsigned int nbElements,
        const sofa::helper::vector< TopologyElementType >& elems,
        const sofa::helper::vector<sofa::helper::vector<unsigned int> > &ancestors,
        const sofa::helper::vector<sofa::helper::vector<double> > &coefs)
{
    // Using default values
    container_type& data = *(m_topologyData->beginEdit());
    unsigned int i0 = data.size();
    data.resize(i0+nbElements);

    for (unsigned int i = 0; i < nbElements; ++i)
    {
        value_type& t = data[i0+i];
        if (ancestors.empty() || coefs.empty())
        {
            const sofa::helper::vector< unsigned int > empty_vecint;
            const sofa::helper::vector< double > empty_vecdouble;
            this->applyCreateFunction( i0+i, t, elems[i], empty_vecint, empty_vecdouble);
        }
        else
            this->applyCreateFunction( i0+i, t, elems[i], ancestors[i], coefs[i] );
    }
    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::move( const sofa::helper::vector<unsigned int> &indexList,
        const sofa::helper::vector< sofa::helper::vector< unsigned int > >& ancestors,
        const sofa::helper::vector< sofa::helper::vector< double > >& coefs)
{
    container_type& data = *(m_topologyData->beginEdit());

    for (unsigned int i = 0; i <indexList.size(); i++)
    {
        this->applyDestroyFunction( indexList[i], data[indexList[i]] );
        this->applyCreateFunction( indexList[i], data[indexList[i]], ancestors[i], coefs[i] );
    }

    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::remove( const sofa::helper::vector<unsigned int> &index )
{

	container_type& data = *(m_topologyData->beginEdit());
	if (data.size()>0) {
		unsigned int last = data.size() -1;

		for (unsigned int i = 0; i < index.size(); ++i)
		{
			this->applyDestroyFunction( index[i], data[index[i]] );
			this->swap( index[i], last );
			--last;
		}

		data.resize( data.size() - index.size() );
	}
	m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::renumber( const sofa::helper::vector<unsigned int> &index )
{
    container_type& data = *(m_topologyData->beginEdit());

    container_type copy = m_topologyData->getValue(); // not very efficient memory-wise, but I can see no better solution...
    for (unsigned int i = 0; i < index.size(); ++i)
        data[i] = copy[ index[i] ];

    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::addOnMovedPosition(const sofa::helper::vector<unsigned int> &indexList,
        const sofa::helper::vector<TopologyElementType> &elems)
{
    container_type& data = *(m_topologyData->beginEdit());

    // Recompute data
    sofa::helper::vector< unsigned int > ancestors;
    sofa::helper::vector< double >  coefs;
    coefs.push_back (1.0);
    ancestors.resize(1);

    for (unsigned int i = 0; i <indexList.size(); i++)
    {
        ancestors[0] = indexList[i];
        this->applyCreateFunction( indexList[i], data[indexList[i]], elems[i], ancestors, coefs );
    }
    m_topologyData->endEdit();
}

template <typename TopologyElementType, typename VecT>
void TopologyDataHandler <TopologyElementType, VecT>::removeOnMovedPosition(const sofa::helper::vector<unsigned int> &indices)
{
    container_type& data = *(m_topologyData->beginEdit());

    for (unsigned int i = 0; i <indices.size(); i++)
        this->applyDestroyFunction( indices[i], data[indices[i]] );

    m_topologyData->endEdit();

    // TODO check why this call.
    //this->remove( indices );
}

} // namespace topology

} // namespace component

} // namespace sofa

#endif // SOFA_COMPONENT_TOPOLOGY_TOPOLOGYDATAHANDLER_INL
<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * InSituMPIReader.h
 * Class to exchange data using MPI between Writer and Reader
 *  partition of an application
 * It requires MPI
 *
 *  Created on: Dec 18, 2017
 *      Author: Norbert Podhorszki pnorbert@ornl.gov
 */

#include "InSituMPIFunctions.h"

#include <chrono>
#include <fstream>
#include <iostream>
#include <thread> // sleep_for

namespace adios2
{

namespace insitumpi
{

std::vector<int> FindPeers(const MPI_Comm comm, const std::string &name,
                           const bool amIWriter, const MPI_Comm commWorld)
{
    std::vector<int> mylist;   // 'our' ranks in the world comm
    std::vector<int> peerlist; // 'their' ranks in the world comm

    int rank, nproc;
    MPI_Comm_rank(comm, &rank);
    MPI_Comm_size(comm, &nproc);

    int wrank, wnproc;
    MPI_Comm_rank(commWorld, &wrank);
    MPI_Comm_size(commWorld, &wnproc);

    if (wnproc == nproc)
    {
        return peerlist;
    }

    mylist.reserve(nproc);
    MPI_Gather(&wrank, 1, MPI_INT, mylist.data(), 1, MPI_INT, 0, comm);

    std::string ofName;
    std::string ifName;
    if (amIWriter)
    {
        ofName = name + "_insitumpi_writers";
        ifName = name + "_insitumpi_readers";
    }
    else
    {
        ofName = name + "_insitumpi_readers";
        ifName = name + "_insitumpi_writers";
    }
    std::string ofNameTmp = ofName + ".tmp";

    int pnproc; // peer nproc

    if (!rank)
    {
        std::ofstream outf(ofNameTmp, std::ios::out | std::ios::binary);
        outf.write(reinterpret_cast<char *>(&nproc), sizeof(int));
        outf.write(reinterpret_cast<char *>(mylist.data()),
                   nproc * sizeof(int));
        outf.close();
        int result = std::rename(ofNameTmp.c_str(), ofName.c_str());
        if (result != 0)
        {
            std::cerr << "ADIOS2 FindPeers error renaming file " << ofNameTmp
                      << " to " << ofNameTmp << std::endl;
        }
        // std::cout << "rank " << wrank << ": Created info file " << ofName
        //          << std::endl;

        std::ifstream inpf;
        inpf.open(ifName, std::ios::in | std::ios::binary);
        while (!inpf.is_open())
        {
            // std::cout << "rank " << wrank
            //          << ": Waiting for peers to create info file..."
            //          << std::endl;
            std::chrono::milliseconds timespan(500);
            std::this_thread::sleep_for(timespan);
            inpf.open(ifName, std::ios::in | std::ios::binary);
        }
        inpf.read((char *)&pnproc, sizeof(int));
        // std::cout << "rank " << wrank << ": #pnproc = " << pnproc <<
        // std::endl;
        peerlist.resize(pnproc);
        inpf.read((char *)peerlist.data(), pnproc * sizeof(int));
        inpf.close();
        // std::cout << "rank " << wrank << ": Read peer info file " << ifName
        //          << std::endl;
    }

    MPI_Bcast(&pnproc, 1, MPI_INT, 0, comm);
    if (rank)
    {
        peerlist.resize(pnproc);
    }
    MPI_Bcast(peerlist.data(), pnproc, MPI_INT, 0, comm);

    // std::cout << "rank " << wrank << ": FindPeers " << wrank
    //          << (amIWriter ? " Writer" : " Reader")
    //          << ". #peers=" << peerlist.size() << " #pnproc=" << pnproc
    //          << std::endl;

    if (!rank)
    {
        std::remove(ifName.c_str());
    }

    return peerlist;
}

std::vector<int> AssignPeers(const int rank, const int nproc,
                             const std::vector<int> &allPeers)
{
    int nAllPeers = allPeers.size();

    std::vector<int> directPeers;

    if (!nAllPeers)
    {
        return directPeers;
    }
    else if (nproc == nAllPeers)
    {
        // one-to-one direct assignment
        directPeers.push_back(allPeers[rank]);
    }
    else if (nproc < nAllPeers)
    {
        int nDirectPeers = nAllPeers / nproc;
        int startPos = rank * nDirectPeers;
        if (rank < nAllPeers % nproc)
        {
            nDirectPeers++;
            startPos += rank;
        }
        else
        {
            startPos += nAllPeers % nproc;
        }
        auto first = allPeers.begin() + startPos;
        auto last = allPeers.begin() + startPos + nDirectPeers;
        directPeers.insert(directPeers.begin(), first, last);
        // std::cout << "rank " << rank << ": nproc=" << nproc
        //          << " npeers=" << nDirectPeers << " start=" << startPos
        //          << " peers=[";
        // for (const auto i : directPeers)
        //    std::cout << i << " ";
        // std::cout << "]" << std::endl;
    }
    else if (nproc > nAllPeers)
    {
        int base = nproc / nAllPeers;
        int peerRank = -1;
        int pos = 0;
        // std::cout << "rank " << rank << ": nproc=" << nproc
        //          << " npeers=" << nAllPeers << " base=" << base << std::endl;

        while (peerRank < nAllPeers && pos <= rank)
        {
            peerRank++;
            pos += base;
            if (peerRank < nproc % nAllPeers)
            {
                pos++;
            }
            // std::cout << " peerRank=" << peerRank << " pos=" << pos
            //          << std::endl;
        }
        // std::cout << " final peerRank=" << peerRank << " pos=" << pos
        //          << std::endl;
        directPeers.push_back(allPeers[peerRank]);
    }
    return directPeers;
}

int ConnectDirectPeers(const MPI_Comm commWorld, const bool IAmSender,
                       const bool IAmWriterRoot, const int globalRank,
                       const std::vector<int> &peers)
{
    /* Return value:
         Reader: write root global rank or -1
         Writer: am I first connect to my Reader?
    */
    int retval;
    MPI_Status status;

    /* Writers send msg to each connected Reader, Writer Root sends different
     * value than others */
    int writeRootToken = (IAmWriterRoot ? 1 : 0);
    retval = -1;
    for (const auto peerRank : peers)
    {
        if (IAmSender)
        {
            // std::cout << " Send from " << rank << " to " << peerRank
            //          << std::endl;
            MPI_Send(&writeRootToken, 1, MPI_INT, peerRank, MpiTags::Connect,
                     commWorld);
        }
        else
        {
            // std::cout << " Recv from " << peerRank << " by " << rank
            //          << std::endl;
            MPI_Recv(&writeRootToken, 1, MPI_INT, peerRank, MpiTags::Connect,
                     commWorld, &status);
            if (writeRootToken == 1)
                retval = peerRank;
        }
    }

    /* Each Reader selects one Writer to be main contact (for BeginStep) */
    int firstAssignedWriterToken = 1;
    for (const auto peerRank : peers)
    {
        if (IAmSender)
        {
            // std::cout << " Receive reader selection from " << peerRank << "
            // by " << rank
            //          << std::endl;
            MPI_Recv(&firstAssignedWriterToken, 1, MPI_INT, peerRank,
                     MpiTags::Connect, commWorld, &status);
            retval = firstAssignedWriterToken;
            /* Note that in case there are less Writer than Readers, here retval
               is set to 1
               multiple times. A mix of 0s and 1s cannot happen */
        }
        else
        {
            // std::cout << " Send reader selection from " << rank << " to " <<
            // peerRank
            //          << std::endl;
            MPI_Send(&firstAssignedWriterToken, 1, MPI_INT, peerRank,
                     MpiTags::Connect, commWorld);
            firstAssignedWriterToken = 0;
        }
    }
    return retval;
}

std::vector<MPI_Status> CompleteRequests(std::vector<MPI_Request> &requests,
                                         const bool IAmWriter,
                                         const int localRank)
{
    std::vector<MPI_Status> statuses(requests.size());

    const auto ierr =
        MPI_Waitall(requests.size(), requests.data(), statuses.data());

    if (ierr == MPI_ERR_IN_STATUS)
    {
        for (auto i = 0; i < requests.size(); i++)
        {
            if (statuses[i].MPI_ERROR == MPI_ERR_PENDING)
            {
                std::cerr << "InSituMPI " << (IAmWriter ? "Writer" : "Reader")
                          << " " << localRank
                          << " Pending transfer error when waiting for all "
                             "data transfers to complete. request id = "
                          << i << std::endl;
            }
            else if (statuses[i].MPI_ERROR != MPI_SUCCESS)
            {
                std::cerr << "InSituMPI " << (IAmWriter ? "Writer" : "Reader")
                          << " " << localRank
                          << " MPI Error when waiting for all data transfers "
                             "to complete. Error code = "
                          << ierr << std::endl;
            }
        }
    }

    return statuses;
}

} // end namespace insitumpi

} // end namespace adios2
<commit_msg>Remove container-overflow error recognized by AddressSanitizer.<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * InSituMPIReader.h
 * Class to exchange data using MPI between Writer and Reader
 *  partition of an application
 * It requires MPI
 *
 *  Created on: Dec 18, 2017
 *      Author: Norbert Podhorszki pnorbert@ornl.gov
 */

#include "InSituMPIFunctions.h"

#include <chrono>
#include <fstream>
#include <iostream>
#include <thread> // sleep_for

namespace adios2
{

namespace insitumpi
{

std::vector<int> FindPeers(const MPI_Comm comm, const std::string &name,
                           const bool amIWriter, const MPI_Comm commWorld)
{
    std::vector<int> mylist;   // 'our' ranks in the world comm
    std::vector<int> peerlist; // 'their' ranks in the world comm

    int rank, nproc;
    MPI_Comm_rank(comm, &rank);
    MPI_Comm_size(comm, &nproc);

    int wrank, wnproc;
    MPI_Comm_rank(commWorld, &wrank);
    MPI_Comm_size(commWorld, &wnproc);

    if (wnproc == nproc)
    {
        return peerlist;
    }

    mylist.resize(nproc);
    MPI_Gather(&wrank, 1, MPI_INT, mylist.data(), 1, MPI_INT, 0, comm);

    std::string ofName;
    std::string ifName;
    if (amIWriter)
    {
        ofName = name + "_insitumpi_writers";
        ifName = name + "_insitumpi_readers";
    }
    else
    {
        ofName = name + "_insitumpi_readers";
        ifName = name + "_insitumpi_writers";
    }
    std::string ofNameTmp = ofName + ".tmp";

    int pnproc; // peer nproc

    if (!rank)
    {
        std::ofstream outf(ofNameTmp, std::ios::out | std::ios::binary);
        outf.write(reinterpret_cast<char *>(&nproc), sizeof(int));
        outf.write(reinterpret_cast<char *>(mylist.data()),
                   nproc * sizeof(int));
        outf.close();
        int result = std::rename(ofNameTmp.c_str(), ofName.c_str());
        if (result != 0)
        {
            std::cerr << "ADIOS2 FindPeers error renaming file " << ofNameTmp
                      << " to " << ofNameTmp << std::endl;
        }
        // std::cout << "rank " << wrank << ": Created info file " << ofName
        //          << std::endl;

        std::ifstream inpf;
        inpf.open(ifName, std::ios::in | std::ios::binary);
        while (!inpf.is_open())
        {
            // std::cout << "rank " << wrank
            //          << ": Waiting for peers to create info file..."
            //          << std::endl;
            std::chrono::milliseconds timespan(500);
            std::this_thread::sleep_for(timespan);
            inpf.open(ifName, std::ios::in | std::ios::binary);
        }
        inpf.read((char *)&pnproc, sizeof(int));
        // std::cout << "rank " << wrank << ": #pnproc = " << pnproc <<
        // std::endl;
        peerlist.resize(pnproc);
        inpf.read((char *)peerlist.data(), pnproc * sizeof(int));
        inpf.close();
        // std::cout << "rank " << wrank << ": Read peer info file " << ifName
        //          << std::endl;
    }

    MPI_Bcast(&pnproc, 1, MPI_INT, 0, comm);
    if (rank)
    {
        peerlist.resize(pnproc);
    }
    MPI_Bcast(peerlist.data(), pnproc, MPI_INT, 0, comm);

    // std::cout << "rank " << wrank << ": FindPeers " << wrank
    //          << (amIWriter ? " Writer" : " Reader")
    //          << ". #peers=" << peerlist.size() << " #pnproc=" << pnproc
    //          << std::endl;

    if (!rank)
    {
        std::remove(ifName.c_str());
    }

    return peerlist;
}

std::vector<int> AssignPeers(const int rank, const int nproc,
                             const std::vector<int> &allPeers)
{
    int nAllPeers = allPeers.size();

    std::vector<int> directPeers;

    if (!nAllPeers)
    {
        return directPeers;
    }
    else if (nproc == nAllPeers)
    {
        // one-to-one direct assignment
        directPeers.push_back(allPeers[rank]);
    }
    else if (nproc < nAllPeers)
    {
        int nDirectPeers = nAllPeers / nproc;
        int startPos = rank * nDirectPeers;
        if (rank < nAllPeers % nproc)
        {
            nDirectPeers++;
            startPos += rank;
        }
        else
        {
            startPos += nAllPeers % nproc;
        }
        auto first = allPeers.begin() + startPos;
        auto last = allPeers.begin() + startPos + nDirectPeers;
        directPeers.insert(directPeers.begin(), first, last);
        // std::cout << "rank " << rank << ": nproc=" << nproc
        //          << " npeers=" << nDirectPeers << " start=" << startPos
        //          << " peers=[";
        // for (const auto i : directPeers)
        //    std::cout << i << " ";
        // std::cout << "]" << std::endl;
    }
    else if (nproc > nAllPeers)
    {
        int base = nproc / nAllPeers;
        int peerRank = -1;
        int pos = 0;
        // std::cout << "rank " << rank << ": nproc=" << nproc
        //          << " npeers=" << nAllPeers << " base=" << base << std::endl;

        while (peerRank < nAllPeers && pos <= rank)
        {
            peerRank++;
            pos += base;
            if (peerRank < nproc % nAllPeers)
            {
                pos++;
            }
            // std::cout << " peerRank=" << peerRank << " pos=" << pos
            //          << std::endl;
        }
        // std::cout << " final peerRank=" << peerRank << " pos=" << pos
        //          << std::endl;
        directPeers.push_back(allPeers[peerRank]);
    }
    return directPeers;
}

int ConnectDirectPeers(const MPI_Comm commWorld, const bool IAmSender,
                       const bool IAmWriterRoot, const int globalRank,
                       const std::vector<int> &peers)
{
    /* Return value:
         Reader: write root global rank or -1
         Writer: am I first connect to my Reader?
    */
    int retval;
    MPI_Status status;

    /* Writers send msg to each connected Reader, Writer Root sends different
     * value than others */
    int writeRootToken = (IAmWriterRoot ? 1 : 0);
    retval = -1;
    for (const auto peerRank : peers)
    {
        if (IAmSender)
        {
            // std::cout << " Send from " << rank << " to " << peerRank
            //          << std::endl;
            MPI_Send(&writeRootToken, 1, MPI_INT, peerRank, MpiTags::Connect,
                     commWorld);
        }
        else
        {
            // std::cout << " Recv from " << peerRank << " by " << rank
            //          << std::endl;
            MPI_Recv(&writeRootToken, 1, MPI_INT, peerRank, MpiTags::Connect,
                     commWorld, &status);
            if (writeRootToken == 1)
                retval = peerRank;
        }
    }

    /* Each Reader selects one Writer to be main contact (for BeginStep) */
    int firstAssignedWriterToken = 1;
    for (const auto peerRank : peers)
    {
        if (IAmSender)
        {
            // std::cout << " Receive reader selection from " << peerRank << "
            // by " << rank
            //          << std::endl;
            MPI_Recv(&firstAssignedWriterToken, 1, MPI_INT, peerRank,
                     MpiTags::Connect, commWorld, &status);
            retval = firstAssignedWriterToken;
            /* Note that in case there are less Writer than Readers, here retval
               is set to 1
               multiple times. A mix of 0s and 1s cannot happen */
        }
        else
        {
            // std::cout << " Send reader selection from " << rank << " to " <<
            // peerRank
            //          << std::endl;
            MPI_Send(&firstAssignedWriterToken, 1, MPI_INT, peerRank,
                     MpiTags::Connect, commWorld);
            firstAssignedWriterToken = 0;
        }
    }
    return retval;
}

std::vector<MPI_Status> CompleteRequests(std::vector<MPI_Request> &requests,
                                         const bool IAmWriter,
                                         const int localRank)
{
    std::vector<MPI_Status> statuses(requests.size());

    const auto ierr =
        MPI_Waitall(requests.size(), requests.data(), statuses.data());

    if (ierr == MPI_ERR_IN_STATUS)
    {
        for (auto i = 0; i < requests.size(); i++)
        {
            if (statuses[i].MPI_ERROR == MPI_ERR_PENDING)
            {
                std::cerr << "InSituMPI " << (IAmWriter ? "Writer" : "Reader")
                          << " " << localRank
                          << " Pending transfer error when waiting for all "
                             "data transfers to complete. request id = "
                          << i << std::endl;
            }
            else if (statuses[i].MPI_ERROR != MPI_SUCCESS)
            {
                std::cerr << "InSituMPI " << (IAmWriter ? "Writer" : "Reader")
                          << " " << localRank
                          << " MPI Error when waiting for all data transfers "
                             "to complete. Error code = "
                          << ierr << std::endl;
            }
        }
    }

    return statuses;
}

} // end namespace insitumpi

} // end namespace adios2
<|endoftext|>


<commit_before>#pragma once

#include <algorithm>
#include <iterator>
#include <memory>
#include <numeric>
#include <set>
#include <unordered_set>
#include <vector>

#include "ConcatIterator.hpp"
#include "Distinct.hpp"
#include "ElementAt.hpp"
#include "IntIterator.hpp"
#include "Last.hpp"
#include "MinMax.hpp"
#include "SelectIterator.hpp"
#include "Skip.hpp"
#include "TakeIterator.hpp"
#include "WhereIterator.hpp"
#include "ZipIterator.hpp"

namespace Linqpp
{
    template <class Iterator>
    class Enumeration;

    template <class Iterator>
    auto From(Iterator first, Iterator last)
    {
        return Enumeration<Iterator>(first, last);
    }

    template <class Container>
    auto From(Container&& container)
    {
        return From(std::begin(std::forward<Container>(container)), std::end(std::forward<Container>(container)));
    }

    template <class Iterator>
    class Enumeration
    {
    private:
        Iterator _first;
        Iterator _last;

    public:
        using value_type = typename std::iterator_traits<Iterator>::value_type;

    public:
        Enumeration(Iterator first, Iterator last) : _first(first), _last(last) { }

    public:
        auto begin() const { return _first; }
        auto end() const { return _last; }

    public:
        template <class Seed, class BinaryFunction>
        auto Aggregate(Seed const& seed, BinaryFunction binaryFunction) const { return std::accumulate(_first, _last, seed, binaryFunction); }

        template <class BinaryFunction>
        auto Aggregate(BinaryFunction binaryFunction) const { decltype(auto) first = First(); return std::accumulate(std::next(_first), _last, first, binaryFunction); }

        bool Any() const { return _first != _last; }

        template <class Predicate>
        bool Any(Predicate predicate) const { return std::any_of(_first, _last, predicate); }

        template <class Predicate>
        bool All(Predicate predicate) const { return std::all_of(_first, _last, predicate); }

        template <class Container>
        auto Concat(Container&& container) const
        {
            auto cBegin = std::begin(std::forward<Container>(container));
            auto cEnd = std::end(std::forward<Container>(container));
            auto first = CreateConcatIterator(_first, _last, cBegin, cBegin);
            auto last = CreateConcatIterator(_last, _last, cBegin, cEnd);

            return From(first, last);
        }

        template <class T, class CompareFunction>
        auto Contains(T const& t, CompareFunction compareFunction) const { return Any([=](const auto& t2) { return compareFunction(t, t2); }); }

        template <class T>
        auto Contains(T const& t) const { return Contains(t, std::equal_to<>()); }

        size_t Count() const { return std::distance(_first, _last); }

        template <class Predicate>
        size_t Count(Predicate predicate) const { return std::count_if(_first, _last, predicate); }

        auto Distinct() const { return Linqpp::Distinct(_first, _last); }

        template <class LessThanComparer>
        auto Distinct(LessThanComparer comparer) const { return Linqpp::Distinct(_first, _last, comparer); }

        template <class EqualityComparer, class Hash>
        auto Distinct(EqualityComparer comparer, Hash hash) const { return Linqpp::Distinct(_first, _last, comparer, hash); }

        decltype(auto) ElementAt(size_t i) const { return Linqpp::ElementAt(_first, i, typename std::iterator_traits<Iterator>::iterator_category()); }

        value_type ElementAtOrDefault(size_t i) const { return Linqpp::ElementAtOrDefault(_first, _last, i, typename std::iterator_traits<Iterator>::iterator_category()); }

        decltype(auto) First() const { return *_first; }

        template <class Predicate>
        decltype(auto) First(Predicate predicate) const { return *std::find_if(_first, _last, predicate); }

        value_type FirstOrDefault() const { return Any() ? First() : value_type(); }

        template <class Predicate>
        value_type FirstOrDefault(Predicate predicate) const { auto found = std::find_if(_first, _last, predicate); return found != _last ? *found : value_type(); }

        decltype(auto) Last() const { return *Linqpp::Last(_first, _last); }

        template <class Predicate>
        decltype(auto) Last(Predicate predicate) const { return *Linqpp::Last(_first, _last, predicate); }

        value_type LastOrDefault() const { return Any() ? Last() : value_type(); }

        template <class Predicate>
        value_type LastOrDefault(Predicate predicate) const { auto found = Linqpp::Last(_first, _last, predicate); return found != _last ? *found : value_type(); }

        decltype(auto) Max() const { return Linqpp::Max(_first, _last); }

        template <class UnaryFunction>
        decltype(auto) Max(UnaryFunction unaryFunction) const { return Select(unaryFunction).Max(); }

        decltype(auto) Min() const { return Linqpp::Min(_first, _last); }

        template <class UnaryFunction>
        decltype(auto) Min(UnaryFunction unaryFunction) const { return Select(unaryFunction).Min(); }

        auto Reverse() const { return From(std::make_reverse_iterator(_last), std::make_reverse_iterator(_first)); }

        template <class UnaryFunction>
        auto Select(UnaryFunction unaryFunction) const { return From(CreateSelectIterator(_first, unaryFunction), CreateSelectIterator(_last, unaryFunction)); }

        auto Skip(size_t n) const { return From(Linqpp::Skip(_first, n, _last), _last); }

        auto Take(size_t n) const { return GetEnumeratorFromTake(_first, n, _last); }

        auto ToVector() const { return std::vector<value_type>(_first, _last); }

        template <class Predicate>
        auto Where(Predicate predicate) const
        {
            auto first = CreateWhereIterator(_first, _last, predicate);
            auto last = CreateWhereIterator(_last, _last, predicate);
            return From(first, last);
        }

        template <class Container, class BinaryFunction>
        auto Zip(Container&& container, BinaryFunction binaryFunction) const
        {
            auto cBegin = std::begin(std::forward<Container>(container));
            auto cEnd = std::end(std::forward<Container>(container));

            return From(CreateZipIterator(_first, cBegin, binaryFunction), CreateZipIterator(_last, cEnd, binaryFunction));
        }
    };

    struct Enumerable
    {
        template <class Int>
        static auto Range(Int start, Int count)
        {
            return From(CreateIntIterator(start), CreateIntIterator(start + count));
        }
    };
}
<commit_msg>use begin() and end() instead of _first and _last<commit_after>#pragma once

#include <algorithm>
#include <iterator>
#include <memory>
#include <numeric>
#include <set>
#include <unordered_set>
#include <vector>

#include "ConcatIterator.hpp"
#include "Distinct.hpp"
#include "ElementAt.hpp"
#include "IntIterator.hpp"
#include "Last.hpp"
#include "MinMax.hpp"
#include "SelectIterator.hpp"
#include "Skip.hpp"
#include "TakeIterator.hpp"
#include "WhereIterator.hpp"
#include "ZipIterator.hpp"

namespace Linqpp
{
    template <class Iterator>
    class Enumeration;

    template <class Iterator>
    auto From(Iterator first, Iterator last)
    {
        return Enumeration<Iterator>(first, last);
    }

    template <class Container>
    auto From(Container&& container)
    {
        return From(std::begin(std::forward<Container>(container)), std::end(std::forward<Container>(container)));
    }

    template <class Iterator>
    class Enumeration
    {
    private:
        Iterator _first;
        Iterator _last;

    public:
        using value_type = typename std::iterator_traits<Iterator>::value_type;

    public:
        Enumeration(Iterator first, Iterator last) : _first(first), _last(last) { }

    public:
        auto begin() const { return _first; }
        auto end() const { return _last; }

    public:
        template <class Seed, class BinaryFunction>
        auto Aggregate(Seed const& seed, BinaryFunction binaryFunction) const { return std::accumulate(begin(), end(), seed, binaryFunction); }

        template <class BinaryFunction>
        auto Aggregate(BinaryFunction binaryFunction) const { decltype(auto) first = First(); return std::accumulate(std::next(begin()), end(), first, binaryFunction); }

        bool Any() const { return begin() != end(); }

        template <class Predicate>
        bool Any(Predicate predicate) const { return std::any_of(begin(), end(), predicate); }

        template <class Predicate>
        bool All(Predicate predicate) const { return std::all_of(begin(), end(), predicate); }

        template <class Container>
        auto Concat(Container&& container) const
        {
            auto cBegin = std::begin(std::forward<Container>(container));
            auto cEnd = std::end(std::forward<Container>(container));
            auto first = CreateConcatIterator(begin(), end(), cBegin, cBegin);
            auto last = CreateConcatIterator(end(), end(), cBegin, cEnd);

            return From(first, last);
        }

        template <class T, class CompareFunction>
        auto Contains(T const& t, CompareFunction compareFunction) const { return Any([=](const auto& t2) { return compareFunction(t, t2); }); }

        template <class T>
        auto Contains(T const& t) const { return Contains(t, std::equal_to<>()); }

        size_t Count() const { return std::distance(begin(), end()); }

        template <class Predicate>
        size_t Count(Predicate predicate) const { return std::count_if(begin(), end(), predicate); }

        auto Distinct() const { return Linqpp::Distinct(begin(), end()); }

        template <class LessThanComparer>
        auto Distinct(LessThanComparer comparer) const { return Linqpp::Distinct(begin(), end(), comparer); }

        template <class EqualityComparer, class Hash>
        auto Distinct(EqualityComparer comparer, Hash hash) const { return Linqpp::Distinct(begin(), end(), comparer, hash); }

        decltype(auto) ElementAt(size_t i) const { return Linqpp::ElementAt(begin(), i, typename std::iterator_traits<Iterator>::iterator_category()); }

        value_type ElementAtOrDefault(size_t i) const { return Linqpp::ElementAtOrDefault(begin(), end(), i, typename std::iterator_traits<Iterator>::iterator_category()); }

        decltype(auto) First() const { return *begin(); }

        template <class Predicate>
        decltype(auto) First(Predicate predicate) const { return *std::find_if(begin(), end(), predicate); }

        value_type FirstOrDefault() const { return Any() ? First() : value_type(); }

        template <class Predicate>
        value_type FirstOrDefault(Predicate predicate) const { auto found = std::find_if(begin(), end(), predicate); return found != end() ? *found : value_type(); }

        decltype(auto) Last() const { return *Linqpp::Last(begin(), end()); }

        template <class Predicate>
        decltype(auto) Last(Predicate predicate) const { return *Linqpp::Last(begin(), end(), predicate); }

        value_type LastOrDefault() const { return Any() ? Last() : value_type(); }

        template <class Predicate>
        value_type LastOrDefault(Predicate predicate) const { auto found = Linqpp::Last(begin(), end(), predicate); return found != end() ? *found : value_type(); }

        decltype(auto) Max() const { return Linqpp::Max(begin(), end()); }

        template <class UnaryFunction>
        decltype(auto) Max(UnaryFunction unaryFunction) const { return Select(unaryFunction).Max(); }

        decltype(auto) Min() const { return Linqpp::Min(begin(), end()); }

        template <class UnaryFunction>
        decltype(auto) Min(UnaryFunction unaryFunction) const { return Select(unaryFunction).Min(); }

        auto Reverse() const { return From(std::make_reverse_iterator(end()), std::make_reverse_iterator(begin())); }

        template <class UnaryFunction>
        auto Select(UnaryFunction unaryFunction) const { return From(CreateSelectIterator(begin(), unaryFunction), CreateSelectIterator(end(), unaryFunction)); }

        auto Skip(size_t n) const { return From(Linqpp::Skip(begin(), n, end()), end()); }

        auto Take(size_t n) const { return GetEnumeratorFromTake(begin(), n, end()); }

        auto ToVector() const { return std::vector<value_type>(begin(), end()); }

        template <class Predicate>
        auto Where(Predicate predicate) const
        {
            auto first = CreateWhereIterator(begin(), end(), predicate);
            auto last = CreateWhereIterator(end(), end(), predicate);
            return From(first, last);
        }

        template <class Container, class BinaryFunction>
        auto Zip(Container&& container, BinaryFunction binaryFunction) const
        {
            auto cBegin = std::begin(std::forward<Container>(container));
            auto cEnd = std::end(std::forward<Container>(container));

            return From(CreateZipIterator(begin(), cBegin, binaryFunction), CreateZipIterator(end(), cEnd, binaryFunction));
        }
    };

    struct Enumerable
    {
        template <class Int>
        static auto Range(Int start, Int count)
        {
            return From(CreateIntIterator(start), CreateIntIterator(start + count));
        }
    };
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <cstring>
#include <limits>
#include <memory>

#include <android/log.h>

#include <tbb/blocked_range2d.h>
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_init.h>

#include "body_parts_recognizer.h"
#include "cloud.h"
#include "stopwatch.h"

const Depth BACKGROUND_DEPTH = std::numeric_limits<Depth>::max();

template <typename Format> void
applyThreshold(ChannelRef<Format> & channel, Format threshold, Format bgValue)
{
  for (int i = 0; i < channel.size; ++i)
    if (channel.data[i] > threshold)
      channel.data[i] = bgValue;
}

template <typename Format> Format
selectThreshold(const ChannelRef<Format> & channel) {
  Format min = *std::min_element(channel.data, channel.data + channel.size);
  return min + 500;
}

template <typename Format> Format
replaceZeroes(ChannelRef<Format> & channel, Format replacement)
{
  std::replace(channel.data, channel.data + channel.size, Format(), replacement);
}

struct DecisionTreeCPU
{
  tbb::task_scheduler_init tbb_init;

  struct Offsets
  {
    boost::int16_t du1, dv1, du2, dv2;
  };

  struct Node
  {
    Offsets offsets;
    boost::int16_t threshold;
  };

  boost::uint16_t depth;
  std::vector<Node> nodes;
  std::vector<Label> leaves;

  DecisionTreeCPU(const char * data)
  {
    std::memcpy (&depth, data, sizeof depth);
    data += sizeof depth;

    nodes.resize ((1 << depth) - 1);
    std::memcpy (&nodes.front (), data, nodes.size () * sizeof (Node));
    data += nodes.size () * sizeof (Node);

    leaves.resize (1 << depth);
    std::memcpy (&leaves.front (), data, leaves.size () * sizeof (Label));
    data += leaves.size () * sizeof (Label);
  }

  Label
  walk(const ChannelRef<Depth> & depthChannel, int x, int y) const
  {
    unsigned nid = 0;
    Depth d0 = depthChannel.at(y, x);
    float scale = 1000.0f / d0;

    for(int node_depth = 0; node_depth < depth; ++node_depth)
    {
      const Node & node = nodes[nid];

      Depth d1 = depthChannel.atDef(y + node.offsets.dv1 * scale, x + node.offsets.du1 * scale, BACKGROUND_DEPTH);
      Depth d2 = depthChannel.atDef(y + node.offsets.dv2 * scale, x + node.offsets.du2 * scale, BACKGROUND_DEPTH);

      int feature = int (d1) - int (d2);

      if (feature > node.threshold)
        nid = nid * 2 + 2;
      else
        nid = nid * 2 + 1;
    }

    return leaves[nid - nodes.size()];
  }

  struct WalkHelper
  {
  private:
    const DecisionTreeCPU & tree;
    const ChannelRef<Depth> depth;
    std::vector<Label> & labels;

  public:
    WalkHelper(const DecisionTreeCPU & tree, Cloud & cloud, std::vector<Label> & labels)
      : tree(tree), depth(cloud.get<TagDepth>()), labels(labels)
    {
    }

    void
    operator () (const tbb::blocked_range2d<unsigned> & range) const
    {
      for (unsigned y = range.rows().begin(); y < range.rows().end(); ++y)
        for (unsigned x = range.cols().begin(); x < range.cols().end(); ++x)
          labels[x + y * depth.width] = depth.at(y, x) == BACKGROUND_DEPTH ?
                Labels::Background : tree.walk(depth, x, y);
    }
  };

  void
  eval(Cloud & cloud, std::vector<Label> & labels) const
  {
    tbb::parallel_for(
          tbb::blocked_range2d<unsigned>(0, cloud.getHeight(), 0, cloud.getWidth()),
          WalkHelper(*this, cloud, labels)
    );
  }
};

int maxElementNoTie(int num, unsigned * elements)
{
  int max_element = 0;
  unsigned max = elements[max_element];

  for (int i = 1; i < num; ++i)
  {
    unsigned val = elements[i];
    if (max < val) { max_element = i; max = val; }
    else if (max == val) { max_element = -1; }
  }

  return max_element;
}

void filterLabels(Cloud & noisy, Cloud & output, int radius)
{
  int width = noisy.getWidth(), height = noisy.getHeight();
  ChannelRef<Label> noisy_labels = noisy.get<TagBPLabel>();
  ChannelRef<Label> labels = output.get<TagBPLabel>();

  for (unsigned i = 0; i < height; ++i)
    for (unsigned j = 0; j < width; ++j)
    {
      unsigned idx = i * width + j;

      if (i < radius || i >= height - radius || j < radius || j >= width - radius || noisy_labels.data[idx] == Labels::Background)
      {
        labels.data[idx] = Labels::Background;
        continue;
      }

      int bins[Labels::NUM_LABELS] = { 0 };
      Label mode = -1;
      Label mode_count = 0;

      for (int dy = -radius; dy <= radius; ++dy)
        for (int dx = -radius; dx <= radius; ++dx)
        {
          Label current = noisy_labels.data[idx + dx + dy * width];
          ++bins[current];
          if (bins[current] > mode_count) {
            mode_count = bins[current];
            mode = current;
          }
        }

      labels.data[idx] = mode;
    }
}

struct ConsensusHelper
{
private:
  const std::vector<std::vector<Label> > & multi_labels;
  ChannelRef<Label> labels;
  const ChannelRef<Depth> depths;

public:
  ConsensusHelper(
      const std::vector<std::vector<Label> > & multi_labels,
      Cloud & cloud
  )
    : multi_labels(multi_labels), labels(cloud.get<TagBPLabel>()), depths(cloud.get<TagDepth>())
  { }

  void
  operator ()(const tbb::blocked_range2d<unsigned> & range) const
  {
    for (unsigned y = range.rows().begin(); y < range.rows().end(); ++y)
      for (unsigned x = range.cols().begin(); x < range.cols().end(); ++x)
      {
        std::size_t i = &depths.at(y, x) - depths.data;

        bool background = true;
        for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
          if (multi_labels[ti][i] != Labels::Background) background = false;

        if (background)
        {
          labels.data[i] = Labels::Background;
          continue;
        }

        unsigned bins[Labels::NUM_LABELS] = { 0 };

        for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
          ++bins[multi_labels[ti][i]];

        int consensus = maxElementNoTie(Labels::NUM_LABELS, bins);

        if (consensus == -1)
        {
          std::fill (bins, bins + Labels::NUM_LABELS, 0);
          Depth d = depths.at(y, x);

          for (int off_x = -1; off_x <= 1; ++off_x)
            for (int off_y = -1; off_y <= 1; ++off_y)
            {
              Depth off_d = depths.atDef(y + off_y, x + off_x, BACKGROUND_DEPTH);

              if (std::abs (d - off_d) < 50)
                for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
                  ++bins[multi_labels[ti][i]];
            }

          labels.data[i] = std::max_element (bins, bins + Labels::NUM_LABELS) - bins;
        }
        else
        {
          labels.data[i] = consensus;
        }
      }
  }
};

BodyPartsRecognizer::BodyPartsRecognizer(std::size_t num_trees, const char * trees[])
{
  this->trees.resize(num_trees);

  for (std::size_t i = 0; i < num_trees; ++i)
    this->trees[i].reset(new Tree(trees[i]));
}

void
BodyPartsRecognizer::recognize(Cloud & cloud) const
{
  ChannelRef<Depth> depth = cloud.get<TagDepth>();

  Stopwatch watch_threshold;

  replaceZeroes(depth, BACKGROUND_DEPTH);
  applyThreshold(depth, selectThreshold(depth), BACKGROUND_DEPTH);

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Thresholding: %d ms", watch_threshold.elapsedMs());

  std::vector<std::vector<Label> > multi_labels (trees.size ());

  for (std::size_t ti = 0; ti < trees.size (); ++ti)
  {
    Stopwatch watch_evaluation;

    multi_labels[ti].resize (cloud.getHeight() * cloud.getWidth());
    trees[ti]->eval (cloud, multi_labels[ti]);

    __android_log_print(ANDROID_LOG_INFO, "BPR", "Evaluating tree %d: %d ms", ti, watch_evaluation.elapsedMs());
  }

  Stopwatch watch_consensus;

  Cloud noisy;
  noisy.resize(cloud.getWidth(), cloud.getHeight());

  tbb::parallel_for(
        tbb::blocked_range2d<unsigned>(0, cloud.getHeight(), 0, cloud.getWidth()),
        ConsensusHelper(multi_labels, noisy)
  );

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Finding consensus: %d ms", watch_consensus.elapsedMs());

  Stopwatch watch_filtering;

  filterLabels(noisy, cloud, 2);

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Filtering labels: %d ms", watch_consensus.elapsedMs());

}
<commit_msg>TBB-ized the label filter.<commit_after>#include <algorithm>
#include <cstring>
#include <limits>
#include <memory>

#include <android/log.h>

#include <tbb/blocked_range2d.h>
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_init.h>

#include "body_parts_recognizer.h"
#include "cloud.h"
#include "stopwatch.h"

const Depth BACKGROUND_DEPTH = std::numeric_limits<Depth>::max();

template <typename Format> void
applyThreshold(ChannelRef<Format> & channel, Format threshold, Format bgValue)
{
  for (int i = 0; i < channel.size; ++i)
    if (channel.data[i] > threshold)
      channel.data[i] = bgValue;
}

template <typename Format> Format
selectThreshold(const ChannelRef<Format> & channel) {
  Format min = *std::min_element(channel.data, channel.data + channel.size);
  return min + 500;
}

template <typename Format> Format
replaceZeroes(ChannelRef<Format> & channel, Format replacement)
{
  std::replace(channel.data, channel.data + channel.size, Format(), replacement);
}

struct DecisionTreeCPU
{
  tbb::task_scheduler_init tbb_init;

  struct Offsets
  {
    boost::int16_t du1, dv1, du2, dv2;
  };

  struct Node
  {
    Offsets offsets;
    boost::int16_t threshold;
  };

  boost::uint16_t depth;
  std::vector<Node> nodes;
  std::vector<Label> leaves;

  DecisionTreeCPU(const char * data)
  {
    std::memcpy (&depth, data, sizeof depth);
    data += sizeof depth;

    nodes.resize ((1 << depth) - 1);
    std::memcpy (&nodes.front (), data, nodes.size () * sizeof (Node));
    data += nodes.size () * sizeof (Node);

    leaves.resize (1 << depth);
    std::memcpy (&leaves.front (), data, leaves.size () * sizeof (Label));
    data += leaves.size () * sizeof (Label);
  }

  Label
  walk(const ChannelRef<Depth> & depthChannel, int x, int y) const
  {
    unsigned nid = 0;
    Depth d0 = depthChannel.at(y, x);
    float scale = 1000.0f / d0;

    for(int node_depth = 0; node_depth < depth; ++node_depth)
    {
      const Node & node = nodes[nid];

      Depth d1 = depthChannel.atDef(y + node.offsets.dv1 * scale, x + node.offsets.du1 * scale, BACKGROUND_DEPTH);
      Depth d2 = depthChannel.atDef(y + node.offsets.dv2 * scale, x + node.offsets.du2 * scale, BACKGROUND_DEPTH);

      int feature = int (d1) - int (d2);

      if (feature > node.threshold)
        nid = nid * 2 + 2;
      else
        nid = nid * 2 + 1;
    }

    return leaves[nid - nodes.size()];
  }

  struct WalkHelper
  {
  private:
    const DecisionTreeCPU & tree;
    const ChannelRef<Depth> depth;
    std::vector<Label> & labels;

  public:
    WalkHelper(const DecisionTreeCPU & tree, Cloud & cloud, std::vector<Label> & labels)
      : tree(tree), depth(cloud.get<TagDepth>()), labels(labels)
    {
    }

    void
    operator () (const tbb::blocked_range2d<unsigned> & range) const
    {
      for (unsigned y = range.rows().begin(); y < range.rows().end(); ++y)
        for (unsigned x = range.cols().begin(); x < range.cols().end(); ++x)
          labels[x + y * depth.width] = depth.at(y, x) == BACKGROUND_DEPTH ?
                Labels::Background : tree.walk(depth, x, y);
    }
  };

  void
  eval(Cloud & cloud, std::vector<Label> & labels) const
  {
    tbb::parallel_for(
          tbb::blocked_range2d<unsigned>(0, cloud.getHeight(), 0, cloud.getWidth()),
          WalkHelper(*this, cloud, labels)
    );
  }
};

int maxElementNoTie(int num, unsigned * elements)
{
  int max_element = 0;
  unsigned max = elements[max_element];

  for (int i = 1; i < num; ++i)
  {
    unsigned val = elements[i];
    if (max < val) { max_element = i; max = val; }
    else if (max == val) { max_element = -1; }
  }

  return max_element;
}

struct FilterHelper
{
private:
  ChannelRef<Label> noisy, good;
  int radius;

public:
  FilterHelper(ChannelRef<Label> noisy, ChannelRef<Label> good, int radius)
    : noisy(noisy), good(good), radius(radius)
  { }

  void
  operator ()(const tbb::blocked_range2d<int> & range) const
  {
    int width = noisy.width, height = noisy.height;

    for (int i = range.rows().begin(); i < range.rows().end(); ++i)
      for (int j = range.cols().begin(); j < range.cols().end(); ++j)
      {
        int idx = i * width + j;

        if (i < radius || i >= height - radius || j < radius || j >= width - radius || noisy.data[idx] == Labels::Background)
        {
          good.data[idx] = Labels::Background;
          continue;
        }

        int bins[Labels::NUM_LABELS] = { 0 };
        Label mode = -1;
        Label mode_count = 0;

        for (int dy = -radius; dy <= radius; ++dy)
          for (int dx = -radius; dx <= radius; ++dx)
          {
            Label current = noisy.data[idx + dx + dy * width];
            ++bins[current];
            if (bins[current] > mode_count) {
              mode_count = bins[current];
              mode = current;
            }
          }

        good.data[idx] = mode;
      }
  }
};

void filterLabels(Cloud & noisy, Cloud & output, int radius)
{
  int width = noisy.getWidth(), height = noisy.getHeight();
  ChannelRef<Label> noisy_labels = noisy.get<TagBPLabel>();
  ChannelRef<Label> good_labels = output.get<TagBPLabel>();

  tbb::parallel_for(
        tbb::blocked_range2d<int>(0, noisy.getHeight(), 0, noisy.getWidth()),
        FilterHelper(noisy_labels, good_labels, radius)
  );
}

struct ConsensusHelper
{
private:
  const std::vector<std::vector<Label> > & multi_labels;
  ChannelRef<Label> labels;
  const ChannelRef<Depth> depths;

public:
  ConsensusHelper(
      const std::vector<std::vector<Label> > & multi_labels,
      Cloud & cloud
  )
    : multi_labels(multi_labels), labels(cloud.get<TagBPLabel>()), depths(cloud.get<TagDepth>())
  { }

  void
  operator ()(const tbb::blocked_range2d<unsigned> & range) const
  {
    for (unsigned y = range.rows().begin(); y < range.rows().end(); ++y)
      for (unsigned x = range.cols().begin(); x < range.cols().end(); ++x)
      {
        std::size_t i = &depths.at(y, x) - depths.data;

        bool background = true;
        for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
          if (multi_labels[ti][i] != Labels::Background) background = false;

        if (background)
        {
          labels.data[i] = Labels::Background;
          continue;
        }

        unsigned bins[Labels::NUM_LABELS] = { 0 };

        for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
          ++bins[multi_labels[ti][i]];

        int consensus = maxElementNoTie(Labels::NUM_LABELS, bins);

        if (consensus == -1)
        {
          std::fill (bins, bins + Labels::NUM_LABELS, 0);
          Depth d = depths.at(y, x);

          for (int off_x = -1; off_x <= 1; ++off_x)
            for (int off_y = -1; off_y <= 1; ++off_y)
            {
              Depth off_d = depths.atDef(y + off_y, x + off_x, BACKGROUND_DEPTH);

              if (std::abs (d - off_d) < 50)
                for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
                  ++bins[multi_labels[ti][i]];
            }

          labels.data[i] = std::max_element (bins, bins + Labels::NUM_LABELS) - bins;
        }
        else
        {
          labels.data[i] = consensus;
        }
      }
  }
};

BodyPartsRecognizer::BodyPartsRecognizer(std::size_t num_trees, const char * trees[])
{
  this->trees.resize(num_trees);

  for (std::size_t i = 0; i < num_trees; ++i)
    this->trees[i].reset(new Tree(trees[i]));
}

void
BodyPartsRecognizer::recognize(Cloud & cloud) const
{
  ChannelRef<Depth> depth = cloud.get<TagDepth>();

  Stopwatch watch_threshold;

  replaceZeroes(depth, BACKGROUND_DEPTH);
  applyThreshold(depth, selectThreshold(depth), BACKGROUND_DEPTH);

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Thresholding: %d ms", watch_threshold.elapsedMs());

  std::vector<std::vector<Label> > multi_labels (trees.size ());

  for (std::size_t ti = 0; ti < trees.size (); ++ti)
  {
    Stopwatch watch_evaluation;

    multi_labels[ti].resize (cloud.getHeight() * cloud.getWidth());
    trees[ti]->eval (cloud, multi_labels[ti]);

    __android_log_print(ANDROID_LOG_INFO, "BPR", "Evaluating tree %d: %d ms", ti, watch_evaluation.elapsedMs());
  }

  Stopwatch watch_consensus;

  Cloud noisy;
  noisy.resize(cloud.getWidth(), cloud.getHeight());

  tbb::parallel_for(
        tbb::blocked_range2d<unsigned>(0, cloud.getHeight(), 0, cloud.getWidth()),
        ConsensusHelper(multi_labels, noisy)
  );

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Finding consensus: %d ms", watch_consensus.elapsedMs());

  Stopwatch watch_filtering;

  filterLabels(noisy, cloud, 2);

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Filtering labels: %d ms", watch_consensus.elapsedMs());

}
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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. */

#include "paddle/platform/cpu_info.h"

#ifdef __APPLE__
#include <sys/sysctl.h>
#include <sys/types.h>
#else
#include <unistd.h>
#endif

#include "gflags/gflags.h"
#include "paddle/platform/error.h"

DEFINE_double(fraction_of_cpu_memory_to_use, 1,
              "Default use 100% of CPU memory for PaddlePaddle,"
              "reserve the rest for page tables, etc");

namespace paddle {
namespace platform {

inline size_t CpuTotalPhysicalMemory() {
#ifdef __APPLE__
  int mib[2];
  mib[0] = CTL_HW;
  mib[1] = HW_MEMSIZE;
  int64_t size = 0;
  size_t len = sizeof(size);
  if (sysctl(mib, 2, &size, &len, NULL, 0) == 0) return (size_t)size;
  return 0L;
#else
  long pages = sysconf(_SC_PHYS_PAGES);
  long page_size = sysconf(_SC_PAGE_SIZE);
  return pages * page_size;
#endif
}

size_t CpuMaxAllocSize() {
  // For distributed systems, it requires configuring and limiting
  // the fraction of memory to use.
  return FLAGS_fraction_of_cpu_memory_to_use * CpuTotalPhysicalMemory();
}

size_t CpuMinChunkSize() {
  // Allow to allocate the minimum chunk size is 256 bytes.
  return 1 << 8;
}

size_t CpuMaxChunkSize() {
  // Allow to allocate the maximum chunk size is roughly 3% of CPU memory.
  return CpuMaxAllocSize() / 32;
}

}  // namespace platform
}  // namespace paddle
<commit_msg>Follow comments<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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. */

#include "paddle/platform/cpu_info.h"

#ifdef __APPLE__
#include <sys/sysctl.h>
#include <sys/types.h>
#else
#include <unistd.h>
#endif

#include "gflags/gflags.h"
#include "paddle/platform/error.h"

DEFINE_double(fraction_of_cpu_memory_to_use, 1,
              "Default use 100% of CPU memory for PaddlePaddle,"
              "reserve the rest for page tables, etc");

namespace paddle {
namespace platform {

inline size_t CpuTotalPhysicalMemory() {
#ifdef __APPLE__
  int mib[2];
  mib[0] = CTL_HW;
  mib[1] = HW_MEMSIZE;
  int64_t size = 0;
  size_t len = sizeof(size);
  if (sysctl(mib, 2, &size, &len, NULL, 0) == 0) return (size_t)size;
  return 0L;
#else
  long pages = sysconf(_SC_PHYS_PAGES);
  long page_size = sysconf(_SC_PAGE_SIZE);
  return pages * page_size;
#endif
}

size_t CpuMaxAllocSize() {
  // For distributed systems, it requires configuring and limiting
  // the fraction of memory to use.
  return FLAGS_fraction_of_cpu_memory_to_use * CpuTotalPhysicalMemory();
}

size_t CpuMinChunkSize() {
  // Allow to allocate the minimum chunk size is 4 KB.
  return 1 << 12;
}

size_t CpuMaxChunkSize() {
  // Allow to allocate the maximum chunk size is roughly 3% of CPU memory.
  return CpuMaxAllocSize() / 32;
}

}  // namespace platform
}  // namespace paddle
<|endoftext|>