<commit_before>/*
  Q Light Controller
  inputoutputmanager.cpp

  Copyright (c) Massimo Callegari

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include <QListWidgetItem>
#include <QListWidget>
#include <QHeaderView>
#include <QStringList>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QSettings>
#include <QSplitter>
#include <QLineEdit>
#include <QToolBar>
#include <QAction>
#include <QTimer>
#include <QDebug>
#include <QLabel>
#include <QIcon>

#include "inputoutputpatcheditor.h"
#include "universeitemwidget.h"
#include "inputoutputmanager.h"
#include "inputoutputmap.h"
#include "outputpatch.h"
#include "inputpatch.h"
#include "apputil.h"
#include "doc.h"

#define KColumnUniverse     0
#define KColumnInput        1
#define KColumnOutput       2
#define KColumnFeedback     3
#define KColumnProfile      4
#define KColumnInputNum     5
#define KColumnOutputNum    6

#define SETTINGS_SPLITTER "inputmanager/splitter"

InputOutputManager* InputOutputManager::s_instance = NULL;

InputOutputManager::InputOutputManager(QWidget* parent, Doc* doc)
    : QWidget(parent)
    , m_doc(doc)
    , m_toolbar(NULL)
    , m_addUniverseAction(NULL)
    , m_deleteUniverseAction(NULL)
    , m_uniNameEdit(NULL)
    , m_editor(NULL)
{
    Q_ASSERT(s_instance == NULL);
    s_instance = this;

    Q_ASSERT(doc != NULL);

    m_ioMap = doc->inputOutputMap();

    /* Create a new layout for this widget */
    new QVBoxLayout(this);
    layout()->setContentsMargins(0, 0, 0, 0);
    layout()->setSpacing(0);

    m_splitter = new QSplitter(Qt::Horizontal, this);
    layout()->addWidget(m_splitter);

    m_addUniverseAction = new QAction(QIcon(":/edit_add.png"),
                                   tr("Add U&niverse"), this);
    m_addUniverseAction->setShortcut(QKeySequence("CTRL+N"));
    connect(m_addUniverseAction, SIGNAL(triggered(bool)),
            this, SLOT(slotAddUniverse()));

    m_deleteUniverseAction = new QAction(QIcon(":/edit_remove.png"),
                                   tr("&Delete Universe"), this);
    m_deleteUniverseAction->setShortcut(QKeySequence("CTRL+D"));
    connect(m_deleteUniverseAction, SIGNAL(triggered(bool)),
            this, SLOT(slotDeleteUniverse()));

    QWidget* ucontainer = new QWidget(this);
    m_splitter->addWidget(ucontainer);
    ucontainer->setLayout(new QVBoxLayout);
    ucontainer->layout()->setContentsMargins(0, 0, 0, 0);

    // Add a toolbar to the dock area
    m_toolbar = new QToolBar("Input Output Manager", this);
    m_toolbar->setFloatable(false);
    m_toolbar->setMovable(false);
    m_toolbar->setIconSize(QSize(32, 32));
    m_toolbar->addAction(m_addUniverseAction);
    m_toolbar->addAction(m_deleteUniverseAction);
    m_toolbar->addSeparator();

    QLabel *uniLabel = new QLabel(tr("Universe name:"));
    m_uniNameEdit = new QLineEdit(this);
    QFont font = QApplication::font();
    //font.setBold(true);
    font.setPixelSize(18);
    uniLabel->setFont(font);
    m_uniNameEdit->setFont(font);
    m_toolbar->addWidget(uniLabel);
    m_toolbar->addWidget(m_uniNameEdit);

    m_splitter->widget(0)->layout()->addWidget(m_toolbar);

    connect(m_uniNameEdit, SIGNAL(textChanged(QString)),
            this, SLOT(slotUniverseNameChanged(QString)));

    /* Universes list */
    m_list = new QListWidget(this);
    m_list->setItemDelegate(new UniverseItemWidget(m_list));
    m_splitter->widget(0)->layout()->addWidget(m_list);

    QWidget* gcontainer = new QWidget(this);
    m_splitter->addWidget(gcontainer);
    gcontainer->setLayout(new QVBoxLayout);
    gcontainer->layout()->setContentsMargins(0, 0, 0, 0);

    connect(m_list, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
            this, SLOT(slotCurrentItemChanged()));

    /* Timer that clears the input data icon after a while */
    m_icon = QIcon(":/input.png");
    m_timer = new QTimer(this);
    m_timer->setSingleShot(true);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTimerTimeout()));

    /* Listen to input map's input data signals */
    connect(m_ioMap, SIGNAL(inputValueChanged(quint32,quint32,uchar)),
            this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));

    /* Listen to plugin configuration changes */
    connect(m_ioMap, SIGNAL(pluginConfigurationChanged(const QString&)),
            this, SLOT(updateList()));

    updateList();
    m_list->setCurrentItem(m_list->item(0));

    QSettings settings;
    QVariant var = settings.value(SETTINGS_SPLITTER);
    if (var.isValid() == true)
        m_splitter->restoreState(var.toByteArray());
}

InputOutputManager::~InputOutputManager()
{
    QSettings settings;
    settings.setValue(SETTINGS_SPLITTER, m_splitter->saveState());

    s_instance = NULL;
}

InputOutputManager* InputOutputManager::instance()
{
    return s_instance;
}

/*****************************************************************************
 * Tree widget
 *****************************************************************************/

void InputOutputManager::updateList()
{
    m_list->clear();
    for (quint32 uni = 0; uni < m_ioMap->universes(); uni++)
        updateItem(new QListWidgetItem(m_list), uni);
    m_list->setCurrentItem(m_list->item(0));
    m_uniNameEdit->setText(m_list->item(0)->data(Qt::DisplayRole).toString());

    if (m_ioMap->universes() == 4)
        m_deleteUniverseAction->setEnabled(false);
    else
        m_deleteUniverseAction->setEnabled(true);
}

void InputOutputManager::updateItem(QListWidgetItem* item, quint32 universe)
{
    Q_ASSERT(item != NULL);

    InputPatch* ip = m_ioMap->inputPatch(universe);
    OutputPatch* op = m_ioMap->outputPatch(universe);
    OutputPatch* fp = m_ioMap->feedbackPatch(universe);

    QString uniName = m_ioMap->getUniverseName(universe);
    if (uniName.isEmpty())
    {
        QString defUniName = tr("Universe %1").arg(universe + 1);
        m_ioMap->setUniverseName(universe, defUniName);
        item->setData(Qt::DisplayRole, defUniName);
    }
    else
        item->setData(Qt::DisplayRole, uniName);
    item->setSizeHint(QSize(m_list->width(), 50));
    item->setData(Qt::UserRole, universe);
    if (ip != NULL)
    {
        item->setData(Qt::UserRole + 1, ip->inputName());
        item->setData(Qt::UserRole + 2, ip->profileName());
    }
    else
    {
        item->setData(Qt::UserRole + 1, KInputNone);
        item->setData(Qt::UserRole + 2, KInputNone);
    }
    if (op != NULL)
        item->setData(Qt::UserRole + 3, op->outputName());
    else
        item->setData(Qt::UserRole + 3, KOutputNone);
    if (fp != NULL)
        item->setData(Qt::UserRole + 4, fp->outputName());
    else
        item->setData(Qt::UserRole + 4, KOutputNone);
}

void InputOutputManager::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
{
    Q_UNUSED(channel);
    Q_UNUSED(value);

    QListWidgetItem *item = m_list->item(universe);
    if (item == NULL)
        return;

    /* Show an icon on a universe row that received input data */
    item->setData(Qt::DecorationRole, m_icon);

    /* Restart the timer */
    m_timer->start(300);
}

void InputOutputManager::slotTimerTimeout()
{
    for (int i = 0; i < m_list->count(); i++)
    {
        QListWidgetItem *item = m_list->item(i);
        item->setData(Qt::DecorationRole, QIcon());
    }
}

void InputOutputManager::slotCurrentItemChanged()
{
    QListWidgetItem* item = m_list->currentItem();
    if (item == NULL)
    {
        m_list->setCurrentItem(m_list->item(0));
        item = m_list->currentItem();
    }
    //Q_ASSERT(item != NULL);
    if (item == NULL)
        return;

    if (m_editor != NULL)
    {
        m_splitter->widget(1)->layout()->removeWidget(m_editor);
        m_editor->deleteLater();
        m_editor = NULL;
        //delete currentEditor();
    }

    quint32 universe = item->data(Qt::UserRole).toInt();
    m_editor = new InputOutputPatchEditor(this, universe, m_ioMap);
    m_splitter->widget(1)->layout()->addWidget(m_editor);
    connect(m_editor, SIGNAL(mappingChanged()), this, SLOT(slotMappingChanged()));
    connect(m_editor, SIGNAL(audioInputDeviceChanged()), this, SLOT(slotAudioInputChanged()));
    m_editor->show();
    m_uniNameEdit->setText(item->data(Qt::DisplayRole).toString());
}

void InputOutputManager::slotMappingChanged()
{
    QListWidgetItem* item = m_list->currentItem();
    if (item != NULL)
    {
        uint universe = item->data(Qt::UserRole).toInt();
        updateItem(item, universe);
        m_doc->inputOutputMap()->saveDefaults();
    }
}

void InputOutputManager::slotAudioInputChanged()
{
    m_doc->destroyAudioCapture();
}

void InputOutputManager::slotAddUniverse()
{
    m_ioMap->addUniverse();
    updateList();
}

void InputOutputManager::slotDeleteUniverse()
{
    m_ioMap->removeUniverse();
    updateList();
}

void InputOutputManager::slotUniverseNameChanged(QString name)
{
    QListWidgetItem *currItem = m_list->currentItem();
    int uniIdx = m_list->currentRow();
    if (name.isEmpty())
        name = tr("Universe %1").arg(uniIdx + 1);
    m_ioMap->setUniverseName(uniIdx, name);
    currItem->setData(Qt::DisplayRole, name);
}

<commit_msg>InputOutputManager: if manager is not visible don't even waste CPU<commit_after>/*
  Q Light Controller
  inputoutputmanager.cpp

  Copyright (c) Massimo Callegari

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include <QListWidgetItem>
#include <QListWidget>
#include <QHeaderView>
#include <QStringList>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QSettings>
#include <QSplitter>
#include <QLineEdit>
#include <QToolBar>
#include <QAction>
#include <QTimer>
#include <QDebug>
#include <QLabel>
#include <QIcon>

#include "inputoutputpatcheditor.h"
#include "universeitemwidget.h"
#include "inputoutputmanager.h"
#include "inputoutputmap.h"
#include "outputpatch.h"
#include "inputpatch.h"
#include "apputil.h"
#include "doc.h"

#define KColumnUniverse     0
#define KColumnInput        1
#define KColumnOutput       2
#define KColumnFeedback     3
#define KColumnProfile      4
#define KColumnInputNum     5
#define KColumnOutputNum    6

#define SETTINGS_SPLITTER "inputmanager/splitter"

InputOutputManager* InputOutputManager::s_instance = NULL;

