<commit_before>#include "../Dual_Constraint_Group.hxx"
#include "../../../../SDP.hxx"

void assign_blocks(
  const std::vector<Dual_Constraint_Group> &dualConstraintGroups,
  const std::list<El::Grid> &block_grid_mapping, SDP &sdp)
{
  auto grid(block_grid_mapping.begin());
  auto group(dualConstraintGroups.begin());
  for(auto &block_size : sdp.schur_block_sizes)
    {
      assert(group != dualConstraintGroups.end());
      assert(group->constraintConstants.size() == block_size);
      assert(static_cast<size_t>(group->constraintMatrix.Height())
             == block_size);
      {
        // sdp.primal_objective_c.blocks.emplace_back(block_size, 1);
        sdp.primal_objective_c.blocks.emplace_back(block_size, 1, *grid);
        auto block(sdp.primal_objective_c.blocks.rbegin());
        size_t local_height(block->LocalHeight());
        if(block->GlobalCol(0) == 0)
          {
            for(size_t row = 0; row < local_height; ++row)
              {
                size_t global_row(block->GlobalRow(row));
                block->SetLocal(row, 0,
                                group->constraintConstants.at(global_row));
              }
          }
      }
      {
        // sdp.free_var_matrix.blocks.emplace_back(
        //   block_size, sdp.dual_objective_b.Height());
        sdp.free_var_matrix.blocks.emplace_back(
          block_size, sdp.dual_objective_b.Height(), *grid);
        auto block(sdp.free_var_matrix.blocks.rbegin());
        int64_t local_height(block->LocalHeight()),
          local_width(block->LocalWidth());

        for(int64_t row = 0; row < local_height; ++row)
          {
            El::Int global_row(block->GlobalRow(row));
            if(global_row < group->constraintMatrix.Height())
              {
                for(int64_t column = 0; column < local_width; ++column)
                  {
                    El::Int global_column(block->GlobalCol(column));
                    if(global_column < group->constraintMatrix.Width())
                      {
                        block->SetLocal(row, column,
                                        group->constraintMatrix.Get(
                                          global_row, global_column));
                      }
                  }
              }
          }
      }
      ++group;
      ++grid;
    }
}
<commit_msg>Remove commented code<commit_after>#include "../Dual_Constraint_Group.hxx"
#include "../../../../SDP.hxx"

void assign_blocks(
  const std::vector<Dual_Constraint_Group> &dualConstraintGroups,
  const std::list<El::Grid> &block_grid_mapping, SDP &sdp)
{
  auto grid(block_grid_mapping.begin());
  auto group(dualConstraintGroups.begin());
  for(auto &block_size : sdp.schur_block_sizes)
    {
      assert(group != dualConstraintGroups.end());
      assert(group->constraintConstants.size() == block_size);
      assert(static_cast<size_t>(group->constraintMatrix.Height())
             == block_size);
      {
        sdp.primal_objective_c.blocks.emplace_back(block_size, 1, *grid);
        auto block(sdp.primal_objective_c.blocks.rbegin());
        size_t local_height(block->LocalHeight());
        if(block->GlobalCol(0) == 0)
          {
            for(size_t row = 0; row < local_height; ++row)
              {
                size_t global_row(block->GlobalRow(row));
                block->SetLocal(row, 0,
                                group->constraintConstants.at(global_row));
              }
          }
      }
      {
        sdp.free_var_matrix.blocks.emplace_back(
          block_size, sdp.dual_objective_b.Height(), *grid);
        auto block(sdp.free_var_matrix.blocks.rbegin());
        int64_t local_height(block->LocalHeight()),
          local_width(block->LocalWidth());

        for(int64_t row = 0; row < local_height; ++row)
          {
            El::Int global_row(block->GlobalRow(row));
            if(global_row < group->constraintMatrix.Height())
              {
                for(int64_t column = 0; column < local_width; ++column)
                  {
                    El::Int global_column(block->GlobalCol(column));
                    if(global_column < group->constraintMatrix.Width())
                      {
                        block->SetLocal(row, column,
                                        group->constraintMatrix.Get(
                                          global_row, global_column));
                      }
                  }
              }
          }
      }
      ++group;
      ++grid;
    }
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Help.cpp : Help and About dialogs
 ****************************************************************************
 * Copyright (C) 2007 the VideoLAN team
 * $Id$
 *
 * Authors: Jean-Baptiste Kempf <jb (at) videolan.org>
 *          Rémi Duraffort <ivoire (at) via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>

#include "dialogs/help.hpp"
#include <vlc_about.h>

#ifdef UPDATE_CHECK
#include <vlc_update.h>
#endif

#include "dialogs_provider.hpp"

#include <vlc_intf_strings.h>

#include <QTextBrowser>
#include <QTabWidget>
#include <QFile>
#include <QLabel>
#include <QString>
#include <QDialogButtonBox>
#include <QEvent>
#include <QFileDialog>
#include <QDate>

HelpDialog *HelpDialog::instance = NULL;

HelpDialog::HelpDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf )

{
    setWindowTitle( qtr( "Help" ) );
    setMinimumSize( 250, 300 );

    QGridLayout *layout = new QGridLayout( this );
    QTextBrowser *helpBrowser = new QTextBrowser( this );
    helpBrowser->setOpenExternalLinks( true );
    helpBrowser->setHtml( I_LONGHELP );
    QPushButton *closeButton = new QPushButton( qtr( "&Close" ) );
    closeButton->setDefault( true );

    layout->addWidget( helpBrowser, 0, 0, 1, 0 );
    layout->addWidget( closeButton, 1, 3 );

    BUTTONACT( closeButton, close() );
    readSettings( "Help", QSize( 400, 450 ) );
}

HelpDialog::~HelpDialog()
{
    writeSettings( "Help" );
}

void HelpDialog::close()
{
    toggleVisible();
}

AboutDialog *AboutDialog::instance = NULL;

AboutDialog::AboutDialog( QWidget *parent, intf_thread_t *_p_intf)
            : QVLCDialog( parent, _p_intf )
{
    setWindowTitle( qtr( "About" ) );
    resize( 600, 500 );
    setMinimumSize( 600, 500 );

    QGridLayout *layout = new QGridLayout( this );
    QTabWidget *tab = new QTabWidget( this );

    QPushButton *closeButton = new QPushButton( qtr( "&Close" ) );
    closeButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
    closeButton->setDefault( true );

    QLabel *introduction = new QLabel(
            qtr( "VLC media player" " " VERSION_MESSAGE ) );
    QLabel *iconVLC = new QLabel;
    if( QDate::currentDate().dayOfYear() >= 354 )
        iconVLC->setPixmap( QPixmap( ":/vlc48-christmas.png" ) );
    else
        iconVLC->setPixmap( QPixmap( ":/vlc48.png" ) );
    layout->addWidget( iconVLC, 0, 0, 1, 1 );
    layout->addWidget( introduction, 0, 1, 1, 7 );
    layout->addWidget( tab, 1, 0, 1, 8 );
    layout->addWidget( closeButton, 2, 6, 1, 2 );

    /* Main Introduction */
    QWidget *infoWidget = new QWidget( this );
    QHBoxLayout *infoLayout = new QHBoxLayout( infoWidget );
    QLabel *infoLabel = new QLabel(
            qtr( "VLC media player is a free media player, "
                "encoder and streamer that can read from files, "
                "CDs, DVDs, network streams, capture cards and even more!\n"
                "VLC uses its internal codecs and works on essentially every "
                "popular platform.\n\n" )
            + qtr( "This version of VLC was compiled by:\n " )
            + qfu( VLC_CompileBy() )+ "@" + qfu( VLC_CompileHost() ) + "."
            + qfu( VLC_CompileDomain() ) + ".\n"
            + "Compiler: " + qfu( VLC_Compiler() ) + ".\n"
            + qtr( "Based on Git commit: " ) + qfu( VLC_Changeset() ) + ".\n"
            + qtr( "You are using the Qt4 Interface.\n\n" )
            + qtr( "Copyright (C) " COPYRIGHT_YEARS " by the VideoLAN Team.\n" )
            + "vlc@videolan.org, http://www.videolan.org" );
    infoLabel->setWordWrap( infoLabel );

    QLabel *iconVLC2 = new QLabel;
    if( QDate::currentDate().dayOfYear() >= 354 )
        iconVLC2->setPixmap( QPixmap( ":/vlc128-christmas.png" ) );
    else
        iconVLC2->setPixmap( QPixmap( ":/vlc128.png" ) );
    infoLayout->addWidget( iconVLC2 );
    infoLayout->addWidget( infoLabel );

    /* GPL License */
    QTextEdit *licenseEdit = new QTextEdit( this );
    licenseEdit->setText( qfu( psz_license ) );
    licenseEdit->setReadOnly( true );

    /* People who helped */
    QWidget *thanksWidget = new QWidget( this );
    QVBoxLayout *thanksLayout = new QVBoxLayout( thanksWidget );

    QLabel *thanksLabel = new QLabel( qtr( "We would like to thank the whole "
                "VLC community, the testers, our users and the following people "
                "(and the missing ones...) for their collaboration to "
                "create the best free software." ) );
    thanksLabel->setWordWrap( true );
    thanksLayout->addWidget( thanksLabel );
    QTextEdit *thanksEdit = new QTextEdit( this );
    thanksEdit->setText( qfu( psz_thanks ) );
    thanksEdit->setReadOnly( true );
    thanksLayout->addWidget( thanksEdit );

    /* People who wrote the software */
    QTextEdit *authorsEdit = new QTextEdit( this );
    authorsEdit->setText( qfu( psz_authors ) );
    authorsEdit->setReadOnly( true );

    /* add the tabs to the Tabwidget */
    tab->addTab( infoWidget, qtr( "About" ) );
    tab->addTab( authorsEdit, qtr( "Authors" ) );
    tab->addTab( thanksWidget, qtr("Thanks") );
    tab->addTab( licenseEdit, qtr("License") );

    BUTTONACT( closeButton, close() );
}

AboutDialog::~AboutDialog()
{
}

void AboutDialog::close()
{
    toggleVisible();
}

#ifdef UPDATE_CHECK

/*****************************************************************************
 * UpdateDialog
 *****************************************************************************/
/* callback to get information from the core */
static void UpdateCallback( void *data, bool b_ret )
{
    UpdateDialog* UDialog = (UpdateDialog *)data;
    QEvent* event;

    if( b_ret )
        event = new QEvent( (QEvent::Type)UDOkEvent );
    else
        event = new QEvent( (QEvent::Type)UDErrorEvent );

    QApplication::postEvent( UDialog, event );
}

UpdateDialog *UpdateDialog::instance = NULL;

