<commit_before>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
 *                                                                                *
 *  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   *
 *************************************************************************************/

#include "daemon.h"
#include "serializer.h"
#include "generator.h"
#include "device.h"
#include "kscreenadaptor.h"

#include <QtCore/QTimer>

#include <kdebug.h>
#include <kdemacros.h>
#include <kaction.h>
#include <KLocalizedString>
#include <KActionCollection>
#include <KPluginFactory>

#include <kscreen/config.h>
#include <kscreen/configmonitor.h>

K_PLUGIN_FACTORY(KScreenDaemonFactory, registerPlugin<KScreenDaemon>();)
K_EXPORT_PLUGIN(KScreenDaemonFactory("kscreen", "kscreen"))

KScreenDaemon::KScreenDaemon(QObject* parent, const QList< QVariant >& )
 : KDEDModule(parent)
 , m_monitoredConfig(0)
 , m_iteration(0)
 , m_monitoring(false)
 , m_timer(new QTimer())
 , m_saveTimer(new QTimer())

{
    if (!KScreen::Config::loadBackend()) {
        return;
    }

    KActionCollection *coll = new KActionCollection(this);
    KAction* action = coll->addAction("display");
    action->setText(i18n("Switch Display" ));
    action->setGlobalShortcut(KShortcut(Qt::Key_Display));

    new KScreenAdaptor(this);
    QDBusConnection::sessionBus().registerService(QLatin1String("org.kde.KScreen"));

    connect(Device::self(), SIGNAL(lidIsClosedChanged(bool,bool)), SLOT(lidClosedChanged(bool)));

    m_timer->setInterval(300);
    m_timer->setSingleShot(true);
    connect(m_timer, SIGNAL(timeout()), SLOT(applyGenericConfig()));

    m_saveTimer->setInterval(300);
    m_saveTimer->setSingleShot(true);
    connect(m_saveTimer, SIGNAL(timeout()), SLOT(saveCurrentConfig()));

    connect(action, SIGNAL(triggered(bool)), SLOT(displayButton()));
    connect(Generator::self(), SIGNAL(ready()), SLOT(init()));
    monitorConnectedChange();
}

KScreenDaemon::~KScreenDaemon()
{
    delete m_saveTimer;
    delete m_timer;

    Generator::destroy();
    Device::destroy();
}

void KScreenDaemon::init()
{
    disconnect(Generator::self(), SIGNAL(ready()), this, SLOT(init()));
    applyConfig();
}

void KScreenDaemon::applyConfig()
{
    kDebug() << "Applying config";
    if (Serializer::configExists()) {
        applyKnownConfig();
        return;
    }

    applyIdealConfig();
}

void KScreenDaemon::applyKnownConfig()
{
    kDebug() << "Applying known config";
    setMonitorForChanges(false);
    KScreen::Config* config = Serializer::config(Serializer::currentConfigId());
    if (!KScreen::Config::canBeApplied(config)) {
        return applyIdealConfig();
    }

    KScreen::Config::setConfig(config);
    QMetaObject::invokeMethod(this, "scheduleMonitorChange", Qt::QueuedConnection);
}

void KScreenDaemon::applyIdealConfig()
{
    kDebug() << "Applying ideal config";
    setMonitorForChanges(true);
    KScreen::Config::setConfig(Generator::self()->idealConfig());
}

void KScreenDaemon::configChanged()
{
    kDebug() << "Change detected";
    // Reset timer, delay the writeback
    m_saveTimer->start();
}

void KScreenDaemon::saveCurrentConfig()
{
    kDebug() << "Saving current config";
    Serializer::saveConfig(KScreen::Config::current(), m_profileId);
}

void KScreenDaemon::displayButton()
{
    kDebug() << "displayBtn triggered";
    if (m_timer->isActive()) {
        kDebug() << "Too fast cowboy";
        return;
    }

    m_timer->start();
}

void KScreenDaemon::resetDisplaySwitch()
{
    kDebug();
    m_iteration = 0;
}

void KScreenDaemon::applyGenericConfig()
{
    if (m_iteration == 5) {
        m_iteration = 0;
    }

    setMonitorForChanges(true);
    m_iteration++;
    kDebug() << "displayButton: " << m_iteration;
    KDebug::Block genericConfig("Applying display switch");
    KScreen::Config::setConfig(Generator::self()->displaySwitch(m_iteration));
}

void KScreenDaemon::lidClosedChanged(bool lidIsClosed)
{
//     KDebug::Block genericConfig(" Lid closed");
//     kDebug() << "Lid is closed:" << lidIsClosed;
//     //If the laptop is closed, use ideal config WITHOUT saving it
//     if (lidIsClosed) {
//         setMonitorForChanges(false);
//         KScreen::Config::setConfig(Generator::self()->idealConfig());
//         return;
//     }
//
//     //If the lid is open, restore config (or generate a new one if needed
//     applyConfig();
}

void KScreenDaemon::outputConnectedChanged()
{
    KScreen::Output *output = qobject_cast<KScreen::Output*>(sender());

    if (output->isConnected()) {
        Q_EMIT outputConnected(output->name());

        if (!Serializer::configExists()) {
            Q_EMIT unknownOutputConnected(output->name());
        }
    }

    Q_EMIT profilesChanged();
}

void KScreenDaemon::monitorConnectedChange()
{
    if (!m_monitoredConfig) {
        m_monitoredConfig = KScreen::Config::current();
        if (!m_monitoredConfig) {
            return;
        }

        KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);
    }

    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        connect(output, SIGNAL(isConnectedChanged()), SLOT(applyConfig()));
        connect(output, SIGNAL(isConnectedChanged()), SLOT(resetDisplaySwitch()));
        connect(output, SIGNAL(isConnectedChanged()), SLOT(outputConnectedChanged()));
    }
}

void KScreenDaemon::setMonitorForChanges(bool enabled)
{
    if (m_monitoring == enabled) {
        return;
    }
    kDebug() << "Monitor for changes: " << enabled;
    if (!m_monitoredConfig) {
        m_monitoredConfig = KScreen::Config::current();
        if (!m_monitoredConfig) {
            return;
        }
        KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);
    }

    m_monitoring = enabled;

    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        if (m_monitoring) {
            enableMonitor(output);
        } else {
            disableMonitor(output);
        }
    }
}

void KScreenDaemon::scheduleMonitorChange()
{
    QMetaObject::invokeMethod(this, "setMonitorForChanges", Qt::QueuedConnection, Q_ARG(bool, true));
}