InputOutputManager::InputOutputManager(QWidget* parent, Doc* doc)
    : QWidget(parent)
    , m_doc(doc)
    , m_toolbar(NULL)
    , m_addUniverseAction(NULL)
    , m_deleteUniverseAction(NULL)
    , m_uniNameEdit(NULL)
    , m_editor(NULL)
{
    Q_ASSERT(s_instance == NULL);
    s_instance = this;

    Q_ASSERT(doc != NULL);

    m_ioMap = doc->inputOutputMap();

    /* Create a new layout for this widget */
    new QVBoxLayout(this);
    layout()->setContentsMargins(0, 0, 0, 0);
    layout()->setSpacing(0);

    m_splitter = new QSplitter(Qt::Horizontal, this);
    layout()->addWidget(m_splitter);

    m_addUniverseAction = new QAction(QIcon(":/edit_add.png"),
                                   tr("Add U&niverse"), this);
    m_addUniverseAction->setShortcut(QKeySequence("CTRL+N"));
    connect(m_addUniverseAction, SIGNAL(triggered(bool)),
            this, SLOT(slotAddUniverse()));

    m_deleteUniverseAction = new QAction(QIcon(":/edit_remove.png"),
                                   tr("&Delete Universe"), this);
    m_deleteUniverseAction->setShortcut(QKeySequence("CTRL+D"));
    connect(m_deleteUniverseAction, SIGNAL(triggered(bool)),
            this, SLOT(slotDeleteUniverse()));

    QWidget* ucontainer = new QWidget(this);
    m_splitter->addWidget(ucontainer);
    ucontainer->setLayout(new QVBoxLayout);
    ucontainer->layout()->setContentsMargins(0, 0, 0, 0);

    // Add a toolbar to the dock area
    m_toolbar = new QToolBar("Input Output Manager", this);
    m_toolbar->setFloatable(false);
    m_toolbar->setMovable(false);
    m_toolbar->setIconSize(QSize(32, 32));
    m_toolbar->addAction(m_addUniverseAction);
    m_toolbar->addAction(m_deleteUniverseAction);
    m_toolbar->addSeparator();

    QLabel *uniLabel = new QLabel(tr("Universe name:"));
    m_uniNameEdit = new QLineEdit(this);
    QFont font = QApplication::font();
    //font.setBold(true);
    font.setPixelSize(18);
    uniLabel->setFont(font);
    m_uniNameEdit->setFont(font);
    m_toolbar->addWidget(uniLabel);
    m_toolbar->addWidget(m_uniNameEdit);

    m_splitter->widget(0)->layout()->addWidget(m_toolbar);

    connect(m_uniNameEdit, SIGNAL(textChanged(QString)),
            this, SLOT(slotUniverseNameChanged(QString)));

    /* Universes list */
    m_list = new QListWidget(this);
    m_list->setItemDelegate(new UniverseItemWidget(m_list));
    m_splitter->widget(0)->layout()->addWidget(m_list);

    QWidget* gcontainer = new QWidget(this);
    m_splitter->addWidget(gcontainer);
    gcontainer->setLayout(new QVBoxLayout);
    gcontainer->layout()->setContentsMargins(0, 0, 0, 0);

    connect(m_list, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
            this, SLOT(slotCurrentItemChanged()));

    /* Timer that clears the input data icon after a while */
    m_icon = QIcon(":/input.png");
    m_timer = new QTimer(this);
    m_timer->setSingleShot(true);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTimerTimeout()));

    /* Listen to input map's input data signals */
    connect(m_ioMap, SIGNAL(inputValueChanged(quint32,quint32,uchar)),
            this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));

    /* Listen to plugin configuration changes */
    connect(m_ioMap, SIGNAL(pluginConfigurationChanged(const QString&)),
            this, SLOT(updateList()));

    updateList();
    m_list->setCurrentItem(m_list->item(0));

    QSettings settings;
    QVariant var = settings.value(SETTINGS_SPLITTER);
    if (var.isValid() == true)
        m_splitter->restoreState(var.toByteArray());
}

InputOutputManager::~InputOutputManager()
{
    QSettings settings;
    settings.setValue(SETTINGS_SPLITTER, m_splitter->saveState());

    s_instance = NULL;
}

InputOutputManager* InputOutputManager::instance()
{
    return s_instance;
}

/*****************************************************************************
 * Tree widget
 *****************************************************************************/

void InputOutputManager::updateList()
{
    m_list->clear();
    for (quint32 uni = 0; uni < m_ioMap->universes(); uni++)
        updateItem(new QListWidgetItem(m_list), uni);
    m_list->setCurrentItem(m_list->item(0));
    m_uniNameEdit->setText(m_list->item(0)->data(Qt::DisplayRole).toString());

    if (m_ioMap->universes() == 4)
        m_deleteUniverseAction->setEnabled(false);
    else
        m_deleteUniverseAction->setEnabled(true);
}

void InputOutputManager::updateItem(QListWidgetItem* item, quint32 universe)
{
    Q_ASSERT(item != NULL);

    InputPatch* ip = m_ioMap->inputPatch(universe);
    OutputPatch* op = m_ioMap->outputPatch(universe);
    OutputPatch* fp = m_ioMap->feedbackPatch(universe);

    QString uniName = m_ioMap->getUniverseName(universe);
    if (uniName.isEmpty())
    {
        QString defUniName = tr("Universe %1").arg(universe + 1);
        m_ioMap->setUniverseName(universe, defUniName);
        item->setData(Qt::DisplayRole, defUniName);
    }
    else
        item->setData(Qt::DisplayRole, uniName);
    item->setSizeHint(QSize(m_list->width(), 50));
    item->setData(Qt::UserRole, universe);
    if (ip != NULL)
    {
        item->setData(Qt::UserRole + 1, ip->inputName());
        item->setData(Qt::UserRole + 2, ip->profileName());
    }
    else
    {
        item->setData(Qt::UserRole + 1, KInputNone);
        item->setData(Qt::UserRole + 2, KInputNone);
    }
    if (op != NULL)
        item->setData(Qt::UserRole + 3, op->outputName());
    else
        item->setData(Qt::UserRole + 3, KOutputNone);
    if (fp != NULL)
        item->setData(Qt::UserRole + 4, fp->outputName());
    else
        item->setData(Qt::UserRole + 4, KOutputNone);
}

void InputOutputManager::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
{
    Q_UNUSED(channel);
    Q_UNUSED(value);

    // If the manager is not visible, don't even waste CPU
    if (isVisible() == false)
        return;

    QListWidgetItem *item = m_list->item(universe);
    if (item == NULL)
        return;

    /* Show an icon on a universe row that received input data */
    item->setData(Qt::DecorationRole, m_icon);

    /* Restart the timer */
    m_timer->start(300);
}

void InputOutputManager::slotTimerTimeout()
{
    for (int i = 0; i < m_list->count(); i++)
    {
        QListWidgetItem *item = m_list->item(i);
        item->setData(Qt::DecorationRole, QIcon());
    }
}

void InputOutputManager::slotCurrentItemChanged()
{
    QListWidgetItem* item = m_list->currentItem();
    if (item == NULL)
    {
        m_list->setCurrentItem(m_list->item(0));
        item = m_list->currentItem();
    }
    //Q_ASSERT(item != NULL);
    if (item == NULL)
        return;

    if (m_editor != NULL)
    {
        m_splitter->widget(1)->layout()->removeWidget(m_editor);
        m_editor->deleteLater();
        m_editor = NULL;
        //delete currentEditor();
    }

    quint32 universe = item->data(Qt::UserRole).toInt();
    m_editor = new InputOutputPatchEditor(this, universe, m_ioMap);
    m_splitter->widget(1)->layout()->addWidget(m_editor);
    connect(m_editor, SIGNAL(mappingChanged()), this, SLOT(slotMappingChanged()));
    connect(m_editor, SIGNAL(audioInputDeviceChanged()), this, SLOT(slotAudioInputChanged()));
    m_editor->show();
    m_uniNameEdit->setText(item->data(Qt::DisplayRole).toString());
}

void InputOutputManager::slotMappingChanged()
{
    QListWidgetItem* item = m_list->currentItem();
    if (item != NULL)
    {
        uint universe = item->data(Qt::UserRole).toInt();
        updateItem(item, universe);
        m_doc->inputOutputMap()->saveDefaults();
    }
}

void InputOutputManager::slotAudioInputChanged()
{
    m_doc->destroyAudioCapture();
}

void InputOutputManager::slotAddUniverse()
{
    m_ioMap->addUniverse();
    updateList();
}

void InputOutputManager::slotDeleteUniverse()
{
    m_ioMap->removeUniverse();
    updateList();
}

void InputOutputManager::slotUniverseNameChanged(QString name)
{
    QListWidgetItem *currItem = m_list->currentItem();
    int uniIdx = m_list->currentRow();
    if (name.isEmpty())
        name = tr("Universe %1").arg(uniIdx + 1);
    m_ioMap->setUniverseName(uniIdx, name);
    currItem->setData(Qt::DisplayRole, name);
}

<|endoftext|>


<commit_before>//
// Copyright 2015 The ANGLE 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.
//
// EGLInitializePerfTest:
//   Performance test for device creation.
//

#include "ANGLEPerfTest.h"
#include "test_utils/angle_test_configs.h"
#include "test_utils/angle_test_instantiate.h"

using namespace testing;

namespace
{

class EGLInitializePerfTest : public ANGLEPerfTest,
                              public WithParamInterface<angle::PlatformParameters>
{
  public:
    EGLInitializePerfTest();
    ~EGLInitializePerfTest();

    void step(float dt, double totalTime) override;

  private:
    OSWindow *mOSWindow;
    EGLDisplay mDisplay;
};

EGLInitializePerfTest::EGLInitializePerfTest()
    : ANGLEPerfTest("EGLInitialize", "_run"),
      mOSWindow(nullptr),
      mDisplay(EGL_NO_DISPLAY)
{
    auto platform = GetParam().eglParameters;

    std::vector<EGLint> displayAttributes;
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
    displayAttributes.push_back(platform.renderer);
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
    displayAttributes.push_back(platform.majorVersion);
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
    displayAttributes.push_back(platform.minorVersion);

    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE ||
        platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
    {
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
        displayAttributes.push_back(platform.deviceType);
    }
    displayAttributes.push_back(EGL_NONE);

    mOSWindow = CreateOSWindow();
    mOSWindow->initialize("EGLInitialize Test", 64, 64);

    auto eglGetPlatformDisplayEXT =
        reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
    if (eglGetPlatformDisplayEXT == nullptr)
    {
        std::cerr << "Error getting platform display!" << std::endl;
        return;
    }

    mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
                                        mOSWindow->getNativeDisplay(),
                                        &displayAttributes[0]);
}

EGLInitializePerfTest::~EGLInitializePerfTest()
{
    SafeDelete(mOSWindow);
}

void EGLInitializePerfTest::step(float dt, double totalTime)
{
    ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);

    EGLint majorVersion, minorVersion;
    ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE);
    ASSERT_TRUE(eglTerminate(mDisplay) == EGL_TRUE);

    if (mTimer->getElapsedTime() >= 5.0)
    {
        mRunning = false;
    }
}