UpdateDialog::UpdateDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf )
{
    setWindowTitle( qtr( "Update" ) );

    QGridLayout *layout = new QGridLayout( this );

    QPushButton *closeButton = new QPushButton( qtr( "&Cancel" ) );
    updateButton = new QPushButton( qtr( "&Update List" ) );
    updateButton->setDefault( true );
    QDialogButtonBox *buttonBox = new QDialogButtonBox( Qt::Horizontal );
    buttonBox->addButton( updateButton, QDialogButtonBox::ActionRole );
    buttonBox->addButton( closeButton, QDialogButtonBox::AcceptRole );

    updateLabel = new QLabel( qtr( "Checking for an update..." ) );
    updateLabel->setWordWrap( true );

    layout->addWidget( updateLabel, 0, 0 );
    layout->addWidget( buttonBox, 1, 0 );

    BUTTONACT( updateButton, UpdateOrDownload() );
    BUTTONACT( closeButton, close() );

    /* Create the update structure */
    p_update = update_New( p_intf );
    b_checked = false;

    readSettings( "Update", QSize( 120, 80 ) );

    /* Check for updates */
    UpdateOrDownload();
}

UpdateDialog::~UpdateDialog()
{
    update_Delete( p_update );
    writeSettings( "Update" );
}

void UpdateDialog::close()
{
    toggleVisible();
}

/* Check for updates */
void UpdateDialog::UpdateOrDownload()
{
    if( !b_checked )
    {
        updateButton->setEnabled( false );
        msg_Dbg( p_intf, "Launching an update request" );
        update_Check( p_update, UpdateCallback, this );
    }
    else
    {
        QString dest_dir = QFileDialog::getExistingDirectory( this,
                                 qtr( "Select a directory..." ),
                                 qfu( config_GetHomeDir() ) );

        if( dest_dir != "" )
        {
            /*HACK: Qt4 isn't able to change the way OS deals with directories
              names. Windows doesn't add an ending separator so we might add it.
             */
            #if defined( WIN32 ) || defined( UNDER_CE )
            dest_dir += DIR_SEP;
            #endif
            msg_Dbg( p_intf, "Downloading to folder: %s", qtu( dest_dir ) );
            toggleVisible();
            update_Download( p_update, qtu( dest_dir ) );
        }
    }
}

/* Handle the events */
void UpdateDialog::customEvent( QEvent *event )
{
    if( event->type() == UDOkEvent )
        updateNotify( true );
    else
        updateNotify( false );
}

/* Notify the end of the update_Check */
void UpdateDialog::updateNotify( bool b_result )
{
    /* The update finish without errors */
    if( b_result )
    {
        if( update_NeedUpgrade( p_update ) )
        {
            update_release_t *p_release = update_GetRelease( p_update );
            assert( p_release );
            b_checked = true;
            updateButton->setText( "Ok" );
            updateLabel->setText( qtr( "There is a new version of VLC :\n" )
                                + qfu( p_release->psz_desc )  );

            /* Force the dialog to be shown */
            this->show();
        }
        else
            updateLabel->setText( qtr( "You have the latest version of VLC" ) );
    }
    else
        updateLabel->setText(
                        qtr( "An error occurred while checking for updates" ) );

    adjustSize();
    updateButton->setEnabled( true );
}

#endif

<commit_msg>Change the message shown by the update dialog: fix #1788.<commit_after>/*****************************************************************************
 * Help.cpp : Help and About dialogs
 ****************************************************************************
 * Copyright (C) 2007 the VideoLAN team
 * $Id$
 *
 * Authors: Jean-Baptiste Kempf <jb (at) videolan.org>
 *          Rémi Duraffort <ivoire (at) via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>

#include "dialogs/help.hpp"
#include <vlc_about.h>

#ifdef UPDATE_CHECK
#include <vlc_update.h>
#endif

#include "dialogs_provider.hpp"

#include <vlc_intf_strings.h>

#include <QTextBrowser>
#include <QTabWidget>
#include <QFile>
#include <QLabel>
#include <QString>
#include <QDialogButtonBox>
#include <QEvent>
#include <QFileDialog>
#include <QDate>

HelpDialog *HelpDialog::instance = NULL;

HelpDialog::HelpDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf )

{
    setWindowTitle( qtr( "Help" ) );
    setMinimumSize( 250, 300 );

    QGridLayout *layout = new QGridLayout( this );
    QTextBrowser *helpBrowser = new QTextBrowser( this );
    helpBrowser->setOpenExternalLinks( true );
    helpBrowser->setHtml( I_LONGHELP );
    QPushButton *closeButton = new QPushButton( qtr( "&Close" ) );
    closeButton->setDefault( true );

    layout->addWidget( helpBrowser, 0, 0, 1, 0 );
    layout->addWidget( closeButton, 1, 3 );

    BUTTONACT( closeButton, close() );
    readSettings( "Help", QSize( 400, 450 ) );
}

HelpDialog::~HelpDialog()
{
    writeSettings( "Help" );
}

void HelpDialog::close()
{
    toggleVisible();
}

AboutDialog *AboutDialog::instance = NULL;

AboutDialog::AboutDialog( QWidget *parent, intf_thread_t *_p_intf)
            : QVLCDialog( parent, _p_intf )
{
    setWindowTitle( qtr( "About" ) );
    resize( 600, 500 );
    setMinimumSize( 600, 500 );

    QGridLayout *layout = new QGridLayout( this );
    QTabWidget *tab = new QTabWidget( this );

    QPushButton *closeButton = new QPushButton( qtr( "&Close" ) );
    closeButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
    closeButton->setDefault( true );

    QLabel *introduction = new QLabel(
            qtr( "VLC media player" " " VERSION_MESSAGE ) );
    QLabel *iconVLC = new QLabel;
    if( QDate::currentDate().dayOfYear() >= 354 )
        iconVLC->setPixmap( QPixmap( ":/vlc48-christmas.png" ) );
    else
        iconVLC->setPixmap( QPixmap( ":/vlc48.png" ) );
    layout->addWidget( iconVLC, 0, 0, 1, 1 );
    layout->addWidget( introduction, 0, 1, 1, 7 );
    layout->addWidget( tab, 1, 0, 1, 8 );
    layout->addWidget( closeButton, 2, 6, 1, 2 );

    /* Main Introduction */
    QWidget *infoWidget = new QWidget( this );
    QHBoxLayout *infoLayout = new QHBoxLayout( infoWidget );
    QLabel *infoLabel = new QLabel(
            qtr( "VLC media player is a free media player, "
                "encoder and streamer that can read from files, "
                "CDs, DVDs, network streams, capture cards and even more!\n"
                "VLC uses its internal codecs and works on essentially every "
                "popular platform.\n\n" )
            + qtr( "This version of VLC was compiled by:\n " )
            + qfu( VLC_CompileBy() )+ "@" + qfu( VLC_CompileHost() ) + "."
            + qfu( VLC_CompileDomain() ) + ".\n"
            + "Compiler: " + qfu( VLC_Compiler() ) + ".\n"
            + qtr( "Based on Git commit: " ) + qfu( VLC_Changeset() ) + ".\n"
            + qtr( "You are using the Qt4 Interface.\n\n" )
            + qtr( "Copyright (C) " COPYRIGHT_YEARS " by the VideoLAN Team.\n" )
            + "vlc@videolan.org, http://www.videolan.org" );
    infoLabel->setWordWrap( infoLabel );

    QLabel *iconVLC2 = new QLabel;
    if( QDate::currentDate().dayOfYear() >= 354 )
        iconVLC2->setPixmap( QPixmap( ":/vlc128-christmas.png" ) );
    else
        iconVLC2->setPixmap( QPixmap( ":/vlc128.png" ) );
    infoLayout->addWidget( iconVLC2 );
    infoLayout->addWidget( infoLabel );

    /* GPL License */
    QTextEdit *licenseEdit = new QTextEdit( this );
    licenseEdit->setText( qfu( psz_license ) );
    licenseEdit->setReadOnly( true );

    /* People who helped */
    QWidget *thanksWidget = new QWidget( this );
    QVBoxLayout *thanksLayout = new QVBoxLayout( thanksWidget );

    QLabel *thanksLabel = new QLabel( qtr( "We would like to thank the whole "
                "VLC community, the testers, our users and the following people "
                "(and the missing ones...) for their collaboration to "
                "create the best free software." ) );
    thanksLabel->setWordWrap( true );
    thanksLayout->addWidget( thanksLabel );
    QTextEdit *thanksEdit = new QTextEdit( this );
    thanksEdit->setText( qfu( psz_thanks ) );
    thanksEdit->setReadOnly( true );
    thanksLayout->addWidget( thanksEdit );

    /* People who wrote the software */
    QTextEdit *authorsEdit = new QTextEdit( this );
    authorsEdit->setText( qfu( psz_authors ) );
    authorsEdit->setReadOnly( true );

    /* add the tabs to the Tabwidget */
    tab->addTab( infoWidget, qtr( "About" ) );
    tab->addTab( authorsEdit, qtr( "Authors" ) );
    tab->addTab( thanksWidget, qtr("Thanks") );
    tab->addTab( licenseEdit, qtr("License") );

    BUTTONACT( closeButton, close() );
}

AboutDialog::~AboutDialog()
{
}

void AboutDialog::close()
{
    toggleVisible();
}

#ifdef UPDATE_CHECK

/*****************************************************************************
 * UpdateDialog
 *****************************************************************************/
/* callback to get information from the core */
static void UpdateCallback( void *data, bool b_ret )
{
    UpdateDialog* UDialog = (UpdateDialog *)data;
    QEvent* event;

    if( b_ret )
        event = new QEvent( (QEvent::Type)UDOkEvent );
    else
        event = new QEvent( (QEvent::Type)UDErrorEvent );

    QApplication::postEvent( UDialog, event );
}

UpdateDialog *UpdateDialog::instance = NULL;

UpdateDialog::UpdateDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf )
{
    setWindowTitle( qtr( "Update" ) );

    QGridLayout *layout = new QGridLayout( this );

    QPushButton *closeButton = new QPushButton( qtr( "&Cancel" ) );
    updateButton = new QPushButton( qtr( "&Update List" ) );
    updateButton->setDefault( true );
    QDialogButtonBox *buttonBox = new QDialogButtonBox( Qt::Horizontal );
    buttonBox->addButton( updateButton, QDialogButtonBox::ActionRole );
    buttonBox->addButton( closeButton, QDialogButtonBox::AcceptRole );

    updateLabel = new QLabel( qtr( "Checking for an update..." ) );
    updateLabel->setWordWrap( true );

    layout->addWidget( updateLabel, 0, 0 );
    layout->addWidget( buttonBox, 1, 0 );

    BUTTONACT( updateButton, UpdateOrDownload() );
    BUTTONACT( closeButton, close() );

    /* Create the update structure */
    p_update = update_New( p_intf );
    b_checked = false;

    readSettings( "Update", QSize( 120, 80 ) );

    /* Check for updates */
    UpdateOrDownload();
}

UpdateDialog::~UpdateDialog()
{
    update_Delete( p_update );
    writeSettings( "Update" );
}

void UpdateDialog::close()
{
    toggleVisible();
}