void KScreenDaemon::enableMonitor(KScreen::Output* output)
{
    connect(output, SIGNAL(currentModeIdChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(isEnabledChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(isPrimaryChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(outputChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(clonesChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(posChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(rotationChanged()), SLOT(configChanged()));
}

void KScreenDaemon::disableMonitor(KScreen::Output* output)
{
    disconnect(output, SIGNAL(currentModeIdChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(isEnabledChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(isPrimaryChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(outputChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(clonesChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(posChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(rotationChanged()), this, SLOT(configChanged()));
}

QMap<QString,QString> KScreenDaemon::listCurrentProfiles() const
{
    return Serializer::listProfiles(Serializer::currentConfigId());
}

QString KScreenDaemon::activeProfile() const
{
    return m_profileId;
}

void KScreenDaemon::activateProfile(const QString &id)
{
    KScreen::Config *config = Serializer::config(Serializer::currentConfigId(), id);
    if (config->isValid()) {
        config->setConfig(config);
    }

    m_profileId = id;
}

QString KScreenDaemon::createProfileFromCurrentConfig(const QString &name, bool preferred)
{
    return Serializer::createProfile(KScreen::Config::current(), name);
}

void KScreenDaemon::deleteProfile(const QString &id)
{
    Serializer::removeProfile(Serializer::currentConfigId(), id);

    Q_EMIT profilesChanged();
}

QDBusVariant KScreenDaemon::getProfile(const QString &id)
{
    return QDBusVariant(Serializer::loadProfile(Serializer::currentConfigId(), id));
}
<commit_msg>Add a few debug messages<commit_after>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
 *                                                                                *
 *  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   *
 *************************************************************************************/

#include "daemon.h"
#include "serializer.h"
#include "generator.h"
#include "device.h"
#include "kscreenadaptor.h"

#include <QtCore/QTimer>

#include <kdebug.h>
#include <kdemacros.h>
#include <kaction.h>
#include <KLocalizedString>
#include <KActionCollection>
#include <KPluginFactory>

#include <kscreen/config.h>
#include <kscreen/configmonitor.h>

K_PLUGIN_FACTORY(KScreenDaemonFactory, registerPlugin<KScreenDaemon>();)
K_EXPORT_PLUGIN(KScreenDaemonFactory("kscreen", "kscreen"))

KScreenDaemon::KScreenDaemon(QObject* parent, const QList< QVariant >& )
 : KDEDModule(parent)
 , m_monitoredConfig(0)
 , m_iteration(0)
 , m_monitoring(false)
 , m_timer(new QTimer())
 , m_saveTimer(new QTimer())

{
    if (!KScreen::Config::loadBackend()) {
        return;
    }

    KActionCollection *coll = new KActionCollection(this);
    KAction* action = coll->addAction("display");
    action->setText(i18n("Switch Display" ));
    action->setGlobalShortcut(KShortcut(Qt::Key_Display));

    new KScreenAdaptor(this);
    QDBusConnection::sessionBus().registerService(QLatin1String("org.kde.KScreen"));

    connect(Device::self(), SIGNAL(lidIsClosedChanged(bool,bool)), SLOT(lidClosedChanged(bool)));

    m_timer->setInterval(300);
    m_timer->setSingleShot(true);
    connect(m_timer, SIGNAL(timeout()), SLOT(applyGenericConfig()));

    m_saveTimer->setInterval(300);
    m_saveTimer->setSingleShot(true);
    connect(m_saveTimer, SIGNAL(timeout()), SLOT(saveCurrentConfig()));

    connect(action, SIGNAL(triggered(bool)), SLOT(displayButton()));
    connect(Generator::self(), SIGNAL(ready()), SLOT(init()));
    monitorConnectedChange();
}

KScreenDaemon::~KScreenDaemon()
{
    delete m_saveTimer;
    delete m_timer;

    Generator::destroy();
    Device::destroy();
}

void KScreenDaemon::init()
{
    disconnect(Generator::self(), SIGNAL(ready()), this, SLOT(init()));
    applyConfig();
}

void KScreenDaemon::applyConfig()
{
    kDebug() << "Applying config";
    if (Serializer::configExists()) {
        applyKnownConfig();
        return;
    }

    applyIdealConfig();
}

void KScreenDaemon::applyKnownConfig()
{
    kDebug() << "Applying known config";
    setMonitorForChanges(false);
    KScreen::Config* config = Serializer::config(Serializer::currentConfigId());
    if (!KScreen::Config::canBeApplied(config)) {
        return applyIdealConfig();
    }

    KScreen::Config::setConfig(config);
    QMetaObject::invokeMethod(this, "scheduleMonitorChange", Qt::QueuedConnection);
}

void KScreenDaemon::applyIdealConfig()
{
    kDebug() << "Applying ideal config";
    setMonitorForChanges(true);
    KScreen::Config::setConfig(Generator::self()->idealConfig());
}

void KScreenDaemon::configChanged()
{
    kDebug() << "Change detected";
    // Reset timer, delay the writeback
    m_saveTimer->start();
}

void KScreenDaemon::saveCurrentConfig()
{
    kDebug() << "Saving current config";
    Serializer::saveConfig(KScreen::Config::current(), m_profileId);
}

void KScreenDaemon::displayButton()
{
    kDebug() << "displayBtn triggered";
    if (m_timer->isActive()) {
        kDebug() << "Too fast cowboy";
        return;
    }

    m_timer->start();
}

void KScreenDaemon::resetDisplaySwitch()
{
    kDebug();
    m_iteration = 0;
}

void KScreenDaemon::applyGenericConfig()
{
    if (m_iteration == 5) {
        m_iteration = 0;
    }

    setMonitorForChanges(true);
    m_iteration++;
    kDebug() << "displayButton: " << m_iteration;
    KDebug::Block genericConfig("Applying display switch");
    KScreen::Config::setConfig(Generator::self()->displaySwitch(m_iteration));
}

void KScreenDaemon::lidClosedChanged(bool lidIsClosed)
{
//     KDebug::Block genericConfig(" Lid closed");
//     kDebug() << "Lid is closed:" << lidIsClosed;
//     //If the laptop is closed, use ideal config WITHOUT saving it
//     if (lidIsClosed) {
//         setMonitorForChanges(false);
//         KScreen::Config::setConfig(Generator::self()->idealConfig());
//         return;
//     }
//
//     //If the lid is open, restore config (or generate a new one if needed
//     applyConfig();
}

void KScreenDaemon::outputConnectedChanged()
{
    KScreen::Output *output = qobject_cast<KScreen::Output*>(sender());

    if (output->isConnected()) {
        Q_EMIT outputConnected(output->name());

        if (!Serializer::configExists()) {
            Q_EMIT unknownOutputConnected(output->name());
        }
    }

    Q_EMIT profilesChanged();
}

void KScreenDaemon::monitorConnectedChange()
{
    if (!m_monitoredConfig) {
        m_monitoredConfig = KScreen::Config::current();
        if (!m_monitoredConfig) {
            return;
        }

        KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);
    }

    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        connect(output, SIGNAL(isConnectedChanged()), SLOT(applyConfig()));
        connect(output, SIGNAL(isConnectedChanged()), SLOT(resetDisplaySwitch()));
        connect(output, SIGNAL(isConnectedChanged()), SLOT(outputConnectedChanged()));
    }
}

void KScreenDaemon::setMonitorForChanges(bool enabled)
{
    if (m_monitoring == enabled) {
        return;
    }
    kDebug() << "Monitor for changes: " << enabled;
    if (!m_monitoredConfig) {
        m_monitoredConfig = KScreen::Config::current();
        if (!m_monitoredConfig) {
            return;
        }
        KScreen::ConfigMonitor::instance()->addConfig(m_monitoredConfig);
    }

    m_monitoring = enabled;

    KScreen::OutputList outputs = m_monitoredConfig->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        if (m_monitoring) {
            enableMonitor(output);
        } else {
            disableMonitor(output);
        }
    }
}

void KScreenDaemon::scheduleMonitorChange()
{
    QMetaObject::invokeMethod(this, "setMonitorForChanges", Qt::QueuedConnection, Q_ARG(bool, true));
}

void KScreenDaemon::enableMonitor(KScreen::Output* output)
{
    connect(output, SIGNAL(currentModeIdChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(isEnabledChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(isPrimaryChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(outputChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(clonesChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(posChanged()), SLOT(configChanged()));
    connect(output, SIGNAL(rotationChanged()), SLOT(configChanged()));
}

void KScreenDaemon::disableMonitor(KScreen::Output* output)
{
    disconnect(output, SIGNAL(currentModeIdChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(isEnabledChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(isPrimaryChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(outputChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(clonesChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(posChanged()), this, SLOT(configChanged()));
    disconnect(output, SIGNAL(rotationChanged()), this, SLOT(configChanged()));
}

QMap<QString,QString> KScreenDaemon::listCurrentProfiles() const
{
    const QString cfgId = Serializer::currentConfigId();
    kDebug() << cfgId;
    return Serializer::listProfiles(cfgId);
}

QString KScreenDaemon::activeProfile() const
{
    return m_profileId;
}

void KScreenDaemon::activateProfile(const QString &id)
{
    const QString cfgId = Serializer::currentConfigId();
    kDebug() << cfgId << id;
    KScreen::Config *config = Serializer::config(cfgId, id);
    if (config->isValid()) {
        config->setConfig(config);
    }

    m_profileId = id;
}

QString KScreenDaemon::createProfileFromCurrentConfig(const QString &name, bool preferred)
{
    kDebug() << name;
    return Serializer::createProfile(KScreen::Config::current(), name);
}

void KScreenDaemon::deleteProfile(const QString &id)
{
    const QString cfgId = Serializer::currentConfigId();
    kDebug() << cfgId << id;
    Serializer::removeProfile(cfgId, id);

    Q_EMIT profilesChanged();
}

QDBusVariant KScreenDaemon::getProfile(const QString &id)
{
    const QString cfgId = Serializer::currentConfigId();
    kDebug() << cfgId << id;
    return QDBusVariant(Serializer::loadProfile(Serializer::currentConfigId(), id));
}
<|endoftext|>


<commit_before>/*
 * LCALIFLateralKernelConn.cpp
 *
 *  Created on: Oct 17, 2012
 *      Author: pschultz
 */

#include "LCALIFLateralKernelConn.hpp"

namespace PV {

LCALIFLateralKernelConn::LCALIFLateralKernelConn()
{
   initialize_base();
}

LCALIFLateralKernelConn::LCALIFLateralKernelConn(const char * name, HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post,
      const char * filename, InitWeights *weightInit) {
   initialize_base();
   initialize(name, hc, pre, post, filename, weightInit);
}

LCALIFLateralKernelConn::~LCALIFLateralKernelConn()
{
   pvcube_delete(integratedSpikeCountCube); integratedSpikeCountCube = NULL; integratedSpikeCount = NULL;
   Communicator::freeDatatypes(mpi_datatype); mpi_datatype = NULL;
}

int LCALIFLateralKernelConn::initialize_base() {
   integratedSpikeCountCube = NULL;
   integratedSpikeCount = NULL;
   mpi_datatype = NULL;
   return PV_SUCCESS;
}

int LCALIFLateralKernelConn::initialize(const char * name, HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post,
      const char * filename, InitWeights * weightInit) {
   int status = KernelConn::initialize(name, hc, pre, post, filename, weightInit);
   const PVLayerLoc * preloc = pre->getLayerLoc();
   const PVLayerLoc * postloc = post->getLayerLoc();
   int nxpre = preloc->nx; int nxpost = postloc->nx;
   int nypre = preloc->ny; int nypost = postloc->ny;
   int nfpre = preloc->nf; int nfpost = postloc->nf;
   int nbpre = preloc->nb; int nbpost = postloc->nb;
   if (nxpre!=nxpost || nypre!=nypost || nfpre!=nfpost || nbpre!=nbpost) {
      if (parent->columnId()==0) {
         fprintf(stderr, "LCALIFLateralKernelConn: pre- and post-synaptic layers must have the same geometry (including margin width)\n");
         fprintf(stderr, "  Pre:  nx=%d, ny=%d, nf=%d, nb=%d\n", nxpre, nypre, nfpre, nbpre);
         fprintf(stderr, "  Post: nx=%d, ny=%d, nf=%d, nb=%d\n", nxpost, nypost, nfpost, nbpost);
      }
      abort();
   }
   integratedSpikeCountCube = pvcube_new(pre->getLayerLoc(), pre->getNumExtended());
   integratedSpikeCount = integratedSpikeCountCube->data;
   for (int k=0; k<pre->getNumExtended(); k++) {
      integratedSpikeCount[k] = integrationTimeConstant*getTargetRateKHz(); // Spike counts initialized to equilibrium value
   }
   mpi_datatype = Communicator::newDatatypes(pre->getLayerLoc());
   if (mpi_datatype==NULL) {
      fprintf(stderr, "LCALIFLateralKernelConn \"%s\" error creating mpi_datatype\n", name);
      abort();
   }
   return status;
}

int LCALIFLateralKernelConn::setParams(PVParams * params) {
   int status = KernelConn::setParams(params);
   integrationTimeConstant = readIntegrationTimeConstant();
   inhibitionTimeConstant = readInhibitionTimeConstant();
   targetRateKHz = 0.001 * readTargetRate();
   return status;
}

int LCALIFLateralKernelConn::update_dW(int axonId) {
   int nExt = preSynapticLayer()->getNumExtended();
   int numKernelIndices = getNumDataPatches();
   updateIntegratedSpikeCount();
   float target_rate_sq = getTargetRateKHz()*getTargetRateKHz();
   float dt = (float) parent->getDeltaTime();
   float tauINH = getInhibitionTimeConstant();
   const pvdata_t * preactbuf = integratedSpikeCount;
   const pvdata_t * postactbuf = integratedSpikeCount;

   int sya = (post->getLayerLoc()->nf * (post->getLayerLoc()->nx + 2*post->getLayerLoc()->nb));

   for(int kExt=0; kExt<nExt;kExt++) {
      PVPatch * weights = getWeights(kExt,axonId);
      size_t offset = getAPostOffset(kExt, axonId);
      pvdata_t preactrate = preactbuf[kExt]/integrationTimeConstant;
      int ny = weights->ny;
      int nk = weights->nx * nfp;
      pvdata_t * dwdata = get_dwData(axonId, kExt);
      int lineoffsetw = 0;
      int lineoffseta = 0;
      for( int y=0; y<ny; y++ ) {
         for( int k=0; k<nk; k++ ) {
            int postactindex = offset+lineoffseta+k;
            if (postactindex != kExt) { // Neurons don't inhibit themselves
               pvdata_t postactrate = postactbuf[postactindex]/integrationTimeConstant;
               pvdata_t dw = preactrate*postactrate-target_rate_sq;
               dwdata[lineoffsetw + k] += dw;
            }
         }
         lineoffsetw += syp;
         lineoffseta += sya;
      }
   }

   // Normalize by dt/tauINH/(targetrate^2) and divide by (numNeurons/numKernels)
   int divisor = pre->getNumNeurons()/numKernelIndices;
   float normalizer = dt/tauINH/target_rate_sq/divisor;
   assert( divisor*numKernelIndices == pre->getNumNeurons() );
   for( int kernelindex=0; kernelindex<numKernelIndices; kernelindex++ ) {
      int numpatchitems = nxp*nyp*nfp;
      pvdata_t * dwpatchdata = get_dwDataHead(axonId,kernelindex);
      for( int n=0; n<numpatchitems; n++ ) {
         dwpatchdata[n] *= normalizer;
      }
   }

   lastUpdateTime = parent->simulationTime();

   return PV_SUCCESS;
}

int LCALIFLateralKernelConn::updateWeights(int axonId) {
   if (plasticityFlag) {
      for (int kernel=0; kernel<getNumDataPatches(); kernel++) {
         pvdata_t * dw_data = get_dwDataHead(axonId,kernel);
         pvdata_t * w_data = get_wDataHead(axonId,kernel);
         for (int y=0; y<nyp; y++) {
            for (int x=0; x<nxp; x++) {
               for (int f=0; f<nfp; f++) {
                  int idx = sxp*x + syp*y + sfp*f;
                  pvdata_t w = w_data[idx] + dw_data[idx];
                  if (w<0) w=0;
                  w_data[idx] = w;
               }
            }
         }
      }
   }
   return PV_SUCCESS;
}

int LCALIFLateralKernelConn::updateIntegratedSpikeCount() {
   float exp_dt_tau = exp(-parent->getDeltaTime()/integrationTimeConstant);
   const pvdata_t * activity = pre->getLayerData(); // pre->getActivity();
   for (int kext=0; kext<getNumWeightPatches(); kext++) {
      integratedSpikeCount[kext] = exp_dt_tau * (integratedSpikeCount[kext]+activity[kext]);
   }
   return PV_SUCCESS;
}

int LCALIFLateralKernelConn::checkpointWrite(const char * cpDir) {
   int status = KernelConn::checkpointWrite(cpDir);
   char filename[PV_PATH_MAX];
   int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_integratedSpikeCount.pvp", cpDir, name);
   if (chars_needed >= PV_PATH_MAX) {
      fprintf(stderr, "LCALIFLateralKernelConn::checkpointWrite error.  Path \"%s/%s_integratedSpikeCount.pvp\" is too long.\n", cpDir, name);
      abort();
   }
   write_pvdata(filename, parent->icCommunicator(), (double) parent->simulationTime(), integratedSpikeCount, pre->getLayerLoc(), PV_FLOAT_TYPE, /*extended*/ true, /*contiguous*/ false);
   return status;
}

int LCALIFLateralKernelConn::checkpointRead(const char * cpDir, double * timef) {
   int status = KernelConn::checkpointRead(cpDir, timef);
   char filename[PV_PATH_MAX];
   int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_integratedSpikeCount.pvp", cpDir, name);
   if (chars_needed >= PV_PATH_MAX) {
      fprintf(stderr, "LCALIFLateralKernelConn::checkpointWrite error.  Path \"%s/%s_integratedSpikeCount.pvp\" is too long.\n", cpDir, name);
      abort();
   }
   double timed;
   read_pvdata(filename, parent->icCommunicator(), &timed, integratedSpikeCount, pre->getLayerLoc(), PV_FLOAT_TYPE, /*extended*/ false, /*contiguous*/ false);
   if( (float) timed != *timef && parent->icCommunicator()->commRank() == 0 ) {
      fprintf(stderr, "Warning: %s and %s_A.pvp have different timestamps: %f versus %f\n", filename, name, (float) timed, *timef);
   }
   // Exchange borders
   if ( pre->useMirrorBCs() ) {
      for (int borderId = 1; borderId < NUM_NEIGHBORHOOD; borderId++){
         pre->mirrorInteriorToBorder(borderId, integratedSpikeCountCube, integratedSpikeCountCube);
      }
   }
   parent->icCommunicator()->exchange(integratedSpikeCount, mpi_datatype, pre->getLayerLoc());

   return status;
}

} /* namespace PV */
<commit_msg>Forced self-interaction weights in LCALIFLateralKernelConn to be zero.<commit_after>/*
 * LCALIFLateralKernelConn.cpp
 *
 *  Created on: Oct 17, 2012
 *      Author: pschultz
 */

#include "LCALIFLateralKernelConn.hpp"

namespace PV {

LCALIFLateralKernelConn::LCALIFLateralKernelConn()
{
   initialize_base();
}

LCALIFLateralKernelConn::LCALIFLateralKernelConn(const char * name, HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post,
      const char * filename, InitWeights *weightInit) {
   initialize_base();
   initialize(name, hc, pre, post, filename, weightInit);
}

LCALIFLateralKernelConn::~LCALIFLateralKernelConn()
{
   pvcube_delete(integratedSpikeCountCube); integratedSpikeCountCube = NULL; integratedSpikeCount = NULL;
   Communicator::freeDatatypes(mpi_datatype); mpi_datatype = NULL;
}

int LCALIFLateralKernelConn::initialize_base() {
   integratedSpikeCountCube = NULL;
   integratedSpikeCount = NULL;
   mpi_datatype = NULL;
   return PV_SUCCESS;
}

int LCALIFLateralKernelConn::initialize(const char * name, HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post,
      const char * filename, InitWeights * weightInit) {
   int status = KernelConn::initialize(name, hc, pre, post, filename, weightInit);
   const PVLayerLoc * preloc = pre->getLayerLoc();
   const PVLayerLoc * postloc = post->getLayerLoc();
   int nxpre = preloc->nx; int nxpost = postloc->nx;
   int nypre = preloc->ny; int nypost = postloc->ny;
   int nfpre = preloc->nf; int nfpost = postloc->nf;
   int nbpre = preloc->nb; int nbpost = postloc->nb;
   if (nxpre!=nxpost || nypre!=nypost || nfpre!=nfpost || nbpre!=nbpost) {
      if (parent->columnId()==0) {
         fprintf(stderr, "LCALIFLateralKernelConn: pre- and post-synaptic layers must have the same geometry (including margin width)\n");
         fprintf(stderr, "  Pre:  nx=%d, ny=%d, nf=%d, nb=%d\n", nxpre, nypre, nfpre, nbpre);
         fprintf(stderr, "  Post: nx=%d, ny=%d, nf=%d, nb=%d\n", nxpost, nypost, nfpost, nbpost);
      }
      abort();
   }

   // Neurons don't inhibit themselves, only their neighbors; set self-interaction weights to mmzero.
   assert(nxp % 2 == 1 && nyp % 2 == 1 && getNumDataPatches()==nfp);
   for (int k=0; k<getNumDataPatches(); k++) {
      int n = kIndex((nxp-1)/2, (nyp-1)/2, k, nxp, nyp, nfp);
      get_wDataHead(0, k)[n] = 0.0f;
   }

   integratedSpikeCountCube = pvcube_new(pre->getLayerLoc(), pre->getNumExtended());
   integratedSpikeCount = integratedSpikeCountCube->data;
   for (int k=0; k<pre->getNumExtended(); k++) {
      integratedSpikeCount[k] = integrationTimeConstant*getTargetRateKHz(); // Spike counts initialized to equilibrium value
   }
   mpi_datatype = Communicator::newDatatypes(pre->getLayerLoc());
   if (mpi_datatype==NULL) {
      fprintf(stderr, "LCALIFLateralKernelConn \"%s\" error creating mpi_datatype\n", name);
      abort();
   }
   return status;
}

int LCALIFLateralKernelConn::setParams(PVParams * params) {
   int status = KernelConn::setParams(params);
   integrationTimeConstant = readIntegrationTimeConstant();
   inhibitionTimeConstant = readInhibitionTimeConstant();
   targetRateKHz = 0.001 * readTargetRate();
   return status;
}

int LCALIFLateralKernelConn::update_dW(int axonId) {
   int nExt = preSynapticLayer()->getNumExtended();
   int numKernelIndices = getNumDataPatches();
   updateIntegratedSpikeCount();
   float target_rate_sq = getTargetRateKHz()*getTargetRateKHz();
   float dt = (float) parent->getDeltaTime();
   float tauINH = getInhibitionTimeConstant();
   const pvdata_t * preactbuf = integratedSpikeCount;
   const pvdata_t * postactbuf = integratedSpikeCount;

   int sya = (post->getLayerLoc()->nf * (post->getLayerLoc()->nx + 2*post->getLayerLoc()->nb));

   for(int kExt=0; kExt<nExt;kExt++) {
      PVPatch * weights = getWeights(kExt,axonId);
      size_t offset = getAPostOffset(kExt, axonId);
      pvdata_t preactrate = preactbuf[kExt]/integrationTimeConstant;
      int ny = weights->ny;
      int nk = weights->nx * nfp;
      pvdata_t * dwdata = get_dwData(axonId, kExt);
      int lineoffsetw = 0;
      int lineoffseta = 0;
      for( int y=0; y<ny; y++ ) {
         for( int k=0; k<nk; k++ ) {
            int postactindex = offset+lineoffseta+k;
            if (postactindex != kExt) { // Neurons don't inhibit themselves
               pvdata_t postactrate = postactbuf[postactindex]/integrationTimeConstant;
               pvdata_t dw = preactrate*postactrate-target_rate_sq;
               dwdata[lineoffsetw + k] += dw;
            }
         }
         lineoffsetw += syp;
         lineoffseta += sya;
      }
   }

   // Normalize by dt/tauINH/(targetrate^2) and divide by (numNeurons/numKernels)
   int divisor = pre->getNumNeurons()/numKernelIndices;
   float normalizer = dt/tauINH/target_rate_sq/divisor;
   assert( divisor*numKernelIndices == pre->getNumNeurons() );
   for( int kernelindex=0; kernelindex<numKernelIndices; kernelindex++ ) {
      int numpatchitems = nxp*nyp*nfp;
      pvdata_t * dwpatchdata = get_dwDataHead(axonId,kernelindex);
      for( int n=0; n<numpatchitems; n++ ) {
         dwpatchdata[n] *= normalizer;
      }
   }

   lastUpdateTime = parent->simulationTime();

   return PV_SUCCESS;
}

int LCALIFLateralKernelConn::updateWeights(int axonId) {
   if (plasticityFlag) {
      for (int kernel=0; kernel<getNumDataPatches(); kernel++) {
         pvdata_t * dw_data = get_dwDataHead(axonId,kernel);
         pvdata_t * w_data = get_wDataHead(axonId,kernel);
         for (int y=0; y<nyp; y++) {
            for (int x=0; x<nxp; x++) {
               for (int f=0; f<nfp; f++) {
                  int idx = sxp*x + syp*y + sfp*f;
                  pvdata_t w = w_data[idx] + dw_data[idx];
                  if (w<0) w=0;
                  w_data[idx] = w;
               }
            }
         }
      }
   }
   return PV_SUCCESS;
}

int LCALIFLateralKernelConn::updateIntegratedSpikeCount() {
   float exp_dt_tau = exp(-parent->getDeltaTime()/integrationTimeConstant);
   const pvdata_t * activity = pre->getLayerData(); // pre->getActivity();
   for (int kext=0; kext<getNumWeightPatches(); kext++) {
      integratedSpikeCount[kext] = exp_dt_tau * (integratedSpikeCount[kext]+activity[kext]);
   }
   return PV_SUCCESS;
}

int LCALIFLateralKernelConn::checkpointWrite(const char * cpDir) {
   int status = KernelConn::checkpointWrite(cpDir);
   char filename[PV_PATH_MAX];
   int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_integratedSpikeCount.pvp", cpDir, name);
   if (chars_needed >= PV_PATH_MAX) {
      fprintf(stderr, "LCALIFLateralKernelConn::checkpointWrite error.  Path \"%s/%s_integratedSpikeCount.pvp\" is too long.\n", cpDir, name);
      abort();
   }
   write_pvdata(filename, parent->icCommunicator(), (double) parent->simulationTime(), integratedSpikeCount, pre->getLayerLoc(), PV_FLOAT_TYPE, /*extended*/ true, /*contiguous*/ false);
   return status;
}

int LCALIFLateralKernelConn::checkpointRead(const char * cpDir, double * timef) {
   int status = KernelConn::checkpointRead(cpDir, timef);
   char filename[PV_PATH_MAX];
   int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_integratedSpikeCount.pvp", cpDir, name);
   if (chars_needed >= PV_PATH_MAX) {
      fprintf(stderr, "LCALIFLateralKernelConn::checkpointWrite error.  Path \"%s/%s_integratedSpikeCount.pvp\" is too long.\n", cpDir, name);
      abort();
   }
   double timed;
   read_pvdata(filename, parent->icCommunicator(), &timed, integratedSpikeCount, pre->getLayerLoc(), PV_FLOAT_TYPE, /*extended*/ false, /*contiguous*/ false);
   if( (float) timed != *timef && parent->icCommunicator()->commRank() == 0 ) {
      fprintf(stderr, "Warning: %s and %s_A.pvp have different timestamps: %f versus %f\n", filename, name, (float) timed, *timef);
   }
   // Exchange borders
   if ( pre->useMirrorBCs() ) {
      for (int borderId = 1; borderId < NUM_NEIGHBORHOOD; borderId++){
         pre->mirrorInteriorToBorder(borderId, integratedSpikeCountCube, integratedSpikeCountCube);
      }
   }
   parent->icCommunicator()->exchange(integratedSpikeCount, mpi_datatype, pre->getLayerLoc());

   return status;
}

} /* namespace PV */
<|endoftext|>


<commit_before>/*
This file is part of Groho, a simulator for inter-planetary travel and warfare.
Copyright (c) 2017-2018 by Kaushik Ghose. Some rights reserved, see LICENSE

A small class to carry a Vector data structure
*/

#pragma once

#include <cmath>
#include <iostream>

namespace groho {

struct V3d {
    double x, y, z;

    double norm_sq() const { return x * x + y * y + z * z; }
    double norm() const { return std::sqrt(norm_sq()); }
    V3d    normed() const { return V3d(*this) / norm(); }

    V3d operator+(const V3d& rhs) const
    {
        return V3d{ x + rhs.x, y + rhs.y, z + rhs.z };
    }

    V3d operator-(const V3d& rhs) const
    {
        return V3d{ x - rhs.x, y - rhs.y, z - rhs.z };
    }

    V3d operator/(const double rhs) const
    {
        return V3d{ x / rhs, y / rhs, z / rhs };
    }

    V3d& operator+=(const V3d& rhs)
    {
        x += rhs.x;
        y += rhs.y;
        z += rhs.z;
        return *this;
    }
};

typedef std::vector<V3d> v3d_vec_t;

inline double dot(const V3d& u, const V3d& v)
{
    return u.x * v.x + u.y * v.y + u.z * v.z;
}

inline V3d operator*(const V3d& u, const V3d& v)
{
    return { u.y * v.z - u.z * v.y,
             u.z * v.x - u.x * v.z,
             u.x * v.y - u.y * v.x };
}

inline V3d cross(const V3d& u, const V3d& v) { return u * v; }

inline V3d operator*(double lhs, const V3d& rhs)
{
    return { lhs * rhs.x, lhs * rhs.y, lhs * rhs.z };
}

inline V3d operator*(const V3d& lhs, double rhs)
{
    return { rhs * lhs.x, rhs * lhs.y, rhs * lhs.z };
}

inline V3d rotate(const V3d& v, V3d k, double th)
// Rotate v about k by th
// https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
{
    k = k / k.norm();
    return v * std::cos(th) + cross(k, v) * std::sin(th)
        + k * dot(k, v) * (1 - std::cos(th));
}

inline std::ostream& operator<<(std::ostream& os, const V3d& v)
{
    os << v.x << ", " << v.y << ", " << v.z;
    return os;
}

// Rolling buffer storing the last three position values
class PosBuf {
public:
    void append(V3d& p)
    {
        _pos[_idx] = p;
        _idx++;
        if (_idx > 2) {
            _idx = 0;
        }
    }

    V3d& T0() { return _pos[_idx]; }

    const V3d& T1() const
    {
        switch (_idx) {
        case 0:
            return _pos[2];
            break;
        case 1:
            return _pos[0];
            break;
        case 2:
            return _pos[1];
            break;
        }
    }

    const V3d& T2() const
    {
        switch (_idx) {
        case 0:
            return _pos[1];
            break;
        case 1:
            return _pos[2];
            break;
        case 2:
            return _pos[0];
            break;
        }
    }

private:
    V3d    _pos[3];
    size_t _idx = 0;
};

struct LatLon {
    float lat, lon;
    // LatLon( float _lat, float _lon ) { lat = _lat; lon = _lon; }
};

inline std::ostream& operator<<(std::ostream& os, const LatLon& ll)
{
    os << ll.lat << ", " << ll.lon;
    return os;
}

} // namespace groho<commit_msg>Remove obsolete code<commit_after>/*
This file is part of Groho, a simulator for inter-planetary travel and warfare.
Copyright (c) 2017-2018 by Kaushik Ghose. Some rights reserved, see LICENSE

A small class to carry a Vector data structure
*/

#pragma once

#include <cmath>
#include <iostream>

namespace groho {

struct V3d {
    double x, y, z;

    double norm_sq() const { return x * x + y * y + z * z; }
    double norm() const { return std::sqrt(norm_sq()); }
    V3d    normed() const { return V3d(*this) / norm(); }

    V3d operator+(const V3d& rhs) const
    {
        return V3d{ x + rhs.x, y + rhs.y, z + rhs.z };
    }

    V3d operator-(const V3d& rhs) const
    {
        return V3d{ x - rhs.x, y - rhs.y, z - rhs.z };
    }

    V3d operator/(const double rhs) const
    {
        return V3d{ x / rhs, y / rhs, z / rhs };
    }

    V3d& operator+=(const V3d& rhs)
    {
        x += rhs.x;
        y += rhs.y;
        z += rhs.z;
        return *this;
    }
};

typedef std::vector<V3d> v3d_vec_t;

inline double dot(const V3d& u, const V3d& v)
{
    return u.x * v.x + u.y * v.y + u.z * v.z;
}

inline V3d operator*(const V3d& u, const V3d& v)
{
    return { u.y * v.z - u.z * v.y,
             u.z * v.x - u.x * v.z,
             u.x * v.y - u.y * v.x };
}

inline V3d cross(const V3d& u, const V3d& v) { return u * v; }

inline V3d operator*(double lhs, const V3d& rhs)
{
    return { lhs * rhs.x, lhs * rhs.y, lhs * rhs.z };
}

inline V3d operator*(const V3d& lhs, double rhs)
{
    return { rhs * lhs.x, rhs * lhs.y, rhs * lhs.z };
}

inline V3d rotate(const V3d& v, V3d k, double th)
// Rotate v about k by th
// https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
{
    k = k / k.norm();
    return v * std::cos(th) + cross(k, v) * std::sin(th)
        + k * dot(k, v) * (1 - std::cos(th));
}

inline std::ostream& operator<<(std::ostream& os, const V3d& v)
{
    os << v.x << ", " << v.y << ", " << v.z;
    return os;
}

} // namespace groho<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
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 of the author 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 "libtorrent/pch.hpp"

#include <algorithm>
#include <iomanip>
#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"

#if defined(_MSC_VER)
namespace std
{
	using ::isprint;
}
#define for if (false) {} else for
#endif

namespace
{
	template <class T>
	void call_destructor(T* o)
	{
		TORRENT_ASSERT(o);
		o->~T();
	}

	struct compare_string
	{
		compare_string(char const* s): m_str(s)  {}

		bool operator()(
			std::pair<std::string
			, libtorrent::entry> const& e) const
		{
			return m_str && e.first == m_str;
		}
		char const* m_str;
	};
}

namespace libtorrent
{
	namespace detail
	{
		TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val)
		{
			int sign = 0;
			if (val < 0)
			{
				sign = 1;
				val = -val;
			}
			buf[--size] = '\0';
			if (val == 0) buf[--size] = '0';
			for (; size > sign && val != 0;)
			{
				buf[--size] = '0' + char(val % 10);
				val /= 10;
			}
			if (sign) buf[--size] = '-';
			return buf + size;
		}
	}

	entry& entry::operator[](char const* key)
	{
		dictionary_type::iterator i = dict().find(key);
		if (i != dict().end()) return i->second;
		dictionary_type::iterator ret = dict().insert(
			dict().begin()
			, std::make_pair(std::string(key), entry()));
		return ret->second;
	}

	entry& entry::operator[](std::string const& key)
	{
		return (*this)[key.c_str()];
	}

	entry* entry::find_key(char const* key)
	{
		dictionary_type::iterator i = std::find_if(
			dict().begin()
			, dict().end()
			, compare_string(key));
		if (i == dict().end()) return 0;
		return &i->second;

	}

	entry const* entry::find_key(char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) return 0;
		return &i->second;
	}

#ifndef BOOST_NO_EXCEPTIONS
	const entry& entry::operator[](char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) throw type_error(
			(std::string("key not found: ") + key).c_str());
		return i->second;
	}

	const entry& entry::operator[](std::string const& key) const
	{
		return (*this)[key.c_str()];
	}
#endif

	entry::entry(dictionary_type const& v)
	{
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	entry::entry(string_type const& v)
	{
		new(data) string_type(v);
		m_type = string_t;
	}

	entry::entry(list_type const& v)
	{
		new(data) list_type(v);
		m_type = list_t;
	}

	entry::entry(integer_type const& v)
	{
		new(data) integer_type(v);
		m_type = int_t;
	}

	void entry::operator=(dictionary_type const& v)
	{
		destruct();
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	void entry::operator=(string_type const& v)
	{
		destruct();
		new(data) string_type(v);
		m_type = string_t;
	}

	void entry::operator=(list_type const& v)
	{
		destruct();
		new(data) list_type(v);
		m_type = list_t;
	}

	void entry::operator=(integer_type const& v)
	{
		destruct();
		new(data) integer_type(v);
		m_type = int_t;
	}

	bool entry::operator==(entry const& e) const
	{
		if (m_type != e.m_type) return false;

		switch(m_type)
		{
		case int_t:
			return integer() == e.integer();
		case string_t:
			return string() == e.string();
		case list_t:
			return list() == e.list();
		case dictionary_t:
			return dict() == e.dict();
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			return true;
		}
	}

	void entry::construct(data_type t)
	{
		m_type = t;
		switch(m_type)
		{
		case int_t:
			new(data) integer_type;
			break;
		case string_t:
			new(data) string_type;
			break;
		case list_t:
			new(data) list_type;
			break;
		case dictionary_t:
			new (data) dictionary_type;
			break;
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			m_type = undefined_t;
		}
	}

	void entry::copy(entry const& e)
	{
		m_type = e.m_type;
		switch(m_type)
		{
		case int_t:
			new(data) integer_type(e.integer());
			break;
		case string_t:
			new(data) string_type(e.string());
			break;
		case list_t:
			new(data) list_type(e.list());
			break;
		case dictionary_t:
			new (data) dictionary_type(e.dict());
			break;
		default:
			m_type = undefined_t;
		}
	}

	void entry::destruct()
	{
		switch(m_type)
		{
		case int_t:
			call_destructor(reinterpret_cast<integer_type*>(data));
			break;
		case string_t:
			call_destructor(reinterpret_cast<string_type*>(data));
			break;
		case list_t:
			call_destructor(reinterpret_cast<list_type*>(data));
			break;
		case dictionary_t:
			call_destructor(reinterpret_cast<dictionary_type*>(data));
			break;
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			break;
		}
	}

	void entry::swap(entry& e)
	{
		// not implemented
		TORRENT_ASSERT(false);
	}

	void entry::print(std::ostream& os, int indent) const
	{
		TORRENT_ASSERT(indent >= 0);
		for (int i = 0; i < indent; ++i) os << " ";
		switch (m_type)
		{
		case int_t:
			os << integer() << "\n";
			break;
		case string_t:
			{
				bool binary_string = false;
				for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
				{
					if (!std::isprint(static_cast<unsigned char>(*i)))
					{
						binary_string = true;
						break;
					}
				}
				if (binary_string)
				{
					os.unsetf(std::ios_base::dec);
					os.setf(std::ios_base::hex);
					for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
						os << std::setfill('0') << std::setw(2)
							<< static_cast<unsigned int>((unsigned char)*i);
					os.unsetf(std::ios_base::hex);
					os.setf(std::ios_base::dec);
					os << "\n";
				}
				else
				{
					os << string() << "\n";
				}
			} break;
		case list_t:
			{
				os << "list\n";
				for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
				{
					i->print(os, indent+1);
				}
			} break;
		case dictionary_t:
			{
				os << "dictionary\n";
				for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
				{
					for (int j = 0; j < indent+1; ++j) os << " ";
					os << "[" << i->first << "]";
					if (i->second.type() != entry::string_t
						&& i->second.type() != entry::int_t)
						os << "\n";
					else os << " ";
					i->second.print(os, indent+2);
				}
			} break;
		default:
			os << "<uninitialized>\n";
		}
	}
}

<commit_msg>fixed missing include in entry.cpp<commit_after>/*

Copyright (c) 2003, Arvid Norberg
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 of the author 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 "libtorrent/pch.hpp"

#include <algorithm>
#include <iostream>
#include <iomanip>
#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"

#if defined(_MSC_VER)
namespace std
{
	using ::isprint;
}
#define for if (false) {} else for
#endif

namespace
{
	template <class T>
	void call_destructor(T* o)
	{
		TORRENT_ASSERT(o);
		o->~T();
	}

	struct compare_string
	{
		compare_string(char const* s): m_str(s)  {}

		bool operator()(
			std::pair<std::string
			, libtorrent::entry> const& e) const
		{
			return m_str && e.first == m_str;
		}
		char const* m_str;
	};
}

namespace libtorrent
{
	namespace detail
	{
		TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val)
		{
			int sign = 0;
			if (val < 0)
			{
				sign = 1;
				val = -val;
			}
			buf[--size] = '\0';
			if (val == 0) buf[--size] = '0';
			for (; size > sign && val != 0;)
			{
				buf[--size] = '0' + char(val % 10);
				val /= 10;
			}
			if (sign) buf[--size] = '-';
			return buf + size;
		}
	}

	entry& entry::operator[](char const* key)
	{
		dictionary_type::iterator i = dict().find(key);
		if (i != dict().end()) return i->second;
		dictionary_type::iterator ret = dict().insert(
			dict().begin()
			, std::make_pair(std::string(key), entry()));
		return ret->second;
	}

	entry& entry::operator[](std::string const& key)
	{
		return (*this)[key.c_str()];
	}

	entry* entry::find_key(char const* key)
	{
		dictionary_type::iterator i = std::find_if(
			dict().begin()
			, dict().end()
			, compare_string(key));
		if (i == dict().end()) return 0;
		return &i->second;

	}

	entry const* entry::find_key(char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) return 0;
		return &i->second;
	}

#ifndef BOOST_NO_EXCEPTIONS
	const entry& entry::operator[](char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) throw type_error(
			(std::string("key not found: ") + key).c_str());
		return i->second;
	}

	const entry& entry::operator[](std::string const& key) const
	{
		return (*this)[key.c_str()];
	}
#endif

	entry::entry(dictionary_type const& v)
	{
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	entry::entry(string_type const& v)
	{
		new(data) string_type(v);
		m_type = string_t;
	}

	entry::entry(list_type const& v)
	{
		new(data) list_type(v);
		m_type = list_t;
	}

	entry::entry(integer_type const& v)
	{
		new(data) integer_type(v);
		m_type = int_t;
	}

	void entry::operator=(dictionary_type const& v)
	{
		destruct();
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	void entry::operator=(string_type const& v)
	{
		destruct();
		new(data) string_type(v);
		m_type = string_t;
	}

	void entry::operator=(list_type const& v)
	{
		destruct();
		new(data) list_type(v);
		m_type = list_t;
	}

	void entry::operator=(integer_type const& v)
	{
		destruct();
		new(data) integer_type(v);
		m_type = int_t;
	}

	bool entry::operator==(entry const& e) const
	{
		if (m_type != e.m_type) return false;

		switch(m_type)
		{
		case int_t:
			return integer() == e.integer();
		case string_t:
			return string() == e.string();
		case list_t:
			return list() == e.list();
		case dictionary_t:
			return dict() == e.dict();
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			return true;
		}
	}

	void entry::construct(data_type t)
	{
		m_type = t;
		switch(m_type)
		{
		case int_t:
			new(data) integer_type;
			break;
		case string_t:
			new(data) string_type;
			break;
		case list_t:
			new(data) list_type;
			break;
		case dictionary_t:
			new (data) dictionary_type;
			break;
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			m_type = undefined_t;
		}
	}

	void entry::copy(entry const& e)
	{
		m_type = e.m_type;
		switch(m_type)
		{
		case int_t:
			new(data) integer_type(e.integer());
			break;
		case string_t:
			new(data) string_type(e.string());
			break;
		case list_t:
			new(data) list_type(e.list());
			break;
		case dictionary_t:
			new (data) dictionary_type(e.dict());
			break;
		default:
			m_type = undefined_t;
		}
	}

	void entry::destruct()
	{
		switch(m_type)
		{
		case int_t:
			call_destructor(reinterpret_cast<integer_type*>(data));
			break;
		case string_t:
			call_destructor(reinterpret_cast<string_type*>(data));
			break;
		case list_t:
			call_destructor(reinterpret_cast<list_type*>(data));
			break;
		case dictionary_t:
			call_destructor(reinterpret_cast<dictionary_type*>(data));
			break;
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			break;
		}
	}

	void entry::swap(entry& e)
	{
		// not implemented
		TORRENT_ASSERT(false);
	}

	void entry::print(std::ostream& os, int indent) const
	{
		TORRENT_ASSERT(indent >= 0);
		for (int i = 0; i < indent; ++i) os << " ";
		switch (m_type)
		{
		case int_t:
			os << integer() << "\n";
			break;
		case string_t:
			{
				bool binary_string = false;
				for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
				{
					if (!std::isprint(static_cast<unsigned char>(*i)))
					{
						binary_string = true;
						break;
					}
				}
				if (binary_string)
				{
					os.unsetf(std::ios_base::dec);
					os.setf(std::ios_base::hex);
					for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
						os << std::setfill('0') << std::setw(2)
							<< static_cast<unsigned int>((unsigned char)*i);
					os.unsetf(std::ios_base::hex);
					os.setf(std::ios_base::dec);
					os << "\n";
				}
				else
				{
					os << string() << "\n";
				}
			} break;
		case list_t:
			{
				os << "list\n";
				for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
				{
					i->print(os, indent+1);
				}
			} break;
		case dictionary_t:
			{
				os << "dictionary\n";
				for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
				{
					for (int j = 0; j < indent+1; ++j) os << " ";
					os << "[" << i->first << "]";
					if (i->second.type() != entry::string_t
						&& i->second.type() != entry::int_t)
						os << "\n";
					else os << " ";
					i->second.print(os, indent+2);
				}
			} break;
		default:
			os << "<uninitialized>\n";
		}
	}
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) version 3, or any
 * later version accepted by the membership of KDE e.V. (or its
 * successor approved by the membership of KDE e.V.), which shall
 * act as a proxy defined in Section 6 of version 3 of the license.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "FilesystemContentLister.h"
#include <QCoreApplication>

#include <QDirIterator>
#include <QMimeDatabase>
#include <QVariantHash>
#include <QDebug>

class FilesystemContentLister::Private
{
public:
    Private() {}
    QString searchString;
    QStringList locations;
    QStringList mimetypes;
};

FilesystemContentLister::FilesystemContentLister(QObject* parent)
    : ContentListerBase(parent)
    , d(new Private)
{
}

FilesystemContentLister::~FilesystemContentLister()
{
    delete d;
}

void FilesystemContentLister::addLocation(QString path)
{
    d->locations.append(path);
}

void FilesystemContentLister::addMimetype(QString mimetype)
{
    d->mimetypes.append(mimetype);
}

void FilesystemContentLister::setSearchString(const QString& searchString)
{
    d->searchString = searchString;
}

void FilesystemContentLister::startSearch()
{
    QMimeDatabase mimeDb;
    bool useThis(false);

    qDebug() << "Searching in" << d->locations;
    Q_FOREACH(const QString& folder, d->locations)
    {
        QDirIterator it(folder, QDirIterator::Subdirectories);
        while (it.hasNext())
        {
            QString filePath = it.next();

            useThis = false;
            QString mimetype = mimeDb.mimeTypeForFile(filePath, QMimeDatabase::MatchExtension).name();
            qDebug() << useThis << mimetype << filePath;
            Q_FOREACH(const QString& type, d->mimetypes)
            {
                if(type == mimetype) {
                    useThis = true;
                    break;
                }
            }

            if(useThis)
            {
                emit fileFound(filePath, QVariantHash());
            }
            qApp->processEvents();
        }
    }

    emit searchCompleted();
}
<commit_msg>Don't try to interpret directories...<commit_after>/*
 * Copyright (C) 2015 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) version 3, or any
 * later version accepted by the membership of KDE e.V. (or its
 * successor approved by the membership of KDE e.V.), which shall
 * act as a proxy defined in Section 6 of version 3 of the license.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "FilesystemContentLister.h"
#include <QCoreApplication>

#include <QDirIterator>
#include <QMimeDatabase>
#include <QVariantHash>
#include <QDebug>

class FilesystemContentLister::Private
{
public:
    Private() {}
    QString searchString;
    QStringList locations;
    QStringList mimetypes;
};

FilesystemContentLister::FilesystemContentLister(QObject* parent)
    : ContentListerBase(parent)
    , d(new Private)
{
}

FilesystemContentLister::~FilesystemContentLister()
{
    delete d;
}

void FilesystemContentLister::addLocation(QString path)
{
    d->locations.append(path);
}

void FilesystemContentLister::addMimetype(QString mimetype)
{
    d->mimetypes.append(mimetype);
}

void FilesystemContentLister::setSearchString(const QString& searchString)
{
    d->searchString = searchString;
}

void FilesystemContentLister::startSearch()
{
    QMimeDatabase mimeDb;
    bool useThis(false);

    qDebug() << "Searching in" << d->locations;
    Q_FOREACH(const QString& folder, d->locations)
    {
        QDirIterator it(folder, QDirIterator::Subdirectories);
        while (it.hasNext())
        {
            QString filePath = it.next();

            if(QFileInfo(filePath).isDir())
            {
                qApp->processEvents();
                continue;
            }
            useThis = false;
            QString mimetype = mimeDb.mimeTypeForFile(filePath, QMimeDatabase::MatchExtension).name();
//             qDebug() << useThis << mimetype << filePath;
            Q_FOREACH(const QString& type, d->mimetypes)
            {
                if(type == mimetype) {
                    useThis = true;
                    break;
                }
            }

            if(useThis)
            {
                emit fileFound(filePath, QVariantHash());
            }
            qApp->processEvents();
        }
    }

    emit searchCompleted();
}
<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "errors.hpp"

#include <cxxabi.h>

#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <typeinfo>

#include "logger.hpp"
#include "utils.hpp"
#include "backtrace.hpp"
#include "thread_local.hpp"
#include "clustering/administration/logger.hpp"
#include "arch/timing.hpp"

TLS_with_init(bool, crashed, false); // to prevent crashing within crashes

NOINLINE int get_errno() {
    return errno;
}
NOINLINE void set_errno(int new_errno) {
    errno = new_errno;
}

NORETURN void crash_oom() {
    const char *message = "rethinkdb: Memory allocation failed. This usually means "
                          "that we have run out of RAM. Aborting.\n";
    fwrite(message, 1, strlen(message), stderr);
    abort();
}

void report_user_error(const char *msg, ...) {
    fprintf(stderr, "Version: %s\n", RETHINKDB_VERSION_STR);
    if (TLS_get_crashed()) {
        va_list args;
        va_start(args, msg);
        fprintf(stderr, "Crashing while already crashed. Printing error message to stderr.\n");
        vfprintf(stderr, msg, args);
        va_end(args);
        return;
    }

    TLS_set_crashed(true);

    thread_log_writer_disabler_t disabler;

    va_list args;
    va_start(args, msg);
    vlogERR(msg, args);
    va_end(args);
}

void report_fatal_error(const char *file, int line, const char *msg, ...) {
    fprintf(stderr, "Version: %s\n", RETHINKDB_VERSION_STR);
    if (TLS_get_crashed()) {
        va_list args;
        va_start(args, msg);
        fprintf(stderr, "Crashing while already crashed. Printing error message to stderr.\n");
        vfprintf(stderr, msg, args);
        va_end(args);
        return;
    }

    TLS_set_crashed(true);

    thread_log_writer_disabler_t disabler;

    va_list args;
    va_start(args, msg);
    logERR("Error in %s at line %d:", file, line);
    vlogERR(msg, args);
    va_end(args);

    /* Don't print backtraces in valgrind mode because valgrind issues lots of spurious
    warnings when print_backtrace() is run. */
#if !defined(VALGRIND)
    logERR("Backtrace:");
    logERR("%s", format_backtrace().c_str());
#endif

    logERR("Exiting.");
}

const char *errno_string_maybe_using_buffer(int errsv, char *buf, size_t buflen) {
#ifdef _GNU_SOURCE
    return strerror_r(errsv, buf, buflen);
#else
    // The result is either 0 or ERANGE (if the buffer is too small) or EINVAL (if the error number
    // is invalid), but in either case a friendly nul-terminated buffer is written.
    UNUSED int res = strerror_r(errsv, buf, buflen);
    return buf;
#endif  // _GNU_SOURCE
}

/* Handlers for various signals and for unexpected exceptions or calls to std::terminate() */

NORETURN void generic_crash_handler(int signum) {
    if (signum == SIGSEGV) {
        crash("Segmentation fault.");
    } else {
        crash("Unexpected signal: %d", signum);
    }
}

NORETURN void terminate_handler() {
    std::type_info *t = abi::__cxa_current_exception_type();
    if (t) {
        std::string name;
        try {
            name = demangle_cpp_name(t->name());
        } catch (const demangle_failed_exc_t &) {
            name = t->name();
        }
        try {
            /* This will rethrow whatever unexpected exception was thrown. */
            throw;
        } catch (const std::exception& e) {
            crash("Uncaught exception of type \"%s\"\n  what(): %s", name.c_str(), e.what());
        } catch (...) {
            crash("Uncaught exception of type \"%s\"", name.c_str());
        }
        unreachable();
    } else {
        crash("std::terminate() called without any exception.");
    }
}

void install_generic_crash_handler() {

#ifndef VALGRIND
    {
        struct sigaction sa = make_sa_handler(0, generic_crash_handler);

        int res = sigaction(SIGSEGV, &sa, NULL);
        guarantee_err(res == 0, "Could not install SEGV handler");
    }
#endif

    struct sigaction sa = make_sa_handler(0, SIG_IGN);
    int res = sigaction(SIGPIPE, &sa, NULL);
    guarantee_err(res == 0, "Could not install PIPE handler");

    std::set_terminate(&terminate_handler);
}

/* If a call to `operator new()` or `operator new[]()` fails, we have to crash
immediately.
The default behavior of this handler is to throw an `std::bad_alloc` exception.
However that is dangerous because it unwinds the stack and can cause side-effects
including data corruption. */
NORETURN void new_oom_handler() {
    crash_oom();
}

void install_new_oom_handler() {
    std::set_new_handler(&new_oom_handler);
}

/* Boost will call this function when an assertion fails. */

namespace boost {

void assertion_failed(char const * expr, char const * function, char const * file, long line) { // NOLINT(runtime/int)
    report_fatal_error(file, line, "BOOST_ASSERT failure in '%s': %s", function, expr);
    BREAKPOINT;
}

void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line) { // NOLINT(runtime/int)
    report_fatal_error(file, line, "BOOST_ASSERT_MSG failure in '%s': %s (%s)", function, expr, msg);
    BREAKPOINT;
}

}  // namespace boost
<commit_msg>Fix for #2511<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "errors.hpp"

#include <cxxabi.h>

#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <typeinfo>

#include "logger.hpp"
#include "utils.hpp"
#include "backtrace.hpp"
#include "thread_local.hpp"
#include "clustering/administration/logger.hpp"
#include "arch/timing.hpp"

TLS_with_init(bool, crashed, false); // to prevent crashing within crashes

NOINLINE int get_errno() {
    return errno;
}
NOINLINE void set_errno(int new_errno) {
    errno = new_errno;
}

NORETURN void crash_oom() {
    const char *message = "rethinkdb: Memory allocation failed. This usually means "
                          "that we have run out of RAM. Aborting.\n";
    UNUSED size_t res = fwrite(message, 1, strlen(message), stderr);
    abort();
}

void report_user_error(const char *msg, ...) {
    fprintf(stderr, "Version: %s\n", RETHINKDB_VERSION_STR);
    if (TLS_get_crashed()) {
        va_list args;
        va_start(args, msg);
        fprintf(stderr, "Crashing while already crashed. Printing error message to stderr.\n");
        vfprintf(stderr, msg, args);
        va_end(args);
        return;
    }

    TLS_set_crashed(true);

    thread_log_writer_disabler_t disabler;

    va_list args;
    va_start(args, msg);
    vlogERR(msg, args);
    va_end(args);
}

void report_fatal_error(const char *file, int line, const char *msg, ...) {
    fprintf(stderr, "Version: %s\n", RETHINKDB_VERSION_STR);
    if (TLS_get_crashed()) {
        va_list args;
        va_start(args, msg);
        fprintf(stderr, "Crashing while already crashed. Printing error message to stderr.\n");
        vfprintf(stderr, msg, args);
        va_end(args);
        return;
    }

    TLS_set_crashed(true);

    thread_log_writer_disabler_t disabler;

    va_list args;
    va_start(args, msg);
    logERR("Error in %s at line %d:", file, line);
    vlogERR(msg, args);
    va_end(args);

    /* Don't print backtraces in valgrind mode because valgrind issues lots of spurious
    warnings when print_backtrace() is run. */
#if !defined(VALGRIND)
    logERR("Backtrace:");
    logERR("%s", format_backtrace().c_str());
#endif

    logERR("Exiting.");
}

const char *errno_string_maybe_using_buffer(int errsv, char *buf, size_t buflen) {
#ifdef _GNU_SOURCE
    return strerror_r(errsv, buf, buflen);
#else
    // The result is either 0 or ERANGE (if the buffer is too small) or EINVAL (if the error number
    // is invalid), but in either case a friendly nul-terminated buffer is written.
    UNUSED int res = strerror_r(errsv, buf, buflen);
    return buf;
#endif  // _GNU_SOURCE
}

/* Handlers for various signals and for unexpected exceptions or calls to std::terminate() */

NORETURN void generic_crash_handler(int signum) {
    if (signum == SIGSEGV) {
        crash("Segmentation fault.");
    } else {
        crash("Unexpected signal: %d", signum);
    }
}

NORETURN void terminate_handler() {
    std::type_info *t = abi::__cxa_current_exception_type();
    if (t) {
        std::string name;
        try {
            name = demangle_cpp_name(t->name());
        } catch (const demangle_failed_exc_t &) {
            name = t->name();
        }
        try {
            /* This will rethrow whatever unexpected exception was thrown. */
            throw;
        } catch (const std::exception& e) {
            crash("Uncaught exception of type \"%s\"\n  what(): %s", name.c_str(), e.what());
        } catch (...) {
            crash("Uncaught exception of type \"%s\"", name.c_str());
        }
        unreachable();
    } else {
        crash("std::terminate() called without any exception.");
    }
}

void install_generic_crash_handler() {

#ifndef VALGRIND
    {
        struct sigaction sa = make_sa_handler(0, generic_crash_handler);

        int res = sigaction(SIGSEGV, &sa, NULL);
        guarantee_err(res == 0, "Could not install SEGV handler");
    }
#endif

    struct sigaction sa = make_sa_handler(0, SIG_IGN);
    int res = sigaction(SIGPIPE, &sa, NULL);
    guarantee_err(res == 0, "Could not install PIPE handler");

    std::set_terminate(&terminate_handler);
}

/* If a call to `operator new()` or `operator new[]()` fails, we have to crash
immediately.
The default behavior of this handler is to throw an `std::bad_alloc` exception.
However that is dangerous because it unwinds the stack and can cause side-effects
including data corruption. */
NORETURN void new_oom_handler() {
    crash_oom();
}

void install_new_oom_handler() {
    std::set_new_handler(&new_oom_handler);
}

/* Boost will call this function when an assertion fails. */

namespace boost {

void assertion_failed(char const * expr, char const * function, char const * file, long line) { // NOLINT(runtime/int)
    report_fatal_error(file, line, "BOOST_ASSERT failure in '%s': %s", function, expr);
    BREAKPOINT;
}

void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line) { // NOLINT(runtime/int)
    report_fatal_error(file, line, "BOOST_ASSERT_MSG failure in '%s': %s (%s)", function, expr, msg);
    BREAKPOINT;
}

}  // namespace boost
<|endoftext|>


<commit_before>/*
 * DesktopMacDetectRHome.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopDetectRHome.hpp"

#include <vector>

#include <boost/algorithm/string/trim.hpp>

#include <QtCore>
#include <QMessageBox>

#include <core/Error.hpp>
#include <core/Log.hpp>
#include <core/FilePath.hpp>
#include <core/system/System.hpp>

#include "config.h"

using namespace core;

namespace desktop {

namespace {

// MacOS X Specific
#ifdef __APPLE__

#define kLibRFileName            "libR.dylib"
#define kLibraryPathEnvVariable  "DYLD_LIBRARY_PATH"

 // define search paths to match shell search path behavior (including
 // /opt/local/bin being first since that is where macports puts it)
 std::vector<std::string> rSearchPaths()
 {
    std::vector<std::string> rPaths;
    rPaths.push_back("/opt/local/bin/R");
    rPaths.push_back("/usr/bin/R");
    rPaths.push_back("/usr/local/bin/R");
    return rPaths;
 }

 // no extra paths on the mac
 std::string extraLibraryPaths(const std::string& rHome)
 {
    return std::string();
 }

// Linux specific
#else

#define kLibRFileName            "libR.so"
#define kLibraryPathEnvVariable  "LD_LIBRARY_PATH"

 // define search paths to match shell search path behavior (note differs
 // from macox by having /usr/local/bin first)
 std::vector<std::string> rSearchPaths()
 {
    std::vector<std::string> rPaths;
    rPaths.push_back("/usr/local/bin/R");
    rPaths.push_back("/usr/bin/R");
    return rPaths;
 }

 // extra paths from R (for rjava) on linux
 std::string extraLibraryPaths(const std::string& rHome)
 {
    std::string libraryPaths;

    FilePath supportingFilePath = desktop::options().supportingFilePath();
    FilePath scriptPath = supportingFilePath.complete("bin/r-ldpath");
    if (!scriptPath.exists())
      scriptPath = supportingFilePath.complete("session/r-ldpath");
    if (scriptPath.exists())
    {
       // run script
       std::string command = scriptPath.absolutePath() + " " + rHome;
       Error error = system::captureCommand(command, &libraryPaths);
       if (error)
          LOG_ERROR(error);
    }

    return libraryPaths;
 }

#endif

FilePath detectRHome()
{
   // scan possible locations for R (need these because on the mac
   // our path as a GUI app is very limited)
   FilePath rPath;
   std::vector<std::string> rPaths = rSearchPaths();
   for(std::vector<std::string>::const_iterator it = rPaths.begin();
       it != rPaths.end(); ++it)
   {
      FilePath candidatePath(*it);
      if (candidatePath.exists())
      {
         rPath = candidatePath ;
         break;
      }
   }

   // if we didn't find one then bail
   if (rPath.empty())
   {
      LOG_ERROR_MESSAGE("Couldn't find R on known path");
      return FilePath();
   }

   // run R to detect R home
   std::string output;
   std::string command = rPath.absolutePath() + " RHOME";
   Error error = core::system::captureCommand(command, &output);
   if (error)
   {
      LOG_ERROR(error);
      return FilePath();
   }
   boost::algorithm::trim(output);

   // return the home path if we got one
   if (!output.empty())
      return FilePath(output);
   else
      return FilePath();
}

void showRNotFoundError(const std::string& msg)
{
   QMessageBox::critical(NULL, "R Not Found", QString::fromStdString(msg));
}

} // anonymous namespace

bool prepareEnvironment(Options&)
{
   // declare home path and doc dir -- can get them from the environment
   // or by probing the system
   FilePath homePath, rDocDir;

   // first check environment
   std::string home = core::system::getenv("R_HOME");
   if (!home.empty())
      homePath = FilePath(home);
   std::string doc = core::system::getenv("R_DOC_DIR");
   if (!doc.empty())
      rDocDir = FilePath(doc);

   // probe for home path if necessary
   if (homePath.empty())
      homePath = detectRHome();

   // if that didn't work then try the configured path as a last ditch
   if (!homePath.exists())
      homePath = FilePath(CONFIG_R_HOME_PATH);

   // verify and set home path
   if (homePath.exists())
   {
      core::system::setenv("R_HOME", homePath.absolutePath());
   }
   else
   {
      showRNotFoundError("R home path (" + homePath.absolutePath() +
                         ") does not exist. Is R installed on "
                         "this system?");
      return false;
   }

   // complete doc dir if necesary
   if (rDocDir.empty())
      rDocDir = homePath.complete("doc");

   // doc dir may be in configured location (/usr/share) rather than
   // a subdirectory of R_HOME (this is in fact the case for the
   // debian r-base package). so check the configuired location as
   // a last ditch
   if (!rDocDir.exists())
      rDocDir = FilePath(CONFIG_R_DOC_PATH);

   // verify and set doc dir
   if (rDocDir.exists())
   {
       core::system::setenv("R_DOC_DIR", rDocDir.absolutePath());
   }
   else
   {
      showRNotFoundError("R doc directory (" + rDocDir.absolutePath() +
                         ") does not exist.");
      return false;
   }

   // verify and set library path
   FilePath rLibPath = homePath.complete("lib");
   if (rLibPath.exists())
   {
      // make sure the R lib was built
      FilePath libRpath = rLibPath.complete(kLibRFileName);
      if (libRpath.exists())
      {
         // initialize library path from existing value + any extras
         std::string libraryPath = core::system::getenv(kLibraryPathEnvVariable);
         if (!libraryPath.empty())
            libraryPath.append(":");
         libraryPath.append(rLibPath.absolutePath());
         std::string extraPaths = extraLibraryPaths(homePath.absolutePath());
         if (!extraPaths.empty())
            libraryPath.append(":" + extraPaths);

         // set it
         core::system::setenv(kLibraryPathEnvVariable, libraryPath);
      }
      else
      {
         showRNotFoundError(rLibPath.absolutePath() + " not found. "
                            "If this is a custom build of R, was it "
                            "built with the --enable-R-shlib option?");
         return false;
      }
   }
   else
   {
      showRNotFoundError("R library directory (" + rLibPath.absolutePath() +
                         ") does not exist.");
      return false;
   }

   return true;
}

} // namespace desktop
<commit_msg>use which to determine what version of R to bind to<commit_after>/*
 * DesktopMacDetectRHome.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopDetectRHome.hpp"

#include <vector>

#include <boost/algorithm/string/trim.hpp>

#include <QtCore>
#include <QMessageBox>

#include <core/Error.hpp>
#include <core/Log.hpp>
#include <core/FilePath.hpp>
#include <core/system/System.hpp>

#include "config.h"

using namespace core;

namespace desktop {

namespace {

// MacOS X Specific
#ifdef __APPLE__

#define kLibRFileName            "libR.dylib"
#define kLibraryPathEnvVariable  "DYLD_LIBRARY_PATH"

// define additional search paths for R. match shell search path behavior
// (including /opt/local/bin being first since that is where macports puts it)
void appendRPaths(std::vector<std::string>* pRPaths)
{
   pRPaths->push_back("/opt/local/bin/R");
   pRPaths->push_back("/usr/bin/R");
   pRPaths->push_back("/usr/local/bin/R");
}

// no extra paths on the mac
std::string extraLibraryPaths(const std::string& rHome)
{
 return std::string();
}

// Linux specific
#else

#define kLibRFileName            "libR.so"
#define kLibraryPathEnvVariable  "LD_LIBRARY_PATH"

// define additional search paths for R. match typical shell search path behavior
// (note differs from macox by having /usr/local/bin first)
void appendRPaths(std::vector<std::string>* pRPaths)
{
   pRPaths->push_back("/usr/local/bin/R");
   pRPaths->push_back("/usr/bin/R");
}

// extra paths from R (for rjava) on linux
std::string extraLibraryPaths(const std::string& rHome)
{
   std::string libraryPaths;

   FilePath supportingFilePath = desktop::options().supportingFilePath();
   FilePath scriptPath = supportingFilePath.complete("bin/r-ldpath");
   if (!scriptPath.exists())
      scriptPath = supportingFilePath.complete("session/r-ldpath");
   if (scriptPath.exists())
   {
      // run script
      std::string command = scriptPath.absolutePath() + " " + rHome;
      Error error = system::captureCommand(command, &libraryPaths);
      if (error)
         LOG_ERROR(error);
   }

   return libraryPaths;
}

#endif

FilePath systemDefaultR()
{
   // ask system which R to use
   std::string whichOutput;
   Error error = core::system::captureCommand("which R", &whichOutput);
   if (error)
   {
      LOG_ERROR(error);
      return FilePath();
   }
   boost::algorithm::trim(whichOutput);

   // check for nothing returned
   if (whichOutput.empty())
      return FilePath();

   // verify that the alias points to a real version of R
   FilePath rBinaryPath;
   error = core::system::realPath(whichOutput, &rBinaryPath);
   if (error)
   {
      LOG_ERROR(error);
      return FilePath();
   }

   // check for real path doesn't exist
   if (!rBinaryPath.exists())
      return FilePath();

   // got a valid R binary
   return rBinaryPath;
}

FilePath detectRHome()
{
   // scan possible locations for R (need these because on the mac
   // our path as a GUI app is very limited)
   FilePath rPath;
   std::vector<std::string> rPaths;

   // system default goes first (and will always be used if known)
   FilePath systemDefaultRPath = systemDefaultR();
   if (!systemDefaultRPath.empty())
      rPaths.push_back(systemDefaultRPath.absolutePath());

   // platfom specific additional paths to look for R binary
   appendRPaths(&rPaths);

   // scan the paths for a file that exists
   for(std::vector<std::string>::const_iterator it = rPaths.begin();
       it != rPaths.end(); ++it)
   {
      FilePath candidatePath(*it);
      if (candidatePath.exists())
      {
         rPath = candidatePath ;
         break;
      }
   }

   // if we didn't find one then bail
   if (rPath.empty())
   {
      LOG_ERROR_MESSAGE("Couldn't find R on known path");
      return FilePath();
   }

   // run R to detect R home
   std::string output;
   std::string command = rPath.absolutePath() + " RHOME";
   Error error = core::system::captureCommand(command, &output);
   if (error)
   {
      LOG_ERROR(error);
      return FilePath();
   }
   boost::algorithm::trim(output);

   // return the home path if we got one
   if (!output.empty())
      return FilePath(output);
   else
      return FilePath();
}

void showRNotFoundError(const std::string& msg)
{
   QMessageBox::critical(NULL, "R Not Found", QString::fromStdString(msg));
}

} // anonymous namespace

bool prepareEnvironment(Options&)
{
   // declare home path and doc dir -- can get them from the environment
   // or by probing the system
   FilePath homePath, rDocDir;

   // first check environment
   std::string home = core::system::getenv("R_HOME");
   if (!home.empty())
      homePath = FilePath(home);
   std::string doc = core::system::getenv("R_DOC_DIR");
   if (!doc.empty())
      rDocDir = FilePath(doc);

   // probe for home path if necessary
   if (homePath.empty())
      homePath = detectRHome();

   // if that didn't work then try the configured path as a last ditch
   if (!homePath.exists())
      homePath = FilePath(CONFIG_R_HOME_PATH);

   // verify and set home path
   if (homePath.exists())
   {
      core::system::setenv("R_HOME", homePath.absolutePath());
   }
   else
   {
      showRNotFoundError("R home path (" + homePath.absolutePath() +
                         ") does not exist. Is R installed on "
                         "this system?");
      return false;
   }

   // complete doc dir if necesary
   if (rDocDir.empty())
      rDocDir = homePath.complete("doc");

   // doc dir may be in configured location (/usr/share) rather than
   // a subdirectory of R_HOME (this is in fact the case for the
   // debian r-base package). so check the configuired location as
   // a last ditch
   if (!rDocDir.exists())
      rDocDir = FilePath(CONFIG_R_DOC_PATH);

   // verify and set doc dir
   if (rDocDir.exists())
   {
       core::system::setenv("R_DOC_DIR", rDocDir.absolutePath());
   }
   else
   {
      showRNotFoundError("R doc directory (" + rDocDir.absolutePath() +
                         ") does not exist.");
      return false;
   }

   // verify and set library path
   FilePath rLibPath = homePath.complete("lib");
   if (rLibPath.exists())
   {
      // make sure the R lib was built
      FilePath libRpath = rLibPath.complete(kLibRFileName);
      if (libRpath.exists())
      {
         // initialize library path from existing value + any extras
         std::string libraryPath = core::system::getenv(kLibraryPathEnvVariable);
         if (!libraryPath.empty())
            libraryPath.append(":");
         libraryPath.append(rLibPath.absolutePath());
         std::string extraPaths = extraLibraryPaths(homePath.absolutePath());
         if (!extraPaths.empty())
            libraryPath.append(":" + extraPaths);

         // set it
         core::system::setenv(kLibraryPathEnvVariable, libraryPath);
      }
      else
      {
         showRNotFoundError(rLibPath.absolutePath() + " not found. "
                            "If this is a custom build of R, was it "
                            "built with the --enable-R-shlib option?");
         return false;
      }
   }
   else
   {
      showRNotFoundError("R library directory (" + rLibPath.absolutePath() +
                         ") does not exist.");
      return false;
   }

   return true;
}

} // namespace desktop
<|endoftext|>


<commit_before>#include "xchainer/native/col2im.h"

#include <algorithm>
#include <cstdint>
#include <vector>

#include "xchainer/array.h"
#include "xchainer/array_index.h"
#include "xchainer/constant.h"
#include "xchainer/device.h"
#include "xchainer/dtype.h"
#include "xchainer/indexable_array.h"
#include "xchainer/indexer.h"
#include "xchainer/routines/creation.h"
#include "xchainer/scalar.h"
#include "xchainer/shape.h"
#include "xchainer/slice.h"
#include "xchainer/stack_vector.h"

namespace xchainer {
namespace native {
namespace native_internal {

namespace {

template <typename T, int8_t kKernelNdim>
void Col2ImImpl(const Array& col, const Array& out, const StackVector<int64_t, kMaxNdim>& stride, const Indexer<2>& batch_channel_indexer) {
    static constexpr int8_t kColNdim = 2 + 2 * kKernelNdim;
    static constexpr int8_t kOutNdim = 2 + kKernelNdim;

    assert(kKernelNdim == static_cast<int8_t>(stride.size()));
    assert(kColNdim == col.ndim());
    assert(kOutNdim == out.ndim());

    Indexer<kKernelNdim> kernel_indexer{Shape{col.shape().begin() + 2, col.shape().begin() + 2 + kKernelNdim}};
    Indexer<kKernelNdim> in_image_dims_indexer{Shape{col.shape().begin() + 2 + kKernelNdim, col.shape().end()}};
    Indexer<kColNdim> col_indexer{col.shape()};
    Indexer<kOutNdim> out_indexer{out.shape()};
    IndexableArray<const T, kColNdim> col_iarray{col};
    IndexableArray<T, kOutNdim> out_iarray{out};

    // Indices over the output image.
    NdimIndex out_image_index{kKernelNdim};

    auto it_batch_channel = batch_channel_indexer.It(0);
    auto it_kernel = kernel_indexer.It(0);
    auto it_in_image_dims = in_image_dims_indexer.It(0);
    auto it_col = col_indexer.It(0);
    auto it_out = out_indexer.It(0);
    for (it_batch_channel.Restart(); it_batch_channel; ++it_batch_channel) {
        for (it_kernel.Restart(); it_kernel; ++it_kernel) {
            for (it_in_image_dims.Restart(); it_in_image_dims; ++it_in_image_dims) {
                for (int8_t i = 0; i < kKernelNdim; ++i) {
                    out_image_index.index()[i] = it_in_image_dims.index()[i] * stride[i] + it_kernel.index()[i];
                }

                it_col.Combine(it_batch_channel, it_kernel, it_in_image_dims);
                it_out.Combine(it_batch_channel, out_image_index);

                out_iarray[it_out] += col_iarray[it_col];
            }
        }
    }
}

}  // namespace

Array Col2Im(
        const Array& col,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        const StackVector<int64_t, kMaxNdim>& out_size) {
    int64_t batch_size = col.shape()[0];
    int64_t channels = col.shape()[1];
    auto ndim = static_cast<int8_t>(stride.size());
    assert(ndim * 2 + 2 == col.ndim());

    Shape padded_shape{batch_size, channels};
    for (int8_t i = 0; i < ndim; ++i) {
        padded_shape.emplace_back(out_size[i] + 2 * pad[i] + stride[i] - 1);
    }
    Array padded_out = Zeros(padded_shape, col.dtype(), col.device());
    assert(ndim + 2 == padded_out.ndim());

    // Write to the output array
    VisitDtype(col.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        Indexer<2> batch_channel_indexer{Shape{batch_size, channels}};

        static_assert(4 * 2 + 2 == kMaxNdim, "4 is the maximum kernel ndim whose col ndim does not exceed kMaxNdim");
        switch (ndim) {
            case 0:
                Col2ImImpl<T, 0>(col, padded_out, stride, batch_channel_indexer);
                break;
            case 1:
                Col2ImImpl<T, 1>(col, padded_out, stride, batch_channel_indexer);
                break;
            case 2:
                Col2ImImpl<T, 2>(col, padded_out, stride, batch_channel_indexer);
                break;
            case 3:
                Col2ImImpl<T, 3>(col, padded_out, stride, batch_channel_indexer);
                break;
            case 4:
                Col2ImImpl<T, 4>(col, padded_out, stride, batch_channel_indexer);
                break;
            default:
                XCHAINER_NEVER_REACH();  // Never col.ndim() > kMaxNdim
                break;
        }
    });

    std::vector<ArrayIndex> slice{ArrayIndex{Slice{}}, ArrayIndex{Slice{}}};  // All batch and channel dimensions.
    for (int8_t i = 0; i < ndim; ++i) {
        slice.emplace_back(Slice{pad[i], pad[i] + out_size[i]});
    }
    return padded_out.At(slice);
}

}  // namespace native_internal
}  // namespace native
}  // namespace xchainer
<commit_msg>Update col2im similarly with im2col<commit_after>#include "xchainer/native/col2im.h"

#include <algorithm>
#include <cstdint>
#include <vector>

#include "xchainer/array.h"
#include "xchainer/array_index.h"
#include "xchainer/constant.h"
#include "xchainer/device.h"
#include "xchainer/dtype.h"
#include "xchainer/indexable_array.h"
#include "xchainer/indexer.h"
#include "xchainer/routines/creation.h"
#include "xchainer/scalar.h"
#include "xchainer/shape.h"
#include "xchainer/slice.h"
#include "xchainer/stack_vector.h"

namespace xchainer {
namespace native {
namespace native_internal {

namespace {

template <typename T, int8_t kKernelNdim>
void Col2ImImpl(const Array& col, const Array& out, const StackVector<int64_t, kMaxNdim>& stride, const Indexer<2>& batch_channel_indexer) {
    static constexpr int8_t kColNdim = 2 + 2 * kKernelNdim;
    static constexpr int8_t kOutNdim = 2 + kKernelNdim;

    assert(kKernelNdim == static_cast<int8_t>(stride.size()));
    assert(kColNdim == col.ndim());
    assert(kOutNdim == out.ndim());

    Indexer<kKernelNdim> kernel_indexer{Shape{col.shape().begin() + 2, col.shape().begin() + 2 + kKernelNdim}};
    Indexer<kKernelNdim> in_image_dims_indexer{Shape{col.shape().begin() + 2 + kKernelNdim, col.shape().end()}};
    Indexer<kColNdim> col_indexer{col.shape()};
    Indexer<kOutNdim> out_indexer{out.shape()};
    IndexableArray<const T, kColNdim> col_iarray{col};
    IndexableArray<T, kOutNdim> out_iarray{out};

    // Indices over the output image.
    NdimIndex out_image_index{kKernelNdim};

    auto it_batch_channel = batch_channel_indexer.It(0);
    auto it_kernel = kernel_indexer.It(0);
    auto it_in_image_dims = in_image_dims_indexer.It(0);
    auto it_col = col_indexer.It(0);
    auto it_out = out_indexer.It(0);
    for (it_batch_channel.Restart(); it_batch_channel; ++it_batch_channel) {
        it_col.CopyFrom(it_batch_channel);
        it_out.CopyFrom(it_batch_channel);

        for (it_kernel.Restart(); it_kernel; ++it_kernel) {
            it_col.CopyFrom(it_kernel, batch_channel_indexer.ndim());

            for (it_in_image_dims.Restart(); it_in_image_dims; ++it_in_image_dims) {
                for (int8_t i = 0; i < kKernelNdim; ++i) {
                    out_image_index.index()[i] = it_in_image_dims.index()[i] * stride[i] + it_kernel.index()[i];
                }
                it_col.CopyFrom(it_in_image_dims, batch_channel_indexer.ndim() + kernel_indexer.ndim());
                it_out.CopyFrom(out_image_index, batch_channel_indexer.ndim());

                out_iarray[it_out] += col_iarray[it_col];
            }
        }
    }
}

}  // namespace

Array Col2Im(
        const Array& col,
        const StackVector<int64_t, kMaxNdim>& stride,
        const StackVector<int64_t, kMaxNdim>& pad,
        const StackVector<int64_t, kMaxNdim>& out_size) {
    int64_t batch_size = col.shape()[0];
    int64_t channels = col.shape()[1];
    auto ndim = static_cast<int8_t>(stride.size());
    assert(ndim * 2 + 2 == col.ndim());

    Shape padded_shape{batch_size, channels};
    for (int8_t i = 0; i < ndim; ++i) {
        padded_shape.emplace_back(out_size[i] + 2 * pad[i] + stride[i] - 1);
    }
    Array padded_out = Zeros(padded_shape, col.dtype(), col.device());
    assert(ndim + 2 == padded_out.ndim());

    // Write to the output array
    VisitDtype(col.dtype(), [&](auto pt) {
        using T = typename decltype(pt)::type;
        Indexer<2> batch_channel_indexer{Shape{batch_size, channels}};

        static_assert(4 * 2 + 2 == kMaxNdim, "4 is the maximum kernel ndim whose col ndim does not exceed kMaxNdim");
        switch (ndim) {
            case 0:
                Col2ImImpl<T, 0>(col, padded_out, stride, batch_channel_indexer);
                break;
            case 1:
                Col2ImImpl<T, 1>(col, padded_out, stride, batch_channel_indexer);
                break;
            case 2:
                Col2ImImpl<T, 2>(col, padded_out, stride, batch_channel_indexer);
                break;
            case 3:
                Col2ImImpl<T, 3>(col, padded_out, stride, batch_channel_indexer);
                break;
            case 4:
                Col2ImImpl<T, 4>(col, padded_out, stride, batch_channel_indexer);
                break;
            default:
                XCHAINER_NEVER_REACH();  // Never col.ndim() > kMaxNdim
                break;
        }
    });

    std::vector<ArrayIndex> slice{ArrayIndex{Slice{}}, ArrayIndex{Slice{}}};  // All batch and channel dimensions.
    for (int8_t i = 0; i < ndim; ++i) {
        slice.emplace_back(Slice{pad[i], pad[i] + out_size[i]});
    }
    return padded_out.At(slice);
}

}  // namespace native_internal
}  // namespace native
}  // namespace xchainer
<|endoftext|>