TEST_P(EGLInitializePerfTest, Run)
{
    run();
}

ANGLE_INSTANTIATE_TEST(EGLInitializePerfTest, angle::ES2_D3D11());

} // namespace
<commit_msg>Add more detailed captures to EGL init perf test.<commit_after>//
// Copyright 2015 The ANGLE 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.
//
// EGLInitializePerfTest:
//   Performance test for device creation.
//

#include "ANGLEPerfTest.h"
#include "Timer.h"
#include "test_utils/angle_test_configs.h"
#include "test_utils/angle_test_instantiate.h"
#include "platform/Platform.h"

using namespace testing;

namespace
{

// Only applies to D3D11
class CapturePlatform : public angle::Platform
{
  public:
    CapturePlatform()
        : mLoadDLLsMS(0),
          mCreateDeviceMS(0),
          mInitResourcesMS(0),
          mTimer(CreateTimer())
    {
        mTimer->start();
    }

    double currentTime() override;
    void histogramCustomCounts(
        const char *name, int sample, int min, int max, int bucketCount) override;

    size_t getLoadDLLsMS() const { return mLoadDLLsMS; }
    size_t getCreateDeviceMS() const { return mCreateDeviceMS; }
    size_t getInitResourcesMS() const { return mInitResourcesMS; }

  private:
    Timer *mTimer;
    size_t mLoadDLLsMS;
    size_t mCreateDeviceMS;
    size_t mInitResourcesMS;
};

double CapturePlatform::currentTime()
{
    return mTimer->getElapsedTime();
}

void CapturePlatform::histogramCustomCounts(
    const char *name, int sample, int /*min*/, int /*max*/, int /*bucketCount*/)
{
    // These must match the names of the histograms.
    if (strcmp(name, "GPU.ANGLE.Renderer11InitializeDLLsMS") == 0)
    {
        mLoadDLLsMS += static_cast<size_t>(sample);
    }
    // Note: not captured in debug, due to creating a debug device
    else if (strcmp(name, "GPU.ANGLE.D3D11CreateDeviceMS") == 0)
    {
        mCreateDeviceMS += static_cast<size_t>(sample);
    }
    else if (strcmp(name, "GPU.ANGLE.Renderer11InitializeDeviceMS") == 0)
    {
        mInitResourcesMS += static_cast<size_t>(sample);
    }
}

class EGLInitializePerfTest : public ANGLEPerfTest,
                              public WithParamInterface<angle::PlatformParameters>
{
  public:
    EGLInitializePerfTest();
    ~EGLInitializePerfTest();

    void step(float dt, double totalTime) override;
    void TearDown() override;

  private:
    OSWindow *mOSWindow;
    EGLDisplay mDisplay;
    CapturePlatform mCapturePlatform;
};

EGLInitializePerfTest::EGLInitializePerfTest()
    : ANGLEPerfTest("EGLInitialize", "_run"),
      mOSWindow(nullptr),
      mDisplay(EGL_NO_DISPLAY)
{
    auto platform = GetParam().eglParameters;

    std::vector<EGLint> displayAttributes;
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
    displayAttributes.push_back(platform.renderer);
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
    displayAttributes.push_back(platform.majorVersion);
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
    displayAttributes.push_back(platform.minorVersion);

    if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE ||
        platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
    {
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
        displayAttributes.push_back(platform.deviceType);
    }
    displayAttributes.push_back(EGL_NONE);

    mOSWindow = CreateOSWindow();
    mOSWindow->initialize("EGLInitialize Test", 64, 64);

    auto eglGetPlatformDisplayEXT =
        reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
    if (eglGetPlatformDisplayEXT == nullptr)
    {
        std::cerr << "Error getting platform display!" << std::endl;
        return;
    }

    mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
                                        mOSWindow->getNativeDisplay(),
                                        &displayAttributes[0]);

    ANGLEPlatformInitialize(&mCapturePlatform);
}

EGLInitializePerfTest::~EGLInitializePerfTest()
{
    SafeDelete(mOSWindow);
}

void EGLInitializePerfTest::step(float dt, double totalTime)
{
    ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);

    EGLint majorVersion, minorVersion;
    ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE);
    ASSERT_TRUE(eglTerminate(mDisplay) == EGL_TRUE);

    if (mTimer->getElapsedTime() >= 5.0)
    {
        mRunning = false;
    }
}

void EGLInitializePerfTest::TearDown()
{
    ANGLEPerfTest::TearDown();
    printResult("LoadDLLs", mCapturePlatform.getLoadDLLsMS(), "ms", true);
    printResult("D3D11CreateDevice", mCapturePlatform.getCreateDeviceMS(), "ms", true);
    printResult("InitResources", mCapturePlatform.getInitResourcesMS(), "ms", true);

    ANGLEPlatformShutdown();
}

TEST_P(EGLInitializePerfTest, Run)
{
    run();
}

ANGLE_INSTANTIATE_TEST(EGLInitializePerfTest, angle::ES2_D3D11());

} // namespace
<|endoftext|>


<commit_before>#include "SkBitmapProcState.h"
#include "SkPerspIter.h"
#include "SkShader.h"

void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);

#ifdef SK_CPU_BENDIAN
    #define PACK_TWO_SHORTS(pri, sec) ((pri) << 16 | (sec))
#else
    #define PACK_TWO_SHORTS(pri, sec) ((pri) | ((sec) << 16))
#endif

#ifdef SK_DEBUG
    static uint32_t pack_two_shorts(U16CPU pri, U16CPU sec)
    {
        SkASSERT((uint16_t)pri == pri);
        SkASSERT((uint16_t)sec == sec);
        return PACK_TWO_SHORTS(pri, sec);
    }
#else
    #define pack_two_shorts(pri, sec)   PACK_TWO_SHORTS(pri, sec)
#endif

#define MAKENAME(suffix)        ClampX_ClampY ## suffix
#define TILEX_PROCF(fx, max)    SkClampMax((fx) >> 16, max)
#define TILEY_PROCF(fy, max)    SkClampMax((fy) >> 16, max)
#define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
#define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
#define CHECK_FOR_DECAL
#define TILEX_TRANS(x, max)     SkClampMax(x, max)
#define TILEY_TRANS(y, max)     SkClampMax(y, max)
#include "SkBitmapProcState_matrix.h"

#define MAKENAME(suffix)        RepeatX_RepeatY ## suffix
#define TILEX_PROCF(fx, max)    (((fx) & 0xFFFF) * ((max) + 1) >> 16)
#define TILEY_PROCF(fy, max)    (((fy) & 0xFFFF) * ((max) + 1) >> 16)
#define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
#define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
#define TILEX_TRANS(x, max)     ((x) % ((max) + 1))
#define TILEY_TRANS(y, max)     ((y) % ((max) + 1))
#include "SkBitmapProcState_matrix.h"

#define MAKENAME(suffix)        GeneralXY ## suffix
#define PREAMBLE(state)         SkBitmapProcState::FixedTileProc tileProcX = (state).fTileProcX; \
                                SkBitmapProcState::FixedTileProc tileProcY = (state).fTileProcY
#define PREAMBLE_PARAM_X        , SkBitmapProcState::FixedTileProc tileProcX
#define PREAMBLE_PARAM_Y        , SkBitmapProcState::FixedTileProc tileProcY
#define PREAMBLE_ARG_X          , tileProcX
#define PREAMBLE_ARG_Y          , tileProcY
#define TILEX_PROCF(fx, max)    (tileProcX(fx, max) >> 16)
#define TILEY_PROCF(fy, max)    (tileProcY(fy, max) >> 16)
#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx, max) >> 14) & 0x3)
#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy, max) >> 14) & 0x3)
#define PREAMBLE_TRANS(state)   SkBitmapProcState::IntTileProc tileProcX = (state).iTileProcX; \
                                SkBitmapProcState::IntTileProc tileProcY = (state).iTileProcY
#define TILEX_TRANS(x, max)     tileProcX(x, max)
#define TILEY_TRANS(y, max)     tileProcY(y, max)
#include "SkBitmapProcState_matrix.h"

static inline SkFixed fixed_clamp(SkFixed x, int max)
{
#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
    if (x >> 16)
        x = 0xFFFF;
    if (x < 0)
        x = 0;
#else
    if (x >> 16)
    {
        if (x < 0)
            x = 0;
        else
            x = 0xFFFF;
    }
#endif
    return x * (max + 1);
}

static inline SkFixed fixed_repeat(SkFixed x, int max)
{
    return (x & 0xFFFF) * (max + 1);
}

static inline SkFixed fixed_mirror(SkFixed x, int max)
{
    SkFixed s = x << 15 >> 31;
    // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
    x = ((x ^ s) & 0xFFFF) * (max + 1);
    return s ? (x ^ 0xFFFF) : x;
}

static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
{
    if (SkShader::kClamp_TileMode == m)
        return fixed_clamp;
    if (SkShader::kRepeat_TileMode == m)
        return fixed_repeat;
    SkASSERT(SkShader::kMirror_TileMode == m);
    return fixed_mirror;
}

static inline int int_clamp(int x, int max)
{
    SkASSERT(max >= 0);

    return SkClampMax(x, max);
}

static inline int int_repeat(int x, int max)
{
    SkASSERT(max >= 0);

    return x % (max + 1);
}

static inline int int_mirror(int x, int max)
{
    SkASSERT(max >= 0);

    int dx = x % (max + 1);
    if (dx < 0)
        dx = -dx - 1;

    return (x / (max + 1) % 2) ? max - dx : dx;
}

static SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned m)
{
    if (SkShader::kClamp_TileMode == m)
        return int_clamp;
    if (SkShader::kRepeat_TileMode == m)
        return int_repeat;
    SkASSERT(SkShader::kMirror_TileMode == m);
    return int_mirror;
}

SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc()
{
    int index = 0;
    if (fDoFilter)
        index = 1;
    if (fInvType & SkMatrix::kPerspective_Mask)
        index |= 6;
    else if (fInvType & SkMatrix::kAffine_Mask)
        index |= 4;
    else if (fInvType & SkMatrix::kScale_Mask)
        index |= 2;

    if (SkShader::kClamp_TileMode == fTileModeX &&
        SkShader::kClamp_TileMode == fTileModeY)
    {
        // clamp gets special version of filterOne
        fFilterOneX = SK_Fixed1;
        fFilterOneY = SK_Fixed1;
        return ClampX_ClampY_Procs[index];
    }

    // all remaining procs use this form for filterOne
    fFilterOneX = SK_Fixed1 / fBitmap->width();
    fFilterOneY = SK_Fixed1 / fBitmap->height();

    if (SkShader::kRepeat_TileMode == fTileModeX &&
        SkShader::kRepeat_TileMode == fTileModeY)
    {
        return RepeatX_RepeatY_Procs[index];
    }

    // only general needs these procs
    fTileProcX = choose_tile_proc(fTileModeX);
    fTileProcY = choose_tile_proc(fTileModeY);
    iTileProcX = choose_int_tile_proc(fTileModeX);
    iTileProcY = choose_int_tile_proc(fTileModeY);
    return GeneralXY_Procs[index];
}