/* Check for updates */
void UpdateDialog::UpdateOrDownload()
{
    if( !b_checked )
    {
        updateButton->setEnabled( false );
        msg_Dbg( p_intf, "Launching an update request" );
        update_Check( p_update, UpdateCallback, this );
    }
    else
    {
        QString dest_dir = QFileDialog::getExistingDirectory( this,
                                 qtr( "Select a directory..." ),
                                 qfu( config_GetHomeDir() ) );

        if( dest_dir != "" )
        {
            /*HACK: Qt4 isn't able to change the way OS deals with directories
              names. Windows doesn't add an ending separator so we might add it.
             */
            #if defined( WIN32 ) || defined( UNDER_CE )
            dest_dir += DIR_SEP;
            #endif
            msg_Dbg( p_intf, "Downloading to folder: %s", qtu( dest_dir ) );
            toggleVisible();
            update_Download( p_update, qtu( dest_dir ) );
        }
    }
}

/* Handle the events */
void UpdateDialog::customEvent( QEvent *event )
{
    if( event->type() == UDOkEvent )
        updateNotify( true );
    else
        updateNotify( false );
}

/* Notify the end of the update_Check */
void UpdateDialog::updateNotify( bool b_result )
{
    /* The update finish without errors */
    if( b_result )
    {
        if( update_NeedUpgrade( p_update ) )
        {
            update_release_t *p_release = update_GetRelease( p_update );
            assert( p_release );
            b_checked = true;
            updateButton->setText( "Ok" );
            QString message = qtr( "A new version of VLC(" )
                              + QString::number( p_release->i_major ) + "."
                              + QString::number( p_release->i_minor ) + "."
                              + QString::number( p_release->i_revision );
            if( p_release->extra )
                message += p_release->extra;
            message += qtr( ") is available.\nDo you want to download it?\n" ) + qfu( p_release->psz_desc );

            updateLabel->setText( message );

            /* Force the dialog to be shown */
            this->show();
        }
        else
            updateLabel->setText( qtr( "You have the latest version of VLC" ) );
    }
    else
        updateLabel->setText(
                        qtr( "An error occurred while checking for updates" ) );

    adjustSize();
    updateButton->setEnabled( true );
}

#endif

<|endoftext|>


<commit_before>#ifndef ENTT_META_NODE_HPP
#define ENTT_META_NODE_HPP

#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
#include "../container/dense_map.hpp"
#include "../core/attribute.h"
#include "../core/enum.hpp"
#include "../core/fwd.hpp"
#include "../core/type_info.hpp"
#include "../core/type_traits.hpp"
#include "../core/utility.hpp"
#include "../locator/locator.hpp"
#include "context.hpp"
#include "type_traits.hpp"

namespace entt {

class meta_any;
class meta_type;
struct meta_handle;

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

enum class meta_traits : std::uint32_t {
    is_none = 0x0000,
    is_const = 0x0001,
    is_static = 0x0002,
    is_arithmetic = 0x0004,
    is_integral = 0x0008,
    is_signed = 0x0010,
    is_array = 0x0020,
    is_enum = 0x0040,
    is_class = 0x0080,
    is_meta_pointer_like = 0x0100,
    is_meta_sequence_container = 0x0200,
    is_meta_associative_container = 0x0400,
    _entt_enum_as_bitmask
};

struct meta_type_node;

struct meta_prop_node {
    meta_type_node *(*type)() noexcept {nullptr};
    basic_any<0u> value{};
};

struct meta_base_node {
    meta_type_node *(*type)() noexcept;
    meta_any (*cast)(meta_any) noexcept;
};

struct meta_conv_node {
    meta_any (*conv)(const meta_any &);
};

struct meta_ctor_node {
    using size_type = std::size_t;

    size_type arity;
    meta_type (*arg)(const size_type) noexcept;
    meta_any (*invoke)(meta_any *const);
};

struct meta_dtor_node {
    void (*dtor)(void *){nullptr};
};

struct meta_data_node {
    using size_type = std::size_t;

    meta_traits traits;
    size_type arity;
    meta_type_node *(*type)() noexcept;
    meta_type (*arg)(const size_type) noexcept;
    bool (*set)(meta_handle, meta_any);
    meta_any (*get)(meta_handle);
    dense_map<id_type, meta_prop_node, identity> prop{};
};

struct meta_func_node {
    using size_type = std::size_t;

    meta_traits traits;
    size_type arity;
    meta_type_node *(*ret)() noexcept;
    meta_type (*arg)(const size_type) noexcept;
    meta_any (*invoke)(meta_handle, meta_any *const);
    dense_map<id_type, meta_prop_node, identity> prop{};
    std::unique_ptr<meta_func_node> next{};
};

struct meta_template_node {
    using size_type = std::size_t;

    size_type arity{0u};
    meta_type_node *(*type)() noexcept {nullptr};
    meta_type_node *(*arg)(const size_type) noexcept {nullptr};
};

struct meta_type_node {
    using size_type = std::size_t;

    const type_info *info;
    id_type id;
    meta_traits traits;
    size_type size_of;
    meta_type_node *(*remove_pointer)() noexcept;
    meta_any (*default_constructor)();
    double (*conversion_helper)(void *, const void *);
    meta_any (*from_void)(void *, const void *);
    meta_template_node templ;
    dense_map<id_type, meta_prop_node, identity> prop{};
    dense_map<id_type, meta_ctor_node, identity> ctor{};
    dense_map<id_type, meta_base_node, identity> base{};
    dense_map<id_type, meta_conv_node, identity> conv{};
    dense_map<id_type, meta_data_node, identity> data{};
    dense_map<id_type, meta_func_node, identity> func{};
    meta_dtor_node dtor{};
};

template<typename Type>
meta_type_node *resolve() noexcept;

template<typename... Args>
[[nodiscard]] meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) noexcept {
    meta_type_node *args[sizeof...(Args) + 1u]{nullptr, internal::resolve<std::remove_cv_t<std::remove_reference_t<Args>>>()...};
    return args[index + 1u];
}

template<typename Type>
[[nodiscard]] auto *meta_default_constructor() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    if constexpr(std::is_default_constructible_v<Type>) {
        return +[]() { return meta_any{std::in_place_type<Type>}; };
    } else {
        return static_cast<std::decay_t<decltype(meta_type_node::default_constructor)>>(nullptr);
    }
}

template<typename Type>
[[nodiscard]] auto *meta_conversion_helper() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    if constexpr(std::is_arithmetic_v<Type>) {
        return +[](void *bin, const void *value) {
            return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(*static_cast<const double *>(value))) : static_cast<double>(*static_cast<const Type *>(value));
        };
    } else if constexpr(std::is_enum_v<Type>) {
        return +[](void *bin, const void *value) {
            return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(value)))) : static_cast<double>(*static_cast<const Type *>(value));
        };
    } else {
        return static_cast<std::decay_t<decltype(meta_type_node::conversion_helper)>>(nullptr);
    }
}

template<typename Type>
[[nodiscard]] auto *meta_from_void() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    if constexpr(std::is_same_v<Type, void> || std::is_function_v<Type>) {
        return static_cast<std::decay_t<decltype(meta_type_node::from_void)>>(nullptr);
    } else {
        return +[](void *element, const void *as_const) {
            using value_type = std::decay_t<Type>;

            if(element) {
                return meta_any{std::in_place_type<value_type &>, *static_cast<value_type *>(element)};
            }

            return meta_any{std::in_place_type<const value_type &>, *static_cast<const value_type *>(as_const)};
        };
    }
}

template<typename Type>
[[nodiscard]] auto meta_template_info() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    if constexpr(is_complete_v<meta_template_traits<Type>>) {
        return meta_template_node{
            meta_template_traits<Type>::args_type::size,
            &resolve<typename meta_template_traits<Type>::class_type>,
            +[](const std::size_t index) noexcept -> meta_type_node * { return meta_arg_node(typename meta_template_traits<Type>::args_type{}, index); }};
    } else {
        return meta_template_node{};
    }
}

template<typename Type>
[[nodiscard]] meta_type_node *resolve() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    auto &&context = meta_context::from(locator<meta_ctx>::value_or());
    auto it = context.value.find(type_id<Type>().hash());

    if(it == context.value.end()) {
        meta_type_node node{
            &type_id<Type>(),
            type_id<Type>().hash(),
            (std::is_arithmetic_v<Type> ? internal::meta_traits::is_arithmetic : internal::meta_traits::is_none)
                | (std::is_integral_v<Type> ? internal::meta_traits::is_integral : internal::meta_traits::is_none)
                | (std::is_signed_v<Type> ? internal::meta_traits::is_signed : internal::meta_traits::is_none)
                | (std::is_array_v<Type> ? internal::meta_traits::is_array : internal::meta_traits::is_none)
                | (std::is_enum_v<Type> ? internal::meta_traits::is_enum : internal::meta_traits::is_none)
                | (std::is_class_v<Type> ? internal::meta_traits::is_class : internal::meta_traits::is_none)
                | (is_meta_pointer_like_v<Type> ? internal::meta_traits::is_meta_pointer_like : internal::meta_traits::is_none)
                | (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_meta_sequence_container : internal::meta_traits::is_none)
                | (is_complete_v<meta_associative_container_traits<Type>> ? internal::meta_traits::is_meta_associative_container : internal::meta_traits::is_none),
            size_of_v<Type>,
            &resolve<std::remove_cv_t<std::remove_pointer_t<Type>>>,
            meta_default_constructor<Type>(),
            meta_conversion_helper<Type>(),
            meta_from_void<Type>(),
            meta_template_info<Type>()};

        it = context.value.insert_or_assign(node.info->hash(), std::make_unique<meta_type_node>(std::move(node))).first;
    }

    return it->second.get();
}

} // namespace internal

/**
 * Internal details not to be documented.
 * @endcond
 */

} // namespace entt

#endif
<commit_msg>meta: explicit initialization of all values of a meta object<commit_after>#ifndef ENTT_META_NODE_HPP
#define ENTT_META_NODE_HPP

#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
#include "../container/dense_map.hpp"
#include "../core/attribute.h"
#include "../core/enum.hpp"
#include "../core/fwd.hpp"
#include "../core/type_info.hpp"
#include "../core/type_traits.hpp"
#include "../core/utility.hpp"
#include "../locator/locator.hpp"
#include "context.hpp"
#include "type_traits.hpp"

namespace entt {

class meta_any;
class meta_type;
struct meta_handle;

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

enum class meta_traits : std::uint32_t {
    is_none = 0x0000,
    is_const = 0x0001,
    is_static = 0x0002,
    is_arithmetic = 0x0004,
    is_integral = 0x0008,
    is_signed = 0x0010,
    is_array = 0x0020,
    is_enum = 0x0040,
    is_class = 0x0080,
    is_meta_pointer_like = 0x0100,
    is_meta_sequence_container = 0x0200,
    is_meta_associative_container = 0x0400,
    _entt_enum_as_bitmask
};

struct meta_type_node;

struct meta_prop_node {
    meta_type_node *(*type)() noexcept {nullptr};
    basic_any<0u> value{};
};

struct meta_base_node {
    meta_type_node *(*type)() noexcept {nullptr};
    meta_any (*cast)(meta_any) noexcept {nullptr};
};

struct meta_conv_node {
    meta_any (*conv)(const meta_any &){nullptr};
};

struct meta_ctor_node {
    using size_type = std::size_t;