//////////////////////////////////////////////////////////////////////////////

void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
{
    int i;

    for (i = (count >> 2); i > 0; --i)
    {
        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
        fx += dx+dx;
        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
        fx += dx+dx;
    }
    uint16_t* xx = (uint16_t*)dst;

    for (i = (count & 3); i > 0; --i)
    {
        *xx++ = SkToU16(fx >> 16); fx += dx;
    }
}

void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
{
    if (count & 1)
    {
        SkASSERT((fx >> (16 + 14)) == 0);
        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
        fx += dx;
    }
    while ((count -= 2) >= 0)
    {
        SkASSERT((fx >> (16 + 14)) == 0);
        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
        fx += dx;

        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
        fx += dx;
    }
}

///////////////////////////////////

void repeat_nofilter_identity(uint32_t dst[], int x, int width, int count)
{
    if (x >= width)
        x %= width;

    int i;
    uint16_t* xx = (uint16_t*)dst;

    // do the first partial run
    int n = width - x;
    if (n > count)
        n = count;

    count -= n;
    n += x;
    for (i = x; i < n; i++)
        *xx++ = SkToU16(i);

    // do all the full-width runs
    while ((count -= width) >= 0)
        for (i = 0; i < width; i++)
            *xx++ = SkToU16(i);

    // final cleanup run
    count += width;
    for (i = 0; i < count; i++)
        *xx++ = SkToU16(i);
}

<commit_msg>In certain cases, the coordinates used for pattern rendering can go negative, eg., when a negative translation is applied in the shader matrix.  This causes the rasterizer to blow up, since it accesses memory outside the pattern bitmap.<commit_after>#include "SkBitmapProcState.h"
#include "SkPerspIter.h"
#include "SkShader.h"

void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);

#ifdef SK_CPU_BENDIAN
    #define PACK_TWO_SHORTS(pri, sec) ((pri) << 16 | (sec))
#else
    #define PACK_TWO_SHORTS(pri, sec) ((pri) | ((sec) << 16))
#endif

#ifdef SK_DEBUG
    static uint32_t pack_two_shorts(U16CPU pri, U16CPU sec)
    {
        SkASSERT((uint16_t)pri == pri);
        SkASSERT((uint16_t)sec == sec);
        return PACK_TWO_SHORTS(pri, sec);
    }
#else
    #define pack_two_shorts(pri, sec)   PACK_TWO_SHORTS(pri, sec)
#endif

#define MAKENAME(suffix)        ClampX_ClampY ## suffix
#define TILEX_PROCF(fx, max)    SkClampMax((fx) >> 16, max)
#define TILEY_PROCF(fy, max)    SkClampMax((fy) >> 16, max)
#define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
#define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
#define CHECK_FOR_DECAL
#define TILEX_TRANS(x, max)     SkClampMax(x, max)
#define TILEY_TRANS(y, max)     SkClampMax(y, max)
#include "SkBitmapProcState_matrix.h"

#define MAKENAME(suffix)        RepeatX_RepeatY ## suffix
#define TILEX_PROCF(fx, max)    (((fx) & 0xFFFF) * ((max) + 1) >> 16)
#define TILEY_PROCF(fy, max)    (((fy) & 0xFFFF) * ((max) + 1) >> 16)
#define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
#define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
#define SK_MOD(a, b)            (((a)%(b)) < 0 ? ((a)%(b) + (b)) : (a)%(b))
#define TILEX_TRANS(x, max)     (SK_MOD((x), ((max) + 1)))
#define TILEY_TRANS(y, max)     (SK_MOD((y), ((max) + 1)))
#include "SkBitmapProcState_matrix.h"

#define MAKENAME(suffix)        GeneralXY ## suffix
#define PREAMBLE(state)         SkBitmapProcState::FixedTileProc tileProcX = (state).fTileProcX; \
                                SkBitmapProcState::FixedTileProc tileProcY = (state).fTileProcY
#define PREAMBLE_PARAM_X        , SkBitmapProcState::FixedTileProc tileProcX
#define PREAMBLE_PARAM_Y        , SkBitmapProcState::FixedTileProc tileProcY
#define PREAMBLE_ARG_X          , tileProcX
#define PREAMBLE_ARG_Y          , tileProcY
#define TILEX_PROCF(fx, max)    (tileProcX(fx, max) >> 16)
#define TILEY_PROCF(fy, max)    (tileProcY(fy, max) >> 16)
#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx, max) >> 14) & 0x3)
#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy, max) >> 14) & 0x3)
#define PREAMBLE_TRANS(state)   SkBitmapProcState::IntTileProc tileProcX = (state).iTileProcX; \
                                SkBitmapProcState::IntTileProc tileProcY = (state).iTileProcY
#define TILEX_TRANS(x, max)     tileProcX(x, max)
#define TILEY_TRANS(y, max)     tileProcY(y, max)
#include "SkBitmapProcState_matrix.h"

static inline SkFixed fixed_clamp(SkFixed x, int max)
{
#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
    if (x >> 16)
        x = 0xFFFF;
    if (x < 0)
        x = 0;
#else
    if (x >> 16)
    {
        if (x < 0)
            x = 0;
        else
            x = 0xFFFF;
    }
#endif
    return x * (max + 1);
}

static inline SkFixed fixed_repeat(SkFixed x, int max)
{
    return (x & 0xFFFF) * (max + 1);
}

static inline SkFixed fixed_mirror(SkFixed x, int max)
{
    SkFixed s = x << 15 >> 31;
    // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
    x = ((x ^ s) & 0xFFFF) * (max + 1);
    return s ? (x ^ 0xFFFF) : x;
}

static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
{
    if (SkShader::kClamp_TileMode == m)
        return fixed_clamp;
    if (SkShader::kRepeat_TileMode == m)
        return fixed_repeat;
    SkASSERT(SkShader::kMirror_TileMode == m);
    return fixed_mirror;
}

static inline int int_clamp(int x, int max)
{
    SkASSERT(max >= 0);

    return SkClampMax(x, max);
}

static inline int int_repeat(int x, int max)
{
    SkASSERT(max >= 0);

    return x % (max + 1);
}

static inline int int_mirror(int x, int max)
{
    SkASSERT(max >= 0);

    int dx = x % (max + 1);
    if (dx < 0)
        dx = -dx - 1;

    return (x / (max + 1) % 2) ? max - dx : dx;
}

static SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned m)
{
    if (SkShader::kClamp_TileMode == m)
        return int_clamp;
    if (SkShader::kRepeat_TileMode == m)
        return int_repeat;
    SkASSERT(SkShader::kMirror_TileMode == m);
    return int_mirror;
}

SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc()
{
    int index = 0;
    if (fDoFilter)
        index = 1;
    if (fInvType & SkMatrix::kPerspective_Mask)
        index |= 6;
    else if (fInvType & SkMatrix::kAffine_Mask)
        index |= 4;
    else if (fInvType & SkMatrix::kScale_Mask)
        index |= 2;

    if (SkShader::kClamp_TileMode == fTileModeX &&
        SkShader::kClamp_TileMode == fTileModeY)
    {
        // clamp gets special version of filterOne
        fFilterOneX = SK_Fixed1;
        fFilterOneY = SK_Fixed1;
        return ClampX_ClampY_Procs[index];
    }

    // all remaining procs use this form for filterOne
    fFilterOneX = SK_Fixed1 / fBitmap->width();
    fFilterOneY = SK_Fixed1 / fBitmap->height();

    if (SkShader::kRepeat_TileMode == fTileModeX &&
        SkShader::kRepeat_TileMode == fTileModeY)
    {
        return RepeatX_RepeatY_Procs[index];
    }

    // only general needs these procs
    fTileProcX = choose_tile_proc(fTileModeX);
    fTileProcY = choose_tile_proc(fTileModeY);
    iTileProcX = choose_int_tile_proc(fTileModeX);
    iTileProcY = choose_int_tile_proc(fTileModeY);
    return GeneralXY_Procs[index];
}

//////////////////////////////////////////////////////////////////////////////

void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
{
    int i;

    for (i = (count >> 2); i > 0; --i)
    {
        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
        fx += dx+dx;
        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
        fx += dx+dx;
    }
    uint16_t* xx = (uint16_t*)dst;

    for (i = (count & 3); i > 0; --i)
    {
        *xx++ = SkToU16(fx >> 16); fx += dx;
    }
}

void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
{
    if (count & 1)
    {
        SkASSERT((fx >> (16 + 14)) == 0);
        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
        fx += dx;
    }
    while ((count -= 2) >= 0)
    {
        SkASSERT((fx >> (16 + 14)) == 0);
        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
        fx += dx;

        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
        fx += dx;
    }
}

///////////////////////////////////

void repeat_nofilter_identity(uint32_t dst[], int x, int width, int count)
{
    if (x >= width)
        x %= width;

    int i;
    uint16_t* xx = (uint16_t*)dst;

    // do the first partial run
    int n = width - x;
    if (n > count)
        n = count;

    count -= n;
    n += x;
    for (i = x; i < n; i++)
        *xx++ = SkToU16(i);

    // do all the full-width runs
    while ((count -= width) >= 0)
        for (i = 0; i < width; i++)
            *xx++ = SkToU16(i);

    // final cleanup run
    count += width;
    for (i = 0; i < count; i++)
        *xx++ = SkToU16(i);
}

<|endoftext|>


<commit_before>#include <cstdio>
#include <cassert>
#include <sstream>

#include "genome.h"
#include "gtf.h"
#include "config.h"
#include "assembler.h"
#include "scallop2.h"
#include "scallop3.h"
#include "sgraph_compare.h"

assembler::assembler()
{
    sfn = sam_open(input_file.c_str(), "r");
    hdr = sam_hdr_read(sfn);
    b1t = bam_init1();
	terminate = false;
	index = -1;
	if(output_file != "") fout.open(output_file);
}

assembler::~assembler()
{
    bam_destroy1(b1t);
    bam_hdr_destroy(hdr);
    sam_close(sfn);
	if(output_file != "") fout.close();
}

int assembler::assemble()
{
    while(sam_read1(sfn, hdr, b1t) >= 0)
	{
		if(terminate == true) return 0;

		bam1_core_t &p = b1t->core;

		if((p.flag & 0x4) >= 1) continue;			// read is not mapped
		if((p.flag & 0x100) >= 1) continue;		// secondary alignment
		if(p.n_cigar < 1) continue;				// should never happen
		if(p.n_cigar > MAX_NUM_CIGAR) continue;	// ignore hits with more than 7 cigar types
		if(p.qual < min_mapping_quality) continue;	// ignore hits with small quality

		hit ht(b1t);
		if(ht.strand == '.') continue;	// TODO

		truncate(ht);
		add_hit(ht);
    }

	for(int i = 0; i < vbb.size(); i++) process(vbb[i]);

	return 0;
}

int assembler::add_hit(const hit &ht)
{
	bool b = false;
	for(int i = 0; i < vbb.size(); i++)
	{
		bundle_base &bb = vbb[i];
		assert(bb.hits.size() >= 1);
		assert(bb.strand != '.');

		//if(bb.overlap(ht) == false) continue;
		if(ht.strand != bb.strand) continue;
		if(ht.tid != bb.tid) continue;
		if(ht.pos > bb.rpos + min_bundle_gap) continue;

		bb.add_hit(ht);
		b = true;
		break;
	}

	if(b == true) return 0;

	bundle_base bb;
	bb.add_hit(ht);

	vbb.push_back(bb);

	return 0;
}

int assembler::truncate(const hit &ht)
{
	for(int i = 0; i < vbb.size(); i++)
	{
		bundle_base &bb = vbb[i];
		//if(ht.pos < bb.rpos && ht.tid == bb.tid) continue;
		if(ht.pos <= bb.rpos + min_bundle_gap && ht.tid == bb.tid) continue;

		process(bb);
		vbb.erase(vbb.begin() + i);
		truncate(ht);
	}
	return 0;
}

int assembler::process(const bundle_base &bb)
{
	if(bb.hits.size() < min_num_hits_in_bundle) return 0;

	char buf[1024];
	assert(bb.tid >= 0);
	strcpy(buf, hdr->target_name[bb.tid]);

	bundle bd(bb);

	bd.chrm = string(buf);
	bd.build();

	if(bd.junctions.size() <= 0 && ignore_single_exon_transcripts) return 0;

	index++;
	bd.print(index);

	if(ref_file1 != "" && bd.strand == '+') compare(bd.sg.root, ref_file1, "compare1.tex");
	if(ref_file2 != "" && bd.strand == '-') compare(bd.sg.root, ref_file2, "compare2.tex");

	for(int k = 0; k < bd.sg.subs.size(); k++)
	{
		string name = "bundle." + tostring(index) + "." + tostring(k);
		/*
		int slen = fixed_gene_name.size();
		if(slen > name.size()) slen = name.size();
		string ss = name.substr(0, slen);
		*/

		if(fixed_gene_name != "" && name != fixed_gene_name) continue;

		splice_graph &gr = bd.sg.subs[k];

		if(algo != "shao")
		{
			scallop3 sc(name, gr);
			sc.assemble();

			if(output_file != "")
			{
				for(int i = 0; i < sc.paths.size(); i++)
				{
					string tid = name + "." + tostring(i);
					path p;
					p.v = bd.sg.get_root_vertices(k, sc.paths[i].v);
					p.abd = sc.paths[i].abd;
					bd.output_transcript(fout, p, name, tid);
				}
			}
		}

		if(fixed_gene_name != "" && name == fixed_gene_name) terminate = true;
		if(terminate == true) return 0;
	}

	return 0;
}

int assembler::compare(splice_graph &gr, const string &file, const string &texfile)
{
	if(file == "") return 0;

	genome g(file);
	if(g.genes.size() <= 0) return 0;

	gtf gg(g.genes[0]);

	splice_graph gt;
	gg.build_splice_graph(gt);

	sgraph_compare sgc(gt, gr);
	sgc.compare(texfile);
	//sgc.compare(string("compare.") + tostring(index) + string(".tex"));

	return 0;
}
<commit_msg>update<commit_after>#include <cstdio>
#include <cassert>
#include <sstream>

#include "genome.h"
#include "gtf.h"
#include "config.h"
#include "assembler.h"
#include "scallop2.h"
#include "scallop3.h"
#include "sgraph_compare.h"

assembler::assembler()
{
    sfn = sam_open(input_file.c_str(), "r");
    hdr = sam_hdr_read(sfn);
    b1t = bam_init1();
	terminate = false;
	index = -1;
	if(output_file != "") fout.open(output_file);
}

assembler::~assembler()
{
    bam_destroy1(b1t);
    bam_hdr_destroy(hdr);
    sam_close(sfn);
	if(output_file != "") fout.close();
}

int assembler::assemble()
{
    while(sam_read1(sfn, hdr, b1t) >= 0)
	{
		if(terminate == true) return 0;

		bam1_core_t &p = b1t->core;

		if((p.flag & 0x4) >= 1) continue;			// read is not mapped
		if((p.flag & 0x100) >= 1) continue;		// secondary alignment
		if(p.n_cigar < 1) continue;				// should never happen
		if(p.n_cigar > MAX_NUM_CIGAR) continue;	// ignore hits with more than 7 cigar types
		if(p.qual < min_mapping_quality) continue;	// ignore hits with small quality

		hit ht(b1t);
		if(ht.strand == '.') continue;	// TODO

		truncate(ht);
		add_hit(ht);
    }

	for(int i = 0; i < vbb.size(); i++) process(vbb[i]);

	return 0;
}

int assembler::add_hit(const hit &ht)
{
	bool b = false;
	for(int i = 0; i < vbb.size(); i++)
	{
		bundle_base &bb = vbb[i];
		assert(bb.hits.size() >= 1);
		assert(bb.strand != '.');

		//if(bb.overlap(ht) == false) continue;
		if(ht.strand != bb.strand) continue;
		if(ht.tid != bb.tid) continue;
		if(ht.pos > bb.rpos + min_bundle_gap) continue;

		bb.add_hit(ht);
		b = true;
		break;
	}

	if(b == true) return 0;

	bundle_base bb;
	bb.add_hit(ht);

	vbb.push_back(bb);

	return 0;
}

int assembler::truncate(const hit &ht)
{
	for(int i = 0; i < vbb.size(); i++)
	{
		bundle_base &bb = vbb[i];
		if(ht.pos <= bb.rpos + min_bundle_gap && ht.tid == bb.tid) continue;

		process(bb);
		vbb.erase(vbb.begin() + i);
		truncate(ht);
	}
	return 0;
}

int assembler::process(const bundle_base &bb)
{
	if(bb.hits.size() < min_num_hits_in_bundle) return 0;

	char buf[1024];
	assert(bb.tid >= 0);
	strcpy(buf, hdr->target_name[bb.tid]);

	bundle bd(bb);

	bd.chrm = string(buf);
	bd.build();

	if(bd.junctions.size() <= 0 && ignore_single_exon_transcripts) return 0;

	index++;
	bd.print(index);

	if(ref_file1 != "" && bd.strand == '+') compare(bd.sg.root, ref_file1, "compare1.tex");
	if(ref_file2 != "" && bd.strand == '-') compare(bd.sg.root, ref_file2, "compare2.tex");

	for(int k = 0; k < bd.sg.subs.size(); k++)
	{
		string name = "bundle." + tostring(index) + "." + tostring(k);
		/*
		int slen = fixed_gene_name.size();
		if(slen > name.size()) slen = name.size();
		string ss = name.substr(0, slen);
		*/

		if(fixed_gene_name != "" && name != fixed_gene_name) continue;

		splice_graph &gr = bd.sg.subs[k];

		if(algo != "shao")
		{
			scallop3 sc(name, gr);
			sc.assemble();

			if(output_file != "")
			{
				for(int i = 0; i < sc.paths.size(); i++)
				{
					string tid = name + "." + tostring(i);
					path p;
					p.v = bd.sg.get_root_vertices(k, sc.paths[i].v);
					p.abd = sc.paths[i].abd;
					bd.output_transcript(fout, p, name, tid);
				}
			}
		}

		if(fixed_gene_name != "" && name == fixed_gene_name) terminate = true;
		if(terminate == true) return 0;
	}

	return 0;
}

int assembler::compare(splice_graph &gr, const string &file, const string &texfile)
{
	if(file == "") return 0;

	genome g(file);
	if(g.genes.size() <= 0) return 0;

	gtf gg(g.genes[0]);

	splice_graph gt;
	gg.build_splice_graph(gt);

	sgraph_compare sgc(gt, gr);
	sgc.compare(texfile);
	//sgc.compare(string("compare.") + tostring(index) + string(".tex"));

	return 0;
}
<|endoftext|>


<commit_before>#include <list>
#include <vector>
using namespace std;
#include <climits>
#include "algorithms.h"
#include "graph.h"
#include "heuristics.h"
#include "stats.h"
#include "node_heap.h"

typedef list<Node*>::iterator list_iter;
typedef vector<Node*>::iterator vector_iter;

// These algorithms 'close' nodes by flagging them with the id of the
// current problem being solved.  This saves us unclosing every node
// after solving each path.
int problem_id = 1;

inline void init_new_problem(Graph & graph, Stats & stats) {
  ++ stats.num_problems;
  ++ problem_id;
  // check integer overflow; problem_ids are no longer unique, so reset.
  if (problem_id == 0) {
    for (size_t ii = 0; ii < graph.graph_view.size(); ++ ii)
      graph.graph_view[ii]->closed_id = 0;
    problem_id = 1;
  }
}

inline void reconstruct_path(Node* start, Node* current,
                             unsigned int (*cost)(Node*, Node*),
                             Stats & stats) {
  while (current != start) {
    stats.path_cost += cost(current->whence, current);
    ++ stats.path_length;
    current = current->whence;
  }
}

/// A-star with no optimizations, not even sorting the open list.
/// Additionally contains some validations on the result.
void astar_basic(Graph & graph, Node* start, Node* goal, Stats & stats,
                 unsigned int (*h)(Node* n1, Node* n2)) {
  init_new_problem(graph, stats);
  static vector<Node*> open_list;
  start->open = true;
  start->relax(0, h(start, goal), NULL);
  open_list.push_back(start);

  while (!open_list.empty()) {
    int fmin = INT_MAX;
    vector_iter best_on_open_list;
    // Pop the best node off the open_list via linear scan
    for (vector_iter node = open_list.begin();
         node != open_list.end(); ++ node) {
      if ((*node)->f < fmin) {
        fmin = (*node)->f;
        best_on_open_list = node;
      }
    }
    Node* expand_me = *best_on_open_list;
    if (expand_me == goal)
      break;
    expand_me->expand(problem_id);
    ++ stats.nodes_expanded;
    // remove it by overwriting it with the back() node
    *best_on_open_list = open_list.back();
    open_list.pop_back();

    // Add each neighbor
    for (vector_iter ii = expand_me->neighbors_out.begin();
         ii != expand_me->neighbors_out.end(); ++ ii) {
      Node* add_me = *ii;
      if (add_me->closed(problem_id))
        continue;
      const int g = expand_me->g + graph.cost(expand_me, add_me);
      if (!add_me->open) {       // If it's not open, open it
        add_me->open = true;
        add_me->relax(g, h(add_me, goal), expand_me);
        open_list.push_back(add_me);
      }
      else if (add_me->g > g) {  // If it is open, relax it
        add_me->relax(g, h(add_me, goal), expand_me);
      }
    }
  }

  // Stats collection & cleanup
  stats.open_list_size += open_list.size();
  reconstruct_path(start, goal, graph.cost, stats);
  for (vector_iter ii = open_list.begin(); ii != open_list.end(); ++ ii)
    (*ii)->open = false;
  open_list.clear();
}