    size_type arity{0u};
    meta_type (*arg)(const size_type) noexcept {nullptr};
    meta_any (*invoke)(meta_any *const){nullptr};
};

struct meta_dtor_node {
    void (*dtor)(void *){nullptr};
};

struct meta_data_node {
    using size_type = std::size_t;

    meta_traits traits{meta_traits::is_none};
    size_type arity{0u};
    meta_type_node *(*type)() noexcept {nullptr};
    meta_type (*arg)(const size_type) noexcept {nullptr};
    bool (*set)(meta_handle, meta_any){nullptr};
    meta_any (*get)(meta_handle){nullptr};
    dense_map<id_type, meta_prop_node, identity> prop{};
};

struct meta_func_node {
    using size_type = std::size_t;

    meta_traits traits{meta_traits::is_none};
    size_type arity{0u};
    meta_type_node *(*ret)() noexcept {nullptr};
    meta_type (*arg)(const size_type) noexcept {nullptr};
    meta_any (*invoke)(meta_handle, meta_any *const){nullptr};
    dense_map<id_type, meta_prop_node, identity> prop{};
    std::unique_ptr<meta_func_node> next{};
};

struct meta_template_node {
    using size_type = std::size_t;

    size_type arity{0u};
    meta_type_node *(*type)() noexcept {nullptr};
    meta_type_node *(*arg)(const size_type) noexcept {nullptr};
};

struct meta_type_node {
    using size_type = std::size_t;

    const type_info *info{nullptr};
    id_type id{};
    meta_traits traits{meta_traits::is_none};
    size_type size_of{0u};
    meta_type_node *(*remove_pointer)() noexcept {nullptr};
    meta_any (*default_constructor)(){nullptr};
    double (*conversion_helper)(void *, const void *){nullptr};
    meta_any (*from_void)(void *, const void *){nullptr};
    meta_template_node templ{};
    dense_map<id_type, meta_prop_node, identity> prop{};
    dense_map<id_type, meta_ctor_node, identity> ctor{};
    dense_map<id_type, meta_base_node, identity> base{};
    dense_map<id_type, meta_conv_node, identity> conv{};
    dense_map<id_type, meta_data_node, identity> data{};
    dense_map<id_type, meta_func_node, identity> func{};
    meta_dtor_node dtor{};
};

template<typename Type>
meta_type_node *resolve() noexcept;

template<typename... Args>
[[nodiscard]] meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) noexcept {
    meta_type_node *args[sizeof...(Args) + 1u]{nullptr, internal::resolve<std::remove_cv_t<std::remove_reference_t<Args>>>()...};
    return args[index + 1u];
}

template<typename Type>
[[nodiscard]] auto *meta_default_constructor() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    if constexpr(std::is_default_constructible_v<Type>) {
        return +[]() { return meta_any{std::in_place_type<Type>}; };
    } else {
        return static_cast<std::decay_t<decltype(meta_type_node::default_constructor)>>(nullptr);
    }
}

template<typename Type>
[[nodiscard]] auto *meta_conversion_helper() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    if constexpr(std::is_arithmetic_v<Type>) {
        return +[](void *bin, const void *value) {
            return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(*static_cast<const double *>(value))) : static_cast<double>(*static_cast<const Type *>(value));
        };
    } else if constexpr(std::is_enum_v<Type>) {
        return +[](void *bin, const void *value) {
            return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(value)))) : static_cast<double>(*static_cast<const Type *>(value));
        };
    } else {
        return static_cast<std::decay_t<decltype(meta_type_node::conversion_helper)>>(nullptr);
    }
}

template<typename Type>
[[nodiscard]] auto *meta_from_void() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    if constexpr(std::is_same_v<Type, void> || std::is_function_v<Type>) {
        return static_cast<std::decay_t<decltype(meta_type_node::from_void)>>(nullptr);
    } else {
        return +[](void *element, const void *as_const) {
            using value_type = std::decay_t<Type>;

            if(element) {
                return meta_any{std::in_place_type<value_type &>, *static_cast<value_type *>(element)};
            }

            return meta_any{std::in_place_type<const value_type &>, *static_cast<const value_type *>(as_const)};
        };
    }
}

template<typename Type>
[[nodiscard]] auto meta_template_info() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    if constexpr(is_complete_v<meta_template_traits<Type>>) {
        return meta_template_node{
            meta_template_traits<Type>::args_type::size,
            &resolve<typename meta_template_traits<Type>::class_type>,
            +[](const std::size_t index) noexcept -> meta_type_node * { return meta_arg_node(typename meta_template_traits<Type>::args_type{}, index); }};
    } else {
        return meta_template_node{};
    }
}

template<typename Type>
[[nodiscard]] meta_type_node *resolve() noexcept {
    static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");

    auto &&context = meta_context::from(locator<meta_ctx>::value_or());
    auto it = context.value.find(type_id<Type>().hash());

    if(it == context.value.end()) {
        meta_type_node node{
            &type_id<Type>(),
            type_id<Type>().hash(),
            (std::is_arithmetic_v<Type> ? internal::meta_traits::is_arithmetic : internal::meta_traits::is_none)
                | (std::is_integral_v<Type> ? internal::meta_traits::is_integral : internal::meta_traits::is_none)
                | (std::is_signed_v<Type> ? internal::meta_traits::is_signed : internal::meta_traits::is_none)
                | (std::is_array_v<Type> ? internal::meta_traits::is_array : internal::meta_traits::is_none)
                | (std::is_enum_v<Type> ? internal::meta_traits::is_enum : internal::meta_traits::is_none)
                | (std::is_class_v<Type> ? internal::meta_traits::is_class : internal::meta_traits::is_none)
                | (is_meta_pointer_like_v<Type> ? internal::meta_traits::is_meta_pointer_like : internal::meta_traits::is_none)
                | (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_meta_sequence_container : internal::meta_traits::is_none)
                | (is_complete_v<meta_associative_container_traits<Type>> ? internal::meta_traits::is_meta_associative_container : internal::meta_traits::is_none),
            size_of_v<Type>,
            &resolve<std::remove_cv_t<std::remove_pointer_t<Type>>>,
            meta_default_constructor<Type>(),
            meta_conversion_helper<Type>(),
            meta_from_void<Type>(),
            meta_template_info<Type>()};

        it = context.value.insert_or_assign(node.info->hash(), std::make_unique<meta_type_node>(std::move(node))).first;
    }

    return it->second.get();
}

} // namespace internal

/**
 * Internal details not to be documented.
 * @endcond
 */

} // namespace entt

#endif
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2017 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 "webrtc/modules/audio_processing/aec3/residual_echo_estimator.h"

#include <numeric>
#include <vector>

#include "webrtc/rtc_base/checks.h"