/// A* with a binary heap.
void astar_heap(Graph & graph, Node* start, Node* goal, Stats & stats,
                unsigned int (*h)(Node* n1, Node* n2)) {
  init_new_problem(graph, stats);
  static vector<Node*> open_list;
  start->open = true;
  start->relax(0, h(start, goal), NULL);
  node_heap::push(open_list, start);

  while (!open_list.empty()) {
    // Pop the best node off the open_list (+ goal check)
    Node* expand_me = open_list.front();
    if (expand_me == goal)
      break;

    ++ stats.nodes_expanded;
    expand_me->expand(problem_id);
    node_heap::pop(open_list);

    // Add each neighbor
    for (vector_iter ii = expand_me->neighbors_out.begin();
           ii != expand_me->neighbors_out.end(); ++ ii) {
      Node* add_me = *ii;
      if (add_me->closed(problem_id))
        continue;
      const int g = expand_me->g + graph.cost(expand_me, add_me);
      if (!add_me->open) {       // If it's not open, open it
        add_me->open = true;
        add_me->relax(g, h(add_me, goal), expand_me);
        node_heap::push(open_list, add_me);
      }
      else if (g < add_me->g) {  // If it is open, relax it
        add_me->relax(g, add_me->f - add_me->g, expand_me);
        node_heap::repair(open_list, add_me->heap_index);
      }
    }
  }

  // Stats collection & cleanup
  stats.open_list_size += open_list.size();
  reconstruct_path(start, goal, graph.cost, stats);
  for (vector_iter ii = open_list.begin(); ii != open_list.end(); ++ ii)
    (*ii)->open = false;
  open_list.clear();
}

/// Fringe search (Bjornsson, Enzenberger, Holte, and Schaeffer '05).
// Like other algorithms in the A* family, fringe search expands nodes one ply
// of f values at a time.  Fringe search does this in a depth-first fashion,
// favoring the expansion of recently touched nodes, which can be accommodated
// by inserting entries into a linked list.
//
// Without aggressive compiler optimizations, Fringe Search beats A* handily.
void fringe_search(Graph & graph, Node* start, Node* goal, Stats & stats,
                   unsigned int (*h)(Node* n1, Node* n2)) {
  unsigned int (*cost)(Node*, Node*) = graph.cost;
  init_new_problem(graph, stats);
  static list<Node*> Fringe;
  typedef list<Node*>::iterator iter;
  Fringe.push_back(start);
  start->open = true;
  start->relax(0, h(start, goal), NULL);
  start->fringe_index = Fringe.begin();
  bool found = false;
  int flimit = start->f;

  do {
    int fnext = INT_MAX;
    iter ff = Fringe.begin();
    while (ff != Fringe.end()) {
      Node* expand_me = *ff;
      int f = expand_me->g + h(expand_me, gg);

      // Consider this node (is `expand_me' outside our depth?)
      if (f > flimit) {
        // keep track of smallest next depth
        if (f < fnext) {
          fnext = f;
        }
        ++ ff;
        continue; // skip this one (for now)
      }
      else if (expand_me == gg) {
        // is `expand_me' the goal and within our depth?
        found = true;
        break;
      }

      // Expand this node: relax its neighbors' g-values and
      // put them on the fringe directly AFTER `expand_me'
      ++ stats.nodes_expanded;
      for (vector<Node*>::iterator jj = expand_me->neighbors_out.begin();
           jj != expand_me->neighbors_out.end(); ++ jj) {
        Node* relax_me = *jj;
        int g = expand_me->g + cost(expand_me, relax_me);
        // jj is or has been on the fringe?
        if (relax_me->open || relax_me->closed == problem_id) {
          // is this a worse path?
          if (g >= relax_me->g)
            continue;
        }
        iter insertion_point = ff;
        ++ insertion_point;
        if (!relax_me->open) {
          // if not already open, insert jj after expand_me
          relax_me->fringe_index = Fringe.insert(insertion_point, relax_me);
          relax_me->open = true;
        }
        else if (*insertion_point != relax_me) {
          // if open, move it to right after expand_me
          Fringe.erase(relax_me->fringe_index);
          relax_me->fringe_index = Fringe.insert(insertion_point, relax_me);
        }
        relax_me->g = g;
        relax_me->whence = expand_me;
      }

      // Remove expand_me from Fringe
      expand_me->open = false;
      expand_me->closed = problem_id;
      expand_me->fringe_index = Fringe.end();
      ff = Fringe.erase(ff);
    }

    // Increase the depth and scan the fringe again
    flimit = fnext;
  } while (!found && !Fringe.empty());

  // Stats collection & cleanup
  stats.open_list_size += Fringe.size();
  reconstruct_path(start, goal, graph.cost, stats);
  for (list_iter ff = Fringe.begin(); ff != Fringe.end(); ++ ff)
    (*ff)->open = false;
  Fringe.clear();
}

/// Basic learning real-time search
void lrta_basic(Graph & graph, Node* start, Node* goal, Stats & stats,
                unsigned int (*h)(Node* n1, Node* n2)) {
  unsigned int (*cost)(Node*, Node*) = graph.cost;
  init_new_problem(graph, stats);
  while (start != goal) {
    Node* best_neighbor = 0;
    unsigned int best_f = INT_MAX;
    stats.nodes_expanded += 1;
    for (size_t ii = 0; ii < start->neighbors_out.size(); ++ ii) {
      Node* neighb = start->neighbors_out[ii];
      // set default heuristic value if it isn't set
      if (!(neighb->closed(problem_id))) {
        neighb->expand(problem_id);
        neighb->f = h(neighb, goal);
      }
      unsigned int f = cost(ss, neighb) + neighb->f;
      if (!best_neighbor || f < best_f) {
        best_neighbor = neighb;
        best_f = f;
      }
      else if (f == best_f && stats.nodes_expanded % 2)
        best_neighbor = neighb;
    }
    start->f = best_f; // learning update
    stats.path_cost += graph.cost(start, best_neighbor);
    start = best_neighbor;
  }
  stats.path_length = stats.nodes_expanded;
}
<commit_msg>optimize fringe search algorithm<commit_after>#include <list>
#include <vector>
using namespace std;
#include <climits>
#include "algorithms.h"
#include "graph.h"
#include "heuristics.h"
#include "stats.h"
#include "node_heap.h"

typedef list<Node*>::iterator list_iter;
typedef vector<Node*>::iterator vector_iter;

// These algorithms 'close' nodes by flagging them with the id of the
// current problem being solved.  This saves us unclosing every node
// after solving each path.
int problem_id = 1;

inline void init_new_problem(Graph & graph, Stats & stats) {
  ++ stats.num_problems;
  ++ problem_id;
  // check integer overflow; problem_ids are no longer unique, so reset.
  if (problem_id == 0) {
    for (size_t ii = 0; ii < graph.graph_view.size(); ++ ii)
      graph.graph_view[ii]->closed_id = 0;
    problem_id = 1;
  }
}

inline void reconstruct_path(Node* start, Node* current,
                             unsigned int (*cost)(Node*, Node*),
                             Stats & stats) {
  while (current != start) {
    stats.path_cost += cost(current->whence, current);
    ++ stats.path_length;
    current = current->whence;
  }
}

/// A-star with no optimizations, not even sorting the open list.
/// Additionally contains some validations on the result.
void astar_basic(Graph & graph, Node* start, Node* goal, Stats & stats,
                 unsigned int (*h)(Node* n1, Node* n2)) {
  init_new_problem(graph, stats);
  static vector<Node*> open_list;
  start->open = true;
  start->relax(0, h(start, goal), NULL);
  open_list.push_back(start);

  while (!open_list.empty()) {
    int fmin = INT_MAX;
    vector_iter best_on_open_list;
    // Pop the best node off the open_list via linear scan
    for (vector_iter node = open_list.begin();
         node != open_list.end(); ++ node) {
      if ((*node)->f < fmin) {
        fmin = (*node)->f;
        best_on_open_list = node;
      }
    }
    Node* expand_me = *best_on_open_list;
    if (expand_me == goal)
      break;
    expand_me->expand(problem_id);
    ++ stats.nodes_expanded;
    // remove it by overwriting it with the back() node
    *best_on_open_list = open_list.back();
    open_list.pop_back();

    // Add each neighbor
    for (vector_iter ii = expand_me->neighbors_out.begin();
         ii != expand_me->neighbors_out.end(); ++ ii) {
      Node* add_me = *ii;
      if (add_me->closed(problem_id))
        continue;
      const int g = expand_me->g + graph.cost(expand_me, add_me);
      if (!add_me->open) {       // If it's not open, open it
        add_me->open = true;
        add_me->relax(g, h(add_me, goal), expand_me);
        open_list.push_back(add_me);
      }
      else if (add_me->g > g) {  // If it is open, relax it
        add_me->relax(g, h(add_me, goal), expand_me);
      }
    }
  }

  // Stats collection & cleanup
  stats.open_list_size += open_list.size();
  reconstruct_path(start, goal, graph.cost, stats);
  for (vector_iter ii = open_list.begin(); ii != open_list.end(); ++ ii)
    (*ii)->open = false;
  open_list.clear();
}

/// A* with a binary heap.
void astar_heap(Graph & graph, Node* start, Node* goal, Stats & stats,
                unsigned int (*h)(Node* n1, Node* n2)) {
  init_new_problem(graph, stats);
  static vector<Node*> open_list;
  start->open = true;
  start->relax(0, h(start, goal), NULL);
  node_heap::push(open_list, start);

  while (!open_list.empty()) {
    // Pop the best node off the open_list (+ goal check)
    Node* expand_me = open_list.front();
    if (expand_me == goal)
      break;

    ++ stats.nodes_expanded;
    expand_me->expand(problem_id);
    node_heap::pop(open_list);

    // Add each neighbor
    for (vector_iter ii = expand_me->neighbors_out.begin();
           ii != expand_me->neighbors_out.end(); ++ ii) {
      Node* add_me = *ii;
      if (add_me->closed(problem_id))
        continue;
      const int g = expand_me->g + graph.cost(expand_me, add_me);
      if (!add_me->open) {       // If it's not open, open it
        add_me->open = true;
        add_me->relax(g, h(add_me, goal), expand_me);
        node_heap::push(open_list, add_me);
      }
      else if (g < add_me->g) {  // If it is open, relax it
        add_me->relax(g, add_me->f - add_me->g, expand_me);
        node_heap::repair(open_list, add_me->heap_index);
      }
    }
  }

  // Stats collection & cleanup
  stats.open_list_size += open_list.size();
  reconstruct_path(start, goal, graph.cost, stats);
  for (vector_iter ii = open_list.begin(); ii != open_list.end(); ++ ii)
    (*ii)->open = false;
  open_list.clear();
}

/// Fringe search (Bjornsson, Enzenberger, Holte, and Schaeffer '05).
// Like other algorithms in the A* family, fringe search expands nodes one ply
// of f values at a time.  Fringe search does this in a depth-first fashion,
// favoring the expansion of recently touched nodes, which can be accommodated
// by inserting entries into a linked list.
//
// Without aggressive compiler optimizations, Fringe Search beats A* handily.
void fringe_search(Graph & graph, Node* start, Node* goal, Stats & stats,
                   unsigned int (*h)(Node* n1, Node* n2)) {
  init_new_problem(graph, stats);
  static list<Node*> Fringe;
  Fringe.push_back(start);
  start->open = true;
  start->relax(0, h(start, goal), NULL);
  start->fringe_index = Fringe.begin();
  bool found = false;
  int flimit = start->f;

  while (!found && !Fringe.empty()) {
    int fnext = INT_MAX;
    for (list_iter ff = Fringe.begin(); ff != Fringe.end();) {
      Node* expand_me = *ff;
      // is this node outside the current depth?
      if (expand_me->f > flimit) {
        if (expand_me->f < fnext)
          fnext = expand_me->f; // track smallest next depth
        ++ ff;
        continue; // skip this one (for now)
      }
      if (expand_me == goal) {
        found = true;
        break;
      }

      ++ stats.nodes_expanded;
      expand_me->expand(problem_id);

      // Relax the neighbors and put them on the fringe AFTER `expand_me'
      for (vector_iter ii = expand_me->neighbors_out.begin();
           ii != expand_me->neighbors_out.end(); ++ ii) {
        Node* add_me = *ii;
        if (add_me->closed(problem_id))
          continue;
        const int g = expand_me->g + graph.cost(expand_me, add_me);

        list_iter insertion_point = ff;
        ++ insertion_point;

        if (!add_me->open) {
          // if not already open, insert add_me after expand_me
          add_me->open = true;
          add_me->relax(g, h(add_me, goal), expand_me);
          add_me->fringe_index = Fringe.insert(insertion_point, add_me);
        }
        else if (g < add_me->g) {
          add_me->relax(g, add_me->f - add_me->g, expand_me);
          if (*insertion_point != add_me) {
            Fringe.erase(add_me->fringe_index);
            add_me->fringe_index = Fringe.insert(insertion_point, add_me);
          }
        }
      }
      ff = Fringe.erase(ff);
    }
    // Increase the depth and scan the fringe again
    flimit = fnext;
  }

  // Stats collection & cleanup
  stats.open_list_size += Fringe.size();
  reconstruct_path(start, goal, graph.cost, stats);
  for (list_iter ff = Fringe.begin(); ff != Fringe.end(); ++ ff)
    (*ff)->open = false;
  Fringe.clear();
}

/// Basic learning real-time search
void lrta_basic(Graph & graph, Node* start, Node* goal, Stats & stats,
                unsigned int (*h)(Node* n1, Node* n2)) {
  init_new_problem(graph, stats);
  while (start != goal) {
    Node* best_neighbor = 0;
    unsigned int best_f = INT_MAX;
    stats.nodes_expanded += 1;
    for (size_t ii = 0; ii < start->neighbors_out.size(); ++ ii) {
      Node* neighb = start->neighbors_out[ii];
      // set default heuristic value if it isn't set
      if (!(neighb->closed(problem_id))) {
        neighb->expand(problem_id);
        neighb->f = h(neighb, goal);
      }
      unsigned int f = graph.cost(start, neighb) + neighb->f;
      if (!best_neighbor || f < best_f) {
        best_neighbor = neighb;
        best_f = f;
      }
      else if (f == best_f && stats.nodes_expanded % 2)
        best_neighbor = neighb;
    }
    start->f = best_f; // learning update
    stats.path_cost += graph.cost(start, best_neighbor);
    start = best_neighbor;
  }
  stats.path_length = stats.nodes_expanded;
}
<|endoftext|>


<commit_before>#include "copy_root_tree.hh"
#include "HdfTuple.hh"

#include "TFile.h"
#include "TTree.h"
#include "TLeaf.h"

#include <iostream>

class DataBuffers: public std::vector<data_buffer_t*> {
public:
  ~DataBuffers() {
    for (auto buf : *this) {
      delete buf;
    }
  }
};

// functions to convert union types back to whatever they are
template <typename T>
T& get_ref(data_buffer_t* buf);
template<> int& get_ref<int>(data_buffer_t* buf) {
  return buf->_int;
}
template<> float& get_ref<float>(data_buffer_t* buf) {
  return buf->_float;
}
template<> double& get_ref<double>(data_buffer_t* buf) {
  return buf->_double;
}
template<> bool& get_ref<bool>(data_buffer_t* buf) {
  return buf->_bool;
}

// copy function
template <typename T>
void set_branch(VariableFillers& vars, TTree& tt, DataBuffers& buffer,
                const std::string& name) {
  buffer.push_back(new data_buffer_t);
  T& buf = get_ref<T>(buffer.back());
  tt.SetBranchAddress(name.c_str(), &buf);
  vars.add<T>(name, [&buf](){return buf;});
}

// main function to do all the things
void copy_root_tree(TTree& tt, H5::CommonFG& fg) {
  const std::string tree_name = tt.GetName();

  DataBuffers buffer;
  std::set<std::string> skipped;

  TIter next(tt.GetListOfLeaves());
  VariableFillers vars;
  TLeaf* leaf;
  while ((leaf = dynamic_cast<TLeaf*>(next()))) {
    std::string leaf_name = leaf->GetName();
    std::string leaf_type = leaf->GetTypeName();
    if (leaf_type == "Int_t") {
      set_branch<int>(vars, tt, buffer, leaf_name);
    } else if (leaf_type == "Float_t") {
      set_branch<float>(vars, tt, buffer, leaf_name);
    } else if (leaf_type == "Double_t") {
      set_branch<double>(vars, tt, buffer, leaf_name);
    } else if (leaf_type == "Bool_t") {
      set_branch<bool>(vars, tt, buffer, leaf_name);
    } else {
      skipped.insert(leaf_type);
    }
  }

  Writer writer(fg, tree_name, vars);
  size_t n_entries = tt.GetEntries();
  for (size_t iii = 0; iii < n_entries; iii++) {
    tt.GetEntry(iii);
    writer.fill();
  }
  writer.flush();
  writer.close();

  for (const auto& name: skipped) {
    std::cerr << "skipped " << name << std::endl;
  }
}
<commit_msg>Prevent adding identical leaf names<commit_after>#include "copy_root_tree.hh"
#include "HdfTuple.hh"

#include "TFile.h"
#include "TTree.h"
#include "TLeaf.h"

#include <iostream>

class DataBuffers: public std::vector<data_buffer_t*> {
public:
  ~DataBuffers() {
    for (auto buf : *this) {
      delete buf;
    }
  }
};

// functions to convert union types back to whatever they are
template <typename T>
T& get_ref(data_buffer_t* buf);
template<> int& get_ref<int>(data_buffer_t* buf) {
  return buf->_int;
}
template<> float& get_ref<float>(data_buffer_t* buf) {
  return buf->_float;
}
template<> double& get_ref<double>(data_buffer_t* buf) {
  return buf->_double;
}
template<> bool& get_ref<bool>(data_buffer_t* buf) {
  return buf->_bool;
}

// copy function
template <typename T>
void set_branch(VariableFillers& vars, TTree& tt, DataBuffers& buffer,
                const std::string& name) {
  buffer.push_back(new data_buffer_t);
  T& buf = get_ref<T>(buffer.back());
  tt.SetBranchAddress(name.c_str(), &buf);
  vars.add<T>(name, [&buf](){return buf;});
}

// main function to do all the things
void copy_root_tree(TTree& tt, H5::CommonFG& fg) {
  const std::string tree_name = tt.GetName();

  DataBuffers buffer;
  std::set<std::string> skipped;

  TIter next(tt.GetListOfLeaves());
  TLeaf* leaf;
  std::set<std::string> leaf_names;
  while ((leaf = dynamic_cast<TLeaf*>(next()))) {
    leaf_names.insert(leaf->GetName());
  }
  VariableFillers vars;
  for (const auto& leaf_name: leaf_names) {
    leaf = tt.GetLeaf(leaf_name.c_str());
    std::string leaf_type = leaf->GetTypeName();
    if (leaf_type == "Int_t") {
      set_branch<int>(vars, tt, buffer, leaf_name);
    } else if (leaf_type == "Float_t") {
      set_branch<float>(vars, tt, buffer, leaf_name);
    } else if (leaf_type == "Double_t") {
      set_branch<double>(vars, tt, buffer, leaf_name);
    } else if (leaf_type == "Bool_t") {
      set_branch<bool>(vars, tt, buffer, leaf_name);
    } else {
      skipped.insert(leaf_type);
    }
  }

  Writer writer(fg, tree_name, vars);
  size_t n_entries = tt.GetEntries();
  for (size_t iii = 0; iii < n_entries; iii++) {
    tt.GetEntry(iii);
    writer.fill();
  }
  writer.flush();
  writer.close();

  for (const auto& name: skipped) {
    std::cerr << "skipped " << name << std::endl;
  }
}
<|endoftext|>


<commit_before>//===-- ExpressionSourceCode.cpp --------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Expression/ExpressionSourceCode.h"

#include <algorithm>

#include "llvm/ADT/StringRef.h"
#include "clang/Basic/CharInfo.h"
#include "swift/AST/PlatformKind.h"
#include "swift/Basic/LangOptions.h"

#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/StreamString.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/FileSystem.h"

using namespace lldb_private;

bool ExpressionSourceCode::SaveExpressionTextToTempFile(
    llvm::StringRef text, const EvaluateExpressionOptions &options,
    std::string &expr_source_path) {
  bool success = false;

  const uint32_t expr_number = options.GetExpressionNumber();

  const bool playground = options.GetPlaygroundTransformEnabled();
  const bool repl = options.GetREPLEnabled();

  llvm::StringRef file_prefix;
  if (playground)
    file_prefix = "playground";
  else if (repl)
    file_prefix = "repl";
  else
    file_prefix = "expr";

  llvm::Twine prefix = llvm::Twine(file_prefix).concat(llvm::Twine(expr_number));

  llvm::StringRef suffix;
  switch (options.GetLanguage()) {
  default:
    suffix = ".cpp";
    break;

  case lldb::eLanguageTypeSwift:
    suffix = ".swift";
    break;
  }

  int temp_fd;
  llvm::SmallString<128> buffer;
  std::error_code err =
      llvm::sys::fs::createTemporaryFile(prefix, suffix, temp_fd, buffer);
  if (!err) {
    lldb_private::File file(temp_fd, true);
    const size_t text_len = text.size();
    size_t bytes_written = text_len;
    if (file.Write(text.data(), bytes_written).Success()) {
      if (bytes_written == text_len) {
        // Make sure we have a newline in the file at the end
        bytes_written = 1;
        file.Write("\n", bytes_written);
        if (bytes_written == 1)
          success = true;
      }
    }
    if (!success)
      llvm::sys::fs::remove(expr_source_path);
  }
  if (!success)
    expr_source_path.clear();
  else
    expr_source_path = buffer.str().str();

  return success;
}

/// Format the OS name the way that Swift availability attributes do.
static llvm::StringRef getAvailabilityName(const llvm::Triple &triple) {
    swift::LangOptions lang_options;
  lang_options.setTarget(triple);
  return swift::platformString(swift::targetPlatform(lang_options));
}