namespace webrtc {
namespace {

// Estimates the echo generating signal power as gated maximal power over a time
// window.
void EchoGeneratingPower(const RenderBuffer& render_buffer,
                         size_t min_delay,
                         size_t max_delay,
                         std::array<float, kFftLengthBy2Plus1>* X2) {
  X2->fill(0.f);
  for (size_t k = min_delay; k <= max_delay; ++k) {
    std::transform(X2->begin(), X2->end(), render_buffer.Spectrum(k).begin(),
                   X2->begin(),
                   [](float a, float b) { return std::max(a, b); });
  }

  // Apply soft noise gate of -78 dBFS.
  const float kNoiseGatePower = 27509.42f;
  std::for_each(X2->begin(), X2->end(), [kNoiseGatePower](float& a) {
    if (kNoiseGatePower > a) {
      a = std::max(0.f, a - 0.3f * (kNoiseGatePower - a));
    }
  });
}

constexpr int kNoiseFloorCounterMax = 50;
constexpr float kNoiseFloorMin = 10.f * 10.f * 128.f * 128.f;

// Updates estimate for the power of the stationary noise component in the
// render signal.
void RenderNoisePower(
    const RenderBuffer& render_buffer,
    std::array<float, kFftLengthBy2Plus1>* X2_noise_floor,
    std::array<int, kFftLengthBy2Plus1>* X2_noise_floor_counter) {
  RTC_DCHECK(X2_noise_floor);
  RTC_DCHECK(X2_noise_floor_counter);

  const auto render_power = render_buffer.Spectrum(0);
  RTC_DCHECK_EQ(X2_noise_floor->size(), render_power.size());
  RTC_DCHECK_EQ(X2_noise_floor_counter->size(), render_power.size());

  // Estimate the stationary noise power in a minimum statistics manner.
  for (size_t k = 0; k < render_power.size(); ++k) {
    // Decrease rapidly.
    if (render_power[k] < (*X2_noise_floor)[k]) {
      (*X2_noise_floor)[k] = render_power[k];
      (*X2_noise_floor_counter)[k] = 0;
    } else {
      // Increase in a delayed, leaky manner.
      if ((*X2_noise_floor_counter)[k] >= kNoiseFloorCounterMax) {
        (*X2_noise_floor)[k] =
            std::max((*X2_noise_floor)[k] * 1.1f, kNoiseFloorMin);
      } else {
        ++(*X2_noise_floor_counter)[k];
      }
    }
  }
}

// Assume a minimum echo path gain of -33 dB for headsets.
constexpr float kHeadsetEchoPathGain = 0.0005f;

}  // namespace

ResidualEchoEstimator::ResidualEchoEstimator() {
  Reset();
}

ResidualEchoEstimator::~ResidualEchoEstimator() = default;

void ResidualEchoEstimator::Estimate(
    bool using_subtractor_output,
    const AecState& aec_state,
    const RenderBuffer& render_buffer,
    const std::array<float, kFftLengthBy2Plus1>& S2_linear,
    const std::array<float, kFftLengthBy2Plus1>& Y2,
    std::array<float, kFftLengthBy2Plus1>* R2) {
  RTC_DCHECK(R2);

  const rtc::Optional<size_t> delay =
      aec_state.FilterDelay()
          ? aec_state.FilterDelay()
          : (aec_state.ExternalDelay() ? aec_state.ExternalDelay()
                                       : rtc::Optional<size_t>());

  // Estimate the power of the stationary noise in the render signal.
  RenderNoisePower(render_buffer, &X2_noise_floor_, &X2_noise_floor_counter_);

  // Estimate the residual echo power.
  const bool use_linear_echo_power =
      aec_state.UsableLinearEstimate() && using_subtractor_output;
  if (use_linear_echo_power && !aec_state.HeadsetDetected()) {
    RTC_DCHECK(aec_state.FilterDelay());
    const int filter_delay = *aec_state.FilterDelay();
    LinearEstimate(S2_linear, aec_state.Erle(), filter_delay, R2);
    AddEchoReverb(S2_linear, aec_state.SaturatedEcho(), filter_delay,
                  aec_state.ReverbDecay(), R2);
  } else {
    // Estimate the echo generating signal power.
    std::array<float, kFftLengthBy2Plus1> X2;
    if (aec_state.ExternalDelay() || aec_state.FilterDelay()) {
      RTC_DCHECK(delay);
      const int delay_use = static_cast<int>(*delay);

      // Computes the spectral power over the blocks surrounding the delay.
      RTC_DCHECK_LT(delay_use, kResidualEchoPowerRenderWindowSize);
      EchoGeneratingPower(
          render_buffer, std::max(0, delay_use - 1),
          std::min(kResidualEchoPowerRenderWindowSize - 1, delay_use + 1), &X2);
    } else {
      // Computes the spectral power over the latest blocks.
      EchoGeneratingPower(render_buffer, 0,
                          kResidualEchoPowerRenderWindowSize - 1, &X2);
    }

    // Subtract the stationary noise power to avoid stationary noise causing
    // excessive echo suppression.
    std::transform(
        X2.begin(), X2.end(), X2_noise_floor_.begin(), X2.begin(),
        [](float a, float b) { return std::max(0.f, a - 10.f * b); });

    NonLinearEstimate(aec_state.HeadsetDetected(), X2, Y2, R2);
    AddEchoReverb(*R2, aec_state.SaturatedEcho(),
                  std::min(static_cast<size_t>(kAdaptiveFilterLength),
                           delay.value_or(kAdaptiveFilterLength)),
                  aec_state.ReverbDecay(), R2);
  }

  // If the echo is deemed inaudible, set the residual echo to zero.
  if (aec_state.InaudibleEcho() &&
      (aec_state.ExternalDelay() || aec_state.HeadsetDetected())) {
    R2->fill(0.f);
  }

  // If the echo is saturated, estimate the echo power as the maximum echo power
  // with a leakage factor.
  if (aec_state.SaturatedEcho()) {
    R2->fill((*std::max_element(R2->begin(), R2->end())) * 100.f);
  }

  std::copy(R2->begin(), R2->end(), R2_old_.begin());
}

void ResidualEchoEstimator::Reset() {
  X2_noise_floor_counter_.fill(kNoiseFloorCounterMax);
  X2_noise_floor_.fill(kNoiseFloorMin);
  R2_reverb_.fill(0.f);
  R2_old_.fill(0.f);
  R2_hold_counter_.fill(0.f);
  for (auto& S2_k : S2_old_) {
    S2_k.fill(0.f);
  }
}

void ResidualEchoEstimator::LinearEstimate(
    const std::array<float, kFftLengthBy2Plus1>& S2_linear,
    const std::array<float, kFftLengthBy2Plus1>& erle,
    size_t delay,
    std::array<float, kFftLengthBy2Plus1>* R2) {
  std::fill(R2_hold_counter_.begin(), R2_hold_counter_.end(), 10.f);
  std::transform(erle.begin(), erle.end(), S2_linear.begin(), R2->begin(),
                 [](float a, float b) {
                   RTC_DCHECK_LT(0.f, a);
                   return b / a;
                 });
}

void ResidualEchoEstimator::NonLinearEstimate(
    bool headset_detected,
    const std::array<float, kFftLengthBy2Plus1>& X2,
    const std::array<float, kFftLengthBy2Plus1>& Y2,
    std::array<float, kFftLengthBy2Plus1>* R2) {
  // Choose gains.
  const float echo_path_gain_lf = headset_detected ? kHeadsetEchoPathGain : 100;
  const float echo_path_gain_mf =
      headset_detected ? kHeadsetEchoPathGain : 1000;
  const float echo_path_gain_hf =
      headset_detected ? kHeadsetEchoPathGain : 5000;

  // Compute preliminary residual echo.
  std::transform(
      X2.begin(), X2.begin() + 12, R2->begin(),
      [echo_path_gain_lf](float a) { return a * echo_path_gain_lf; });
  std::transform(
      X2.begin() + 12, X2.begin() + 25, R2->begin() + 12,
      [echo_path_gain_mf](float a) { return a * echo_path_gain_mf; });
  std::transform(
      X2.begin() + 25, X2.end(), R2->begin() + 25,
      [echo_path_gain_hf](float a) { return a * echo_path_gain_hf; });

  for (size_t k = 0; k < R2->size(); ++k) {
    // Update hold counter.
    R2_hold_counter_[k] = R2_old_[k] < (*R2)[k] ? 0 : R2_hold_counter_[k] + 1;

    // Compute the residual echo by holding a maximum echo powers and an echo
    // fading corresponding to a room with an RT60 value of about 50 ms.
    (*R2)[k] = R2_hold_counter_[k] < 2
                   ? std::max((*R2)[k], R2_old_[k])
                   : std::min((*R2)[k] + R2_old_[k] * 0.1f, Y2[k]);
  }
}

void ResidualEchoEstimator::AddEchoReverb(
    const std::array<float, kFftLengthBy2Plus1>& S2,
    bool saturated_echo,
    size_t delay,
    float reverb_decay_factor,
    std::array<float, kFftLengthBy2Plus1>* R2) {
  // Compute the decay factor for how much the echo has decayed before leaving
  // the region covered by the linear model.
  auto integer_power = [](float base, int exp) {
    float result = 1.f;
    for (int k = 0; k < exp; ++k) {
      result *= base;
    }
    return result;
  };
  RTC_DCHECK_LE(delay, S2_old_.size());
  const float reverb_decay_for_delay =
      integer_power(reverb_decay_factor, S2_old_.size() - delay);

  // Update the estimate of the reverberant residual echo power.
  S2_old_index_ = S2_old_index_ > 0 ? S2_old_index_ - 1 : S2_old_.size() - 1;
  const auto& S2_end = S2_old_[S2_old_index_];
  std::transform(
      S2_end.begin(), S2_end.end(), R2_reverb_.begin(), R2_reverb_.begin(),
      [reverb_decay_for_delay, reverb_decay_factor](float a, float b) {
        return (b + a * reverb_decay_for_delay) * reverb_decay_factor;
      });

  // Update the buffer of old echo powers.
  if (saturated_echo) {
    S2_old_[S2_old_index_].fill((*std::max_element(S2.begin(), S2.end())) *
                                100.f);
  } else {
    std::copy(S2.begin(), S2.end(), S2_old_[S2_old_index_].begin());
  }

  // Add the power of the echo reverb to the residual echo power.
  std::transform(R2->begin(), R2->end(), R2_reverb_.begin(), R2->begin(),
                 std::plus<float>());
}

}  // namespace webrtc
<commit_msg>Made the AEC3 alignment a mandatory for using the adaptive filter delay<commit_after>/*
 *  Copyright (c) 2017 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 "webrtc/modules/audio_processing/aec3/residual_echo_estimator.h"

#include <numeric>
#include <vector>

#include "webrtc/rtc_base/checks.h"

namespace webrtc {
namespace {

// Estimates the echo generating signal power as gated maximal power over a time
// window.
void EchoGeneratingPower(const RenderBuffer& render_buffer,
                         size_t min_delay,
                         size_t max_delay,
                         std::array<float, kFftLengthBy2Plus1>* X2) {
  X2->fill(0.f);
  for (size_t k = min_delay; k <= max_delay; ++k) {
    std::transform(X2->begin(), X2->end(), render_buffer.Spectrum(k).begin(),
                   X2->begin(),
                   [](float a, float b) { return std::max(a, b); });
  }

  // Apply soft noise gate of -78 dBFS.
  const float kNoiseGatePower = 27509.42f;
  std::for_each(X2->begin(), X2->end(), [kNoiseGatePower](float& a) {
    if (kNoiseGatePower > a) {
      a = std::max(0.f, a - 0.3f * (kNoiseGatePower - a));
    }
  });
}

constexpr int kNoiseFloorCounterMax = 50;
constexpr float kNoiseFloorMin = 10.f * 10.f * 128.f * 128.f;

// Updates estimate for the power of the stationary noise component in the
// render signal.
void RenderNoisePower(
    const RenderBuffer& render_buffer,
    std::array<float, kFftLengthBy2Plus1>* X2_noise_floor,
    std::array<int, kFftLengthBy2Plus1>* X2_noise_floor_counter) {
  RTC_DCHECK(X2_noise_floor);
  RTC_DCHECK(X2_noise_floor_counter);

  const auto render_power = render_buffer.Spectrum(0);
  RTC_DCHECK_EQ(X2_noise_floor->size(), render_power.size());
  RTC_DCHECK_EQ(X2_noise_floor_counter->size(), render_power.size());

  // Estimate the stationary noise power in a minimum statistics manner.
  for (size_t k = 0; k < render_power.size(); ++k) {
    // Decrease rapidly.
    if (render_power[k] < (*X2_noise_floor)[k]) {
      (*X2_noise_floor)[k] = render_power[k];
      (*X2_noise_floor_counter)[k] = 0;
    } else {
      // Increase in a delayed, leaky manner.
      if ((*X2_noise_floor_counter)[k] >= kNoiseFloorCounterMax) {
        (*X2_noise_floor)[k] =
            std::max((*X2_noise_floor)[k] * 1.1f, kNoiseFloorMin);
      } else {
        ++(*X2_noise_floor_counter)[k];
      }
    }
  }
}

// Assume a minimum echo path gain of -33 dB for headsets.
constexpr float kHeadsetEchoPathGain = 0.0005f;

}  // namespace

ResidualEchoEstimator::ResidualEchoEstimator() {
  Reset();
}

ResidualEchoEstimator::~ResidualEchoEstimator() = default;

void ResidualEchoEstimator::Estimate(
    bool using_subtractor_output,
    const AecState& aec_state,
    const RenderBuffer& render_buffer,
    const std::array<float, kFftLengthBy2Plus1>& S2_linear,
    const std::array<float, kFftLengthBy2Plus1>& Y2,
    std::array<float, kFftLengthBy2Plus1>* R2) {
  RTC_DCHECK(R2);

  const rtc::Optional<size_t> delay =
      aec_state.ExternalDelay()
          ? (aec_state.FilterDelay() ? aec_state.FilterDelay()
                                     : aec_state.ExternalDelay())
          : rtc::Optional<size_t>();

  // Estimate the power of the stationary noise in the render signal.
  RenderNoisePower(render_buffer, &X2_noise_floor_, &X2_noise_floor_counter_);

  // Estimate the residual echo power.
  const bool use_linear_echo_power =
      aec_state.UsableLinearEstimate() && using_subtractor_output;
  if (use_linear_echo_power && !aec_state.HeadsetDetected()) {
    RTC_DCHECK(aec_state.FilterDelay());
    const int filter_delay = *aec_state.FilterDelay();
    LinearEstimate(S2_linear, aec_state.Erle(), filter_delay, R2);
    AddEchoReverb(S2_linear, aec_state.SaturatedEcho(), filter_delay,
                  aec_state.ReverbDecay(), R2);
  } else {
    // Estimate the echo generating signal power.
    std::array<float, kFftLengthBy2Plus1> X2;
    if (aec_state.ExternalDelay() && aec_state.FilterDelay()) {
      RTC_DCHECK(delay);
      const int delay_use = static_cast<int>(*delay);

      // Computes the spectral power over the blocks surrounding the delay.
      RTC_DCHECK_LT(delay_use, kResidualEchoPowerRenderWindowSize);
      EchoGeneratingPower(
          render_buffer, std::max(0, delay_use - 1),
          std::min(kResidualEchoPowerRenderWindowSize - 1, delay_use + 1), &X2);
    } else {
      // Computes the spectral power over the latest blocks.
      EchoGeneratingPower(render_buffer, 0,
                          kResidualEchoPowerRenderWindowSize - 1, &X2);
    }

    // Subtract the stationary noise power to avoid stationary noise causing
    // excessive echo suppression.
    std::transform(
        X2.begin(), X2.end(), X2_noise_floor_.begin(), X2.begin(),
        [](float a, float b) { return std::max(0.f, a - 10.f * b); });

    NonLinearEstimate(aec_state.HeadsetDetected(), X2, Y2, R2);
    AddEchoReverb(*R2, aec_state.SaturatedEcho(),
                  std::min(static_cast<size_t>(kAdaptiveFilterLength),
                           delay.value_or(kAdaptiveFilterLength)),
                  aec_state.ReverbDecay(), R2);
  }

  // If the echo is deemed inaudible, set the residual echo to zero.
  if (aec_state.InaudibleEcho() &&
      (aec_state.ExternalDelay() || aec_state.HeadsetDetected())) {
    R2->fill(0.f);
  }

  // If the echo is saturated, estimate the echo power as the maximum echo power
  // with a leakage factor.
  if (aec_state.SaturatedEcho()) {
    R2->fill((*std::max_element(R2->begin(), R2->end())) * 100.f);
  }

  std::copy(R2->begin(), R2->end(), R2_old_.begin());
}

void ResidualEchoEstimator::Reset() {
  X2_noise_floor_counter_.fill(kNoiseFloorCounterMax);
  X2_noise_floor_.fill(kNoiseFloorMin);
  R2_reverb_.fill(0.f);
  R2_old_.fill(0.f);
  R2_hold_counter_.fill(0.f);
  for (auto& S2_k : S2_old_) {
    S2_k.fill(0.f);
  }
}

void ResidualEchoEstimator::LinearEstimate(
    const std::array<float, kFftLengthBy2Plus1>& S2_linear,
    const std::array<float, kFftLengthBy2Plus1>& erle,
    size_t delay,
    std::array<float, kFftLengthBy2Plus1>* R2) {
  std::fill(R2_hold_counter_.begin(), R2_hold_counter_.end(), 10.f);
  std::transform(erle.begin(), erle.end(), S2_linear.begin(), R2->begin(),
                 [](float a, float b) {
                   RTC_DCHECK_LT(0.f, a);
                   return b / a;
                 });
}

void ResidualEchoEstimator::NonLinearEstimate(
    bool headset_detected,
    const std::array<float, kFftLengthBy2Plus1>& X2,
    const std::array<float, kFftLengthBy2Plus1>& Y2,
    std::array<float, kFftLengthBy2Plus1>* R2) {
  // Choose gains.
  const float echo_path_gain_lf = headset_detected ? kHeadsetEchoPathGain : 100;
  const float echo_path_gain_mf =
      headset_detected ? kHeadsetEchoPathGain : 1000;
  const float echo_path_gain_hf =
      headset_detected ? kHeadsetEchoPathGain : 5000;

  // Compute preliminary residual echo.
  std::transform(
      X2.begin(), X2.begin() + 12, R2->begin(),
      [echo_path_gain_lf](float a) { return a * echo_path_gain_lf; });
  std::transform(
      X2.begin() + 12, X2.begin() + 25, R2->begin() + 12,
      [echo_path_gain_mf](float a) { return a * echo_path_gain_mf; });
  std::transform(
      X2.begin() + 25, X2.end(), R2->begin() + 25,
      [echo_path_gain_hf](float a) { return a * echo_path_gain_hf; });

  for (size_t k = 0; k < R2->size(); ++k) {
    // Update hold counter.
    R2_hold_counter_[k] = R2_old_[k] < (*R2)[k] ? 0 : R2_hold_counter_[k] + 1;

    // Compute the residual echo by holding a maximum echo powers and an echo
    // fading corresponding to a room with an RT60 value of about 50 ms.
    (*R2)[k] = R2_hold_counter_[k] < 2
                   ? std::max((*R2)[k], R2_old_[k])
                   : std::min((*R2)[k] + R2_old_[k] * 0.1f, Y2[k]);
  }
}

void ResidualEchoEstimator::AddEchoReverb(
    const std::array<float, kFftLengthBy2Plus1>& S2,
    bool saturated_echo,
    size_t delay,
    float reverb_decay_factor,
    std::array<float, kFftLengthBy2Plus1>* R2) {
  // Compute the decay factor for how much the echo has decayed before leaving
  // the region covered by the linear model.
  auto integer_power = [](float base, int exp) {
    float result = 1.f;
    for (int k = 0; k < exp; ++k) {
      result *= base;
    }
    return result;
  };
  RTC_DCHECK_LE(delay, S2_old_.size());
  const float reverb_decay_for_delay =
      integer_power(reverb_decay_factor, S2_old_.size() - delay);

  // Update the estimate of the reverberant residual echo power.
  S2_old_index_ = S2_old_index_ > 0 ? S2_old_index_ - 1 : S2_old_.size() - 1;
  const auto& S2_end = S2_old_[S2_old_index_];
  std::transform(
      S2_end.begin(), S2_end.end(), R2_reverb_.begin(), R2_reverb_.begin(),
      [reverb_decay_for_delay, reverb_decay_factor](float a, float b) {
        return (b + a * reverb_decay_for_delay) * reverb_decay_factor;
      });

  // Update the buffer of old echo powers.
  if (saturated_echo) {
    S2_old_[S2_old_index_].fill((*std::max_element(S2.begin(), S2.end())) *
                                100.f);
  } else {
    std::copy(S2.begin(), S2.end(), S2_old_[S2_old_index_].begin());
  }

  // Add the power of the echo reverb to the residual echo power.
  std::transform(R2->begin(), R2->end(), R2_reverb_.begin(), R2->begin(),
                 std::plus<float>());
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/*
   Copyright (c) 2009-2015, Jack Poulson
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
#include "El.hpp"
#ifdef EL_HAVE_OPENBLAS

using El::BlasInt;
using El::scomplex;
using El::dcomplex;

extern "C" {

void EL_BLAS(somatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const float* alpha, const float* A, const BlasInt* lda,
                            float* B, const BlasInt* ldb );
void EL_BLAS(domatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const double* alpha, const double* A, const BlasInt* lda,
                             double* B, const BlasInt* ldb );
void EL_BLAS(comatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const scomplex* alpha, const scomplex* A, const BlasInt* lda,
                               scomplex* B, const BlasInt* ldb );
void EL_BLAS(zomatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const dcomplex* alpha, const dcomplex* A, const BlasInt* lda,
                               dcomplex* B, const BlasInt* ldb );

void EL_BLAS(simatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const float* alpha, float* A, const BlasInt* lda, const BlasInt* ldb );
void EL_BLAS(dimatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const double* alpha, double* A, const BlasInt* lda, const BlasInt* ldb );
void EL_BLAS(cimatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const scomplex* alpha, scomplex* A, const BlasInt* lda, const BlasInt* ldb );
void EL_BLAS(zimatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const dcomplex* alpha, dcomplex* A, const BlasInt* lda, const BlasInt* ldb );

} // extern "C"

namespace El {
namespace openblas {

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  Int alpha, const Int* A, BlasInt lda,
                   Int* B, BlasInt ldb )
{
    if( orientation == NORMAL )
    {
        for( BlasInt j=0; j<n; ++j )
            for( BlasInt i=0; i<m; ++i )
                B[i+j*ldb] = A[i+j*lda];
    }
    else if( orientation == TRANSPOSE )
    {
        for( BlasInt i=0; i<m; ++i )
            for( BlasInt j=0; j<n; ++j )
                B[j+i*ldb] = A[i+j*lda];
    }
    else
    {
        for( BlasInt i=0; i<m; ++i )
            for( BlasInt j=0; j<n; ++j )
                B[j+i*ldb] = Conj(A[i+j*lda]);
    }
}

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  float alpha, const float* A, BlasInt lda,
                     float* B, BlasInt ldb )
{
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(somatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, B, &ldb );
}

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  double alpha, const double* A, BlasInt lda,
                      double* B, BlasInt ldb )
{
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(domatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, B, &ldb );
}

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  scomplex alpha, const scomplex* A, BlasInt lda,
                        scomplex* B, BlasInt ldb )
{
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(comatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, B, &ldb );
}

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  dcomplex alpha, const dcomplex* A, BlasInt lda,
                        dcomplex* B, BlasInt ldb )
{
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(zomatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, B, &ldb );
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  Int alpha, Int* A, BlasInt lda, BlasInt ldb )
{
    LogicError("Integer MKL imatcopy not yet supported");
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  float alpha, float* A, BlasInt lda, BlasInt ldb )
{
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(simatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, &ldb );
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  double alpha, double* A, BlasInt lda, BlasInt ldb )
{
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(dimatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, &ldb );
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  scomplex alpha, scomplex* A, BlasInt lda, BlasInt ldb )
{
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(cimatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, &ldb );
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  dcomplex alpha, dcomplex* A, BlasInt lda, BlasInt ldb )
{
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(zimatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, &ldb );
}

} // namespace openblas
} // namespace El

#endif // ifdef EL_HAVE_OPENBLAS
<commit_msg>Avoiding calls to OpenBLAS's omatcopy and friends when the matrix has a zero dimension<commit_after>/*
   Copyright (c) 2009-2015, Jack Poulson
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
#include "El.hpp"
#ifdef EL_HAVE_OPENBLAS

using El::BlasInt;
using El::scomplex;
using El::dcomplex;

extern "C" {

void EL_BLAS(somatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const float* alpha, const float* A, const BlasInt* lda,
                            float* B, const BlasInt* ldb );
void EL_BLAS(domatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const double* alpha, const double* A, const BlasInt* lda,
                             double* B, const BlasInt* ldb );
void EL_BLAS(comatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const scomplex* alpha, const scomplex* A, const BlasInt* lda,
                               scomplex* B, const BlasInt* ldb );
void EL_BLAS(zomatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const dcomplex* alpha, const dcomplex* A, const BlasInt* lda,
                               dcomplex* B, const BlasInt* ldb );

void EL_BLAS(simatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const float* alpha, float* A, const BlasInt* lda, const BlasInt* ldb );
void EL_BLAS(dimatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const double* alpha, double* A, const BlasInt* lda, const BlasInt* ldb );
void EL_BLAS(cimatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const scomplex* alpha, scomplex* A, const BlasInt* lda, const BlasInt* ldb );
void EL_BLAS(zimatcopy)
( const char* ordering, const char* trans,
  const BlasInt* rows, const BlasInt* cols,
  const dcomplex* alpha, dcomplex* A, const BlasInt* lda, const BlasInt* ldb );

} // extern "C"

namespace El {
namespace openblas {

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  Int alpha, const Int* A, BlasInt lda,
                   Int* B, BlasInt ldb )
{
    if( orientation == NORMAL )
    {
        for( BlasInt j=0; j<n; ++j )
            for( BlasInt i=0; i<m; ++i )
                B[i+j*ldb] = A[i+j*lda];
    }
    else if( orientation == TRANSPOSE )
    {
        for( BlasInt i=0; i<m; ++i )
            for( BlasInt j=0; j<n; ++j )
                B[j+i*ldb] = A[i+j*lda];
    }
    else
    {
        for( BlasInt i=0; i<m; ++i )
            for( BlasInt j=0; j<n; ++j )
                B[j+i*ldb] = Conj(A[i+j*lda]);
    }
}

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  float alpha, const float* A, BlasInt lda,
                     float* B, BlasInt ldb )
{
    if( m < 1 || n < 1 )
        return;
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(somatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, B, &ldb );
}

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  double alpha, const double* A, BlasInt lda,
                      double* B, BlasInt ldb )
{
    if( m < 1 || n < 1 )
        return;
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(domatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, B, &ldb );
}

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  scomplex alpha, const scomplex* A, BlasInt lda,
                        scomplex* B, BlasInt ldb )
{
    if( m < 1 || n < 1 )
        return;
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(comatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, B, &ldb );
}

void omatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  dcomplex alpha, const dcomplex* A, BlasInt lda,
                        dcomplex* B, BlasInt ldb )
{
    if( m < 1 || n < 1 )
        return;
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(zomatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, B, &ldb );
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  Int alpha, Int* A, BlasInt lda, BlasInt ldb )
{
    LogicError("Integer MKL imatcopy not yet supported");
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  float alpha, float* A, BlasInt lda, BlasInt ldb )
{
    if( m < 1 || n < 1 )
        return;
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(simatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, &ldb );
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  double alpha, double* A, BlasInt lda, BlasInt ldb )
{
    if( m < 1 || n < 1 )
        return;
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(dimatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, &ldb );
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  scomplex alpha, scomplex* A, BlasInt lda, BlasInt ldb )
{
    if( m < 1 || n < 1 )
        return;
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(cimatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, &ldb );
}

void imatcopy
( Orientation orientation, BlasInt m, BlasInt n,
  dcomplex alpha, dcomplex* A, BlasInt lda, BlasInt ldb )
{
    if( m < 1 || n < 1 )
        return;
    char ordering = 'C';
    char trans = OrientationToChar( orientation );
    EL_BLAS(zimatcopy)( &ordering, &trans, &m, &n, &alpha, A, &lda, &ldb );
}

} // namespace openblas
} // namespace El

#endif // ifdef EL_HAVE_OPENBLAS
<|endoftext|>


<commit_before>/*
 * Open Source Movement Analysis Library
 * Copyright (C) 2016, Moveck Solution Inc., all rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *     * Neither the name(s) of the copyright holders nor the names
 *       of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written
 *       permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "openma/io/handlerreader.h"
#include "openma/io/handlerplugin.h"
#include "openma/io/device.h"
#include "openma/io/handler.h"

// -------------------------------------------------------------------------- //
//                                 PRIVATE API                                //
// -------------------------------------------------------------------------- //

#ifndef DOXYGEN_SHOULD_SKIP_THIS

namespace ma
{
namespace io
{
  enum class Error;

  class HandlerReaderPrivate
  {
  public:
    HandlerReaderPrivate(Device* device, const std::string& format);
    ~HandlerReaderPrivate() _OPENMA_NOEXCEPT;

    Device* Source;
    std::string Format;
    Handler* Reader;
    Error ErrorCode;
    std::string ErrorMessage;
  };

  HandlerReaderPrivate::HandlerReaderPrivate(Device* device, const std::string& format)
  : Source(device), Format(format), Reader(nullptr), ErrorCode(Error::None), ErrorMessage(std::string{})
  {};

  HandlerReaderPrivate::~HandlerReaderPrivate() _OPENMA_NOEXCEPT = default; // Cannot be inlined
};
};

#endif

// ------------------------------------------------------------------------- //
//                                 PUBLIC API                                //
// ------------------------------------------------------------------------- //

namespace ma
{
namespace io
{
  /**
   * @class HandlerReader openma/io/handlerreader.h
   * @brief Format independent interface to read movement analysis data from devices.
   *
   * The reading of movement analysis data is simplifed with this interface that manage different kind of formats.
   * In case the format is not know (i.e. set to an empty string), the method read() and canRead() will attempt to detect the good format associated with the content of the device. The detected format can be retrieved using the method format().
   * You could also decide to force the type of format using the method setFormat().
   *
   * A simple usage to read a file is for example
   * @code{.unparsed}
   * // Create a file device
   * ma::io::File file;
   * // Open a file in read mode
   * file.open(filename, ma::io::Mode::In);
   * // Pass it to the reader
   * ma::io::HandlerReader reader(&file);
   * // Create a root node
   * ma::Node root("root");
   * // Extract the content of the file and assign it as a child of root
   * reader.read(&root);
   * // Depending of your needs, you can directly access to some children data.
   * auto timeSequences = root.findChildren<ma::TimeSequence*>();
   * // Or retrieve a complete trial
   * ma::Trial* trial = root.findChild<ma::Trial*>();
   * @endcode
   *
   * You can reuse a reader by modifying the set device or format using the methods setDevice() and setFormat() respectively. The modification of the format will reset the internal format handler. If you set a new device and you are not sure about its format, you should set the later to an empty string. This will run a new auto-detection when the method read() will be used.
   *
   * @ingroup openma_io
   */

  /**
   * Constructor.
   * The given @a device and @a format (optional) are stored to be later used to extract data using the method read().
   * In case, you have no idea on the format, leave it blank. The method canRead() will attempt to find it.
   */
  HandlerReader::HandlerReader(Device* device, const std::string& format)
  : mp_Pimpl(new HandlerReaderPrivate(device, format))
  {};

  /**
   * Destructor (default)
   */
  HandlerReader::~HandlerReader() = default;

  /**
   * Set a new device.
   * If no format was set, the methods canRead() or read() will attempt to find a handler that fit with the set device.
   */
  void HandlerReader::setDevice(Device* device)
  {
    auto optr = this->pimpl();
    optr->Source = device;
  };

  /**
   * When a new format is set, the current handler (if any) is reset. The use of the methods canRead() or read() will attempt to find a handler that fit with the given format.
   * If the given @a format is set to an empty string, the reader will try to auto-detect the format, based on the content of the set device.
   */
  void HandlerReader::setFormat(const std::string& format)
  {
    auto optr = this->pimpl();
    if (optr->Format.compare(format) == 0)
      return;
    optr->Format = format;
    delete optr->Reader;
    optr->Reader = nullptr;
  };

  /**
   * Return the current format used by this reader.
   * In case no (or empty) format was set to the reader, the returned value will be the one detected by the method canRead().
   * If a format was set, this one is returned.
   */
  const std::string& HandlerReader::format() const _OPENMA_NOEXCEPT
  {
    auto optr = this->pimpl();
    return optr->Format;
  };

  /**
   * Returns true if the signature used by the set format is found.
   * If no format was previously set (i.e. if the format is set to an empty string), this method will attempt to find the good format
   * @note This method can return true but the reading of data with the method read() can fail if the content of the set device is corrupted.
   */
  bool HandlerReader::canRead()
  {
    auto optr = this->pimpl();
    this->setError(Error::None);
    if ((optr->Source == nullptr) || ((optr->Source->openMode() & Mode::In) != Mode::In) || !optr->Source->isOpen())
    {
      this->setError(Error::Device, "No valid device assigned.");
      return false;
    }
    if (optr->Reader != nullptr)
    {
      // If a handler is already cached, it must be because the given device (and format) helped to detect/extract it. For this, let's return true.
      return true;
    }
    // Let's find the good handler
    const auto& plugins = load_handler_plugins();
    // Format auto detection?
    bool formatAutoDetection = optr->Format.empty();
    // In case no format is specified, it is necessary to pass through all the loaded handlers. If none of them detects a managed signature, then, a second pass is made for handler with non specific signature. These handlers rely on device name and handler format.
    if (formatAutoDetection)
    {
      std::vector<HandlerPlugin*> missingSignature, invalidSignature;
      // First pass: use handler signatures
      for (const auto& plugin: plugins)
      {
        auto signature = plugin->detectSignature(optr->Source, &(optr->Format));
        if (signature == Signature::Valid)
        {
          optr->Reader = plugin->create(optr->Source, optr->Format);
          break;
        }
        else if (signature == Signature::NotAvailable)
        {
          missingSignature.push_back(plugin);
        }
        else
        {
          invalidSignature.push_back(plugin);
        }
      }
      // No yet found? Let's go in the second pass for specific plugin
      // Maybe the name of the device will help to find the good format (extension)
      if (optr->Reader == nullptr)
      {
        const std::string name(optr->Source->name());
        for (const auto& plugin: missingSignature)
        {
          if (plugin->detectExtension(name, &(optr->Format)) && ((plugin->capabilities(optr->Format) & Capability::CanRead) == Capability::CanRead))
          {
            optr->Reader = plugin->create(optr->Source, optr->Format);
            break;
          }
        }
      }
      // Finally, it might be possible than one of the signed handler was not detected because of invalid data in the device.
      // Lets check if the extension was recognized.
      if (optr->Reader == nullptr)
      {
        const std::string name(optr->Source->name());
        std::string format;
        for (const auto& plugin: invalidSignature)
        {
          if (plugin->detectExtension(name, &format) && ((plugin->capabilities(format) & Capability::CanRead) == Capability::CanRead))
          {
            this->setError(Error::InvalidData, "The content of your device might be corrupted as no handler signature was found, but the extension is known");
            break;
          }
        }
      }
      // Final test
      if ((optr->Reader == nullptr) && (this->errorCode() == Error::None))
        this->setError(Error::UnsupportedFormat, "No handler found to support the given device and/or format");
    }
    // Pre-determined format?
    else
    {
      for (const auto& plugin: plugins)
      {
        if ((plugin->capabilities(optr->Format) & Capability::CanRead) == Capability::CanRead)
        {
          optr->Reader = plugin->create(optr->Source, optr->Format);
          break;
        }
      }
    }
    // Final test
    return (optr->Reader != nullptr);
  };

  /**
   * Read the content of the set device using the set/detected format and add the result as a child (children) of the given object @a root.
   * This method returns @c true if no error was thrown during the reading of the device.
   * In case @c false is returned, you could find more information on the error using the methods errorCode() and errorMessage().
   */
  bool HandlerReader::read(Node* root)
  {
    auto optr = this->pimpl();
    if ((optr->Reader == nullptr) && !this->canRead())
      return false;
    auto result = optr->Reader->read(root);
    this->setError(optr->Reader->errorCode(), optr->Reader->errorMessage());
    return result;
  };

  /**
   * Returns the code associated with a posible error set during the reading of a device.
   * By default this method returns Error::None.
   * This method should be used if the method read() returns false.
   */
  Error HandlerReader::errorCode() const _OPENMA_NOEXCEPT
  {
    auto optr = this->pimpl();
    return optr->ErrorCode;
  };

  /**
   * Returns the message associated with a posible error set during the reading of a device.
   * By default this method returns an empty string.
   * This method could be used if the method read() returns false.
   */
  const std::string& HandlerReader::errorMessage() const _OPENMA_NOEXCEPT
  {
    auto optr = this->pimpl();
    return optr->ErrorMessage;
  };

  /**
   * Returns a vector with all formats that have the capability to read data from a device.
   */
  const std::vector<std::string>& HandlerReader::availableFormats() _OPENMA_NOEXCEPT
  {
    static std::vector<std::string> formats;
    if (formats.empty())
    {
      const auto& plugins = load_handler_plugins();
      for (auto plugin: plugins)
      {
        const auto& supportedformats = plugin->supportedFormats();
        for (const auto& format: supportedformats)
        {
          if ((plugin->capabilities(format) & Capability::CanRead) == Capability::CanRead)
          {
            formats.push_back(format);
          }
        }
      }
    }
    return formats;
  };

  /**
   * Helper method to set error information (code and message).
   */
  void HandlerReader::setError(Error code, const std::string& msg) _OPENMA_NOEXCEPT
  {
    auto optr = this->pimpl();
    optr->ErrorCode = code;
    optr->ErrorMessage = msg;
  };
};
};<commit_msg>Coverity might say that the check against null is unnecessary. Indeed it is done in the method canRead().<commit_after>/*
 * Open Source Movement Analysis Library
 * Copyright (C) 2016, Moveck Solution Inc., all rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *     * Neither the name(s) of the copyright holders nor the names
 *       of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written
 *       permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "openma/io/handlerreader.h"
#include "openma/io/handlerplugin.h"
#include "openma/io/device.h"
#include "openma/io/handler.h"

// -------------------------------------------------------------------------- //
//                                 PRIVATE API                                //
// -------------------------------------------------------------------------- //

#ifndef DOXYGEN_SHOULD_SKIP_THIS

namespace ma
{
namespace io
{
  enum class Error;

  class HandlerReaderPrivate
  {
  public:
    HandlerReaderPrivate(Device* device, const std::string& format);
    ~HandlerReaderPrivate() _OPENMA_NOEXCEPT;

    Device* Source;
    std::string Format;
    Handler* Reader;
    Error ErrorCode;
    std::string ErrorMessage;
  };

  HandlerReaderPrivate::HandlerReaderPrivate(Device* device, const std::string& format)
  : Source(device), Format(format), Reader(nullptr), ErrorCode(Error::None), ErrorMessage(std::string{})
  {};

  HandlerReaderPrivate::~HandlerReaderPrivate() _OPENMA_NOEXCEPT = default; // Cannot be inlined
};
};

#endif

// ------------------------------------------------------------------------- //
//                                 PUBLIC API                                //
// ------------------------------------------------------------------------- //

namespace ma
{
namespace io
{
  /**
   * @class HandlerReader openma/io/handlerreader.h
   * @brief Format independent interface to read movement analysis data from devices.
   *
   * The reading of movement analysis data is simplifed with this interface that manage different kind of formats.
   * In case the format is not know (i.e. set to an empty string), the method read() and canRead() will attempt to detect the good format associated with the content of the device. The detected format can be retrieved using the method format().
   * You could also decide to force the type of format using the method setFormat().
   *
   * A simple usage to read a file is for example
   * @code{.unparsed}
   * // Create a file device
   * ma::io::File file;
   * // Open a file in read mode
   * file.open(filename, ma::io::Mode::In);
   * // Pass it to the reader
   * ma::io::HandlerReader reader(&file);
   * // Create a root node
   * ma::Node root("root");
   * // Extract the content of the file and assign it as a child of root
   * reader.read(&root);
   * // Depending of your needs, you can directly access to some children data.
   * auto timeSequences = root.findChildren<ma::TimeSequence*>();
   * // Or retrieve a complete trial
   * ma::Trial* trial = root.findChild<ma::Trial*>();
   * @endcode
   *
   * You can reuse a reader by modifying the set device or format using the methods setDevice() and setFormat() respectively. The modification of the format will reset the internal format handler. If you set a new device and you are not sure about its format, you should set the later to an empty string. This will run a new auto-detection when the method read() will be used.
   *
   * @ingroup openma_io
   */

  /**
   * Constructor.
   * The given @a device and @a format (optional) are stored to be later used to extract data using the method read().
   * In case, you have no idea on the format, leave it blank. The method canRead() will attempt to find it.
   */
  HandlerReader::HandlerReader(Device* device, const std::string& format)
  : mp_Pimpl(new HandlerReaderPrivate(device, format))
  {};

  /**
   * Destructor (default)
   */
  HandlerReader::~HandlerReader() = default;

  /**
   * Set a new device.
   * If no format was set, the methods canRead() or read() will attempt to find a handler that fit with the set device.
   */
  void HandlerReader::setDevice(Device* device)
  {
    auto optr = this->pimpl();
    optr->Source = device;
  };

  /**
   * When a new format is set, the current handler (if any) is reset. The use of the methods canRead() or read() will attempt to find a handler that fit with the given format.
   * If the given @a format is set to an empty string, the reader will try to auto-detect the format, based on the content of the set device.
   */
  void HandlerReader::setFormat(const std::string& format)
  {
    auto optr = this->pimpl();
    if (optr->Format.compare(format) == 0)
      return;
    optr->Format = format;
    delete optr->Reader;
    optr->Reader = nullptr;
  };

  /**
   * Return the current format used by this reader.
   * In case no (or empty) format was set to the reader, the returned value will be the one detected by the method canRead().
   * If a format was set, this one is returned.
   */
  const std::string& HandlerReader::format() const _OPENMA_NOEXCEPT
  {
    auto optr = this->pimpl();
    return optr->Format;
  };

  /**
   * Returns true if the signature used by the set format is found.
   * If no format was previously set (i.e. if the format is set to an empty string), this method will attempt to find the good format
   * @note This method can return true but the reading of data with the method read() can fail if the content of the set device is corrupted.
   */
  bool HandlerReader::canRead()
  {
    auto optr = this->pimpl();
    this->setError(Error::None);
    if ((optr->Source == nullptr) || ((optr->Source->openMode() & Mode::In) != Mode::In) || !optr->Source->isOpen())
    {
      this->setError(Error::Device, "No valid device assigned.");
      return false;
    }
    if (optr->Reader != nullptr)
    {
      // If a handler is already cached, it must be because the given device (and format) helped to detect/extract it. For this, let's return true.
      return true;
    }
    // Let's find the good handler
    const auto& plugins = load_handler_plugins();
    // Format auto detection?
    bool formatAutoDetection = optr->Format.empty();
    // In case no format is specified, it is necessary to pass through all the loaded handlers. If none of them detects a managed signature, then, a second pass is made for handler with non specific signature. These handlers rely on device name and handler format.
    if (formatAutoDetection)
    {
      std::vector<HandlerPlugin*> missingSignature, invalidSignature;
      // First pass: use handler signatures
      for (const auto& plugin: plugins)
      {
        auto signature = plugin->detectSignature(optr->Source, &(optr->Format));
        if (signature == Signature::Valid)
        {
          optr->Reader = plugin->create(optr->Source, optr->Format);
          break;
        }
        else if (signature == Signature::NotAvailable)
        {
          missingSignature.push_back(plugin);
        }
        else
        {
          invalidSignature.push_back(plugin);
        }
      }
      // No yet found? Let's go in the second pass for specific plugin
      // Maybe the name of the device will help to find the good format (extension)
      if (optr->Reader == nullptr)
      {
        const std::string name(optr->Source->name());
        for (const auto& plugin: missingSignature)
        {
          if (plugin->detectExtension(name, &(optr->Format)) && ((plugin->capabilities(optr->Format) & Capability::CanRead) == Capability::CanRead))
          {
            optr->Reader = plugin->create(optr->Source, optr->Format);
            break;
          }
        }
      }
      // Finally, it might be possible than one of the signed handler was not detected because of invalid data in the device.
      // Lets check if the extension was recognized.
      if (optr->Reader == nullptr)
      {
        const std::string name(optr->Source->name());
        std::string format;
        for (const auto& plugin: invalidSignature)
        {
          if (plugin->detectExtension(name, &format) && ((plugin->capabilities(format) & Capability::CanRead) == Capability::CanRead))
          {
            this->setError(Error::InvalidData, "The content of your device might be corrupted as no handler signature was found, but the extension is known");
            break;
          }
        }
      }
      // Final test
      if ((optr->Reader == nullptr) && (this->errorCode() == Error::None))
        this->setError(Error::UnsupportedFormat, "No handler found to support the given device and/or format");
    }
    // Pre-determined format?
    else
    {
      for (const auto& plugin: plugins)
      {
        if ((plugin->capabilities(optr->Format) & Capability::CanRead) == Capability::CanRead)
        {
          optr->Reader = plugin->create(optr->Source, optr->Format);
          break;
        }
      }
    }
    // Final test
    return (optr->Reader != nullptr);
  };

  /**
   * Read the content of the set device using the set/detected format and add the result as a child (children) of the given object @a root.
   * This method returns @c true if no error was thrown during the reading of the device.
   * In case @c false is returned, you could find more information on the error using the methods errorCode() and errorMessage().
   */
  bool HandlerReader::read(Node* root)
  {
    if (!this->canRead())
      return false;
    auto optr = this->pimpl();
    auto result = optr->Reader->read(root);
    this->setError(optr->Reader->errorCode(), optr->Reader->errorMessage());
    return result;
  };

  /**
   * Returns the code associated with a posible error set during the reading of a device.
   * By default this method returns Error::None.
   * This method should be used if the method read() returns false.
   */
  Error HandlerReader::errorCode() const _OPENMA_NOEXCEPT
  {
    auto optr = this->pimpl();
    return optr->ErrorCode;
  };

  /**
   * Returns the message associated with a posible error set during the reading of a device.
   * By default this method returns an empty string.
   * This method could be used if the method read() returns false.
   */
  const std::string& HandlerReader::errorMessage() const _OPENMA_NOEXCEPT
  {
    auto optr = this->pimpl();
    return optr->ErrorMessage;
  };

  /**
   * Returns a vector with all formats that have the capability to read data from a device.
   */
  const std::vector<std::string>& HandlerReader::availableFormats() _OPENMA_NOEXCEPT
  {
    static std::vector<std::string> formats;
    if (formats.empty())
    {
      const auto& plugins = load_handler_plugins();
      for (auto plugin: plugins)
      {
        const auto& supportedformats = plugin->supportedFormats();
        for (const auto& format: supportedformats)
        {
          if ((plugin->capabilities(format) & Capability::CanRead) == Capability::CanRead)
          {
            formats.push_back(format);
          }
        }
      }
    }
    return formats;
  };

  /**
   * Helper method to set error information (code and message).
   */
  void HandlerReader::setError(Error code, const std::string& msg) _OPENMA_NOEXCEPT
  {
    auto optr = this->pimpl();
    optr->ErrorCode = code;
    optr->ErrorMessage = msg;
  };
};
};<|endoftext|>


<commit_before><commit_msg>DOCX drawingML import: handle paragraph top margin<commit_after><|endoftext|>