bool ExpressionSourceCode::GetText(
    std::string &text, lldb::LanguageType wrapping_language,
    uint32_t language_flags, const EvaluateExpressionOptions &options,
    ExecutionContext &exe_ctx, uint32_t &first_body_line) const {
  first_body_line = 0;

  const char *target_specific_defines = "typedef signed char BOOL;\n";
  std::string module_macros;

  Target *target = exe_ctx.GetTargetPtr();
  if (ClangModulesDeclVendor::LanguageSupportsClangModules(wrapping_language)) {
    if (target) {
      if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) {
        target_specific_defines = "typedef bool BOOL;\n";
      }
      if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) {
        if (lldb::PlatformSP platform_sp = target->GetPlatform()) {
          static ConstString g_platform_ios_simulator("ios-simulator");
          if (platform_sp->GetPluginName() == g_platform_ios_simulator) {
            target_specific_defines = "typedef bool BOOL;\n";
          }
        }
      }

      ClangPersistentVariables *persistent_vars =
          llvm::dyn_cast_or_null<ClangPersistentVariables>(
              target->GetPersistentExpressionStateForLanguage(
                  lldb::eLanguageTypeC));
      ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor();

      if (persistent_vars && decl_vendor) {
        const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
            persistent_vars->GetHandLoadedClangModules();

        ClangModulesDeclVendor::ModuleVector modules_for_macros;

        for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) {
          modules_for_macros.push_back(module);
        }

        if (target->GetEnableAutoImportClangModules()) {
          if (StackFrame *frame = exe_ctx.GetFramePtr()) {
            if (Block *block = frame->GetFrameBlock()) {
              SymbolContext sc;

              block->CalculateSymbolContext(&sc);

              if (sc.comp_unit) {
                StreamString error_stream;

                decl_vendor->AddModulesForCompileUnit(
                    *sc.comp_unit, modules_for_macros, error_stream);
              }
            }
          }
        }

        decl_vendor->ForEachMacro(
            modules_for_macros,
            [&module_macros](const std::string &expansion) -> bool {
              module_macros.append(expansion);
              module_macros.append("\n");
              return false;
            });
      }
    }
  }

  StreamString debug_macros_stream;
  StreamString lldb_local_var_decls;
  if (StackFrame *frame = exe_ctx.GetFramePtr()) {
    const SymbolContext &sc = frame->GetSymbolContext(
        lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);

    if (sc.comp_unit && sc.line_entry.IsValid()) {
      DebugMacros *dm = sc.comp_unit->GetDebugMacros();
      if (dm) {
        AddMacroState state(sc.line_entry.file, sc.line_entry.line);
        AddMacros(dm, sc.comp_unit, state, debug_macros_stream);
      }
    }

    ConstString object_name;
    if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) {
      if (target->GetInjectLocalVariables(&exe_ctx)) {
        lldb::VariableListSP var_list_sp =
            frame->GetInScopeVariableList(false, true);
        AddLocalVariableDecls(var_list_sp, lldb_local_var_decls, m_body);
      }
    }
  }

  if (m_wrap) {
    const char *body = m_body.c_str();
    const char *pound_file = options.GetPoundLineFilePath();
    const uint32_t pound_line = options.GetPoundLineLine();
    StreamString pound_body;
    if (pound_file && pound_line) {
      if (wrapping_language == lldb::eLanguageTypeSwift) {
        pound_body.Printf("#sourceLocation(file: \"%s\", line: %u)\n%s",
                          pound_file, pound_line, body);
      } else {
        pound_body.Printf("#line %u \"%s\"\n%s", pound_line, pound_file, body);
      }
      body = pound_body.GetString().data();
    }

    switch (wrapping_language) {
    default:
      return false;
    case lldb::eLanguageTypeC:
    case lldb::eLanguageTypeC_plus_plus:
    case lldb::eLanguageTypeObjC:
    case lldb::eLanguageTypeSwift:
      break;
    }

    StreamString wrap_stream;

    if (ClangModulesDeclVendor::LanguageSupportsClangModules(
            wrapping_language)) {
      wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", module_macros.c_str(),
                         debug_macros_stream.GetData(), g_expression_prefix,
                         target_specific_defines, m_prefix.c_str());
    }

    // First construct a tagged form of the user expression so we can find it
    // later:
    std::string tagged_body;
    switch (wrapping_language) {
    default:
      tagged_body = m_body;
      break;
    case lldb::eLanguageTypeC:
    case lldb::eLanguageTypeC_plus_plus:
    case lldb::eLanguageTypeObjC:
      tagged_body.append(c_start_marker);
      tagged_body.append(m_body);
      tagged_body.append(c_end_marker);
      break;
    }
    switch (wrapping_language) {
    default:
      break;
    case lldb::eLanguageTypeC:
      wrap_stream.Printf("void                           \n"
                         "%s(void *$__lldb_arg)          \n"
                         "{                              \n"
                         "    %s;                        \n"
                         "%s"
                         "}                              \n",
                         m_name.c_str(), lldb_local_var_decls.GetData(),
                         tagged_body.c_str());
      break;
    case lldb::eLanguageTypeC_plus_plus:
      wrap_stream.Printf("void                                   \n"
                         "$__lldb_class::%s(void *$__lldb_arg)   \n"
                         "{                                      \n"
                         "    %s;                                \n"
                         "%s"
                         "}                                      \n",
                         m_name.c_str(), lldb_local_var_decls.GetData(),
                         tagged_body.c_str());
      break;
    case lldb::eLanguageTypeObjC:
      if (language_flags & ClangUserExpression::eLanguageFlagInStaticMethod) {
        wrap_stream.Printf(
            "@interface $__lldb_objc_class ($__lldb_category)        \n"
            "+(void)%s:(void *)$__lldb_arg;                          \n"
            "@end                                                    \n"
            "@implementation $__lldb_objc_class ($__lldb_category)   \n"
            "+(void)%s:(void *)$__lldb_arg                           \n"
            "{                                                       \n"
            "%s"
            "}                                                       \n"
            "@end                                                    \n",
            m_name.c_str(), m_name.c_str(), tagged_body.c_str());
      } else {
        wrap_stream.Printf(
            "@interface $__lldb_objc_class ($__lldb_category)       \n"
            "-(void)%s:(void *)$__lldb_arg;                         \n"
            "@end                                                   \n"
            "@implementation $__lldb_objc_class ($__lldb_category)  \n"
            "-(void)%s:(void *)$__lldb_arg                          \n"
            "{                                                      \n"
            "%s"
            "}                                                      \n"
            "@end                                                   \n",
            m_name.c_str(), m_name.c_str(), tagged_body.c_str());
      }
      break;
    case lldb::eLanguageTypeSwift: {
      llvm::SmallString<16> buffer;
      llvm::raw_svector_ostream os_vers(buffer);

      auto arch_spec = target->GetArchitecture();
      auto triple = arch_spec.GetTriple();
      if (triple.isOSDarwin()) {
        if (auto process_sp = exe_ctx.GetProcessSP()) {
          os_vers << getAvailabilityName(triple) << " ";
          auto platform = target->GetPlatform();
          bool is_simulator =
              platform->GetPluginName().GetStringRef().endswith("-simulator");
          if (is_simulator) {
            // The simulators look like the host OS to Process, but Platform
            // can the version out of an environment variable.
            os_vers << platform->GetOSVersion(process_sp.get()).getAsString();
          } else {
	    llvm::VersionTuple version =
	      process_sp->GetHostOSVersion();
	    os_vers << version.getAsString();
          }
        }
      }
      SwiftPersistentExpressionState *persistent_state =
        llvm::cast<SwiftPersistentExpressionState>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeSwift));
      std::vector<swift::ValueDecl *> persistent_results;
      // Check if we have already declared the playground stub debug functions
      persistent_state->GetSwiftPersistentDecls(ConstString("__builtin_log_with_id"), {},
                                                persistent_results);

      size_t num_persistent_results = persistent_results.size();
      bool need_to_declare_log_functions = num_persistent_results == 0;
      EvaluateExpressionOptions localOptions(options);

      localOptions.SetPreparePlaygroundStubFunctions(need_to_declare_log_functions);

      SwiftASTManipulator::WrapExpression(wrap_stream, m_body.c_str(),
                                          language_flags, localOptions,
                                          os_vers.str(), first_body_line);
    }
    }

    text = wrap_stream.GetString();
  } else {
    text.append(m_body);
  }

  return true;
}

bool ExpressionSourceCode::GetOriginalBodyBounds(
    std::string transformed_text, lldb::LanguageType wrapping_language,
    size_t &start_loc, size_t &end_loc) {
  const char *start_marker;
  const char *end_marker;

  switch (wrapping_language) {
  default:
    return false;
  case lldb::eLanguageTypeSwift:
    start_marker = SwiftASTManipulator::GetUserCodeStartMarker();
    end_marker = SwiftASTManipulator::GetUserCodeEndMarker();
    break;
  case lldb::eLanguageTypeC:
  case lldb::eLanguageTypeC_plus_plus:
  case lldb::eLanguageTypeObjC:
    start_marker = c_start_marker;
    end_marker = c_end_marker;
    break;
  }

  start_loc = transformed_text.find(start_marker);
  if (start_loc == std::string::npos)
    return false;
  start_loc += strlen(start_marker);
  end_loc = transformed_text.find(end_marker);
  return end_loc != std::string::npos;
}
<commit_msg>Remove some code from the base class that has been moved into subclasses.<commit_after>//===-- ExpressionSourceCode.cpp --------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Expression/ExpressionSourceCode.h"

#include <algorithm>

#include "llvm/ADT/StringRef.h"
#include "clang/Basic/CharInfo.h"
#include "swift/AST/PlatformKind.h"
#include "swift/Basic/LangOptions.h"

#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/StreamString.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/FileSystem.h"

using namespace lldb_private;

bool ExpressionSourceCode::SaveExpressionTextToTempFile(
    llvm::StringRef text, const EvaluateExpressionOptions &options,
    std::string &expr_source_path) {
  bool success = false;

  const uint32_t expr_number = options.GetExpressionNumber();

  const bool playground = options.GetPlaygroundTransformEnabled();
  const bool repl = options.GetREPLEnabled();

  llvm::StringRef file_prefix;
  if (playground)
    file_prefix = "playground";
  else if (repl)
    file_prefix = "repl";
  else
    file_prefix = "expr";

  llvm::Twine prefix = llvm::Twine(file_prefix).concat(llvm::Twine(expr_number));

  llvm::StringRef suffix;
  switch (options.GetLanguage()) {
  default:
    suffix = ".cpp";
    break;

  case lldb::eLanguageTypeSwift:
    suffix = ".swift";
    break;
  }

  int temp_fd;
  llvm::SmallString<128> buffer;
  std::error_code err =
      llvm::sys::fs::createTemporaryFile(prefix, suffix, temp_fd, buffer);
  if (!err) {
    lldb_private::File file(temp_fd, true);
    const size_t text_len = text.size();
    size_t bytes_written = text_len;
    if (file.Write(text.data(), bytes_written).Success()) {
      if (bytes_written == text_len) {
        // Make sure we have a newline in the file at the end
        bytes_written = 1;
        file.Write("\n", bytes_written);
        if (bytes_written == 1)
          success = true;
      }
    }
    if (!success)
      llvm::sys::fs::remove(expr_source_path);
  }
  if (!success)
    expr_source_path.clear();
  else
    expr_source_path = buffer.str().str();

  return success;
}
<|endoftext|>