<commit_before>/*
 * MomentumConn.cpp
 *
 *  Created on: Feburary 27, 2014
 *      Author: slundquist
 */

#include "MomentumConn.hpp"
#include <cstring>

namespace PV {

MomentumConn::MomentumConn() { initialize_base(); }

MomentumConn::MomentumConn(const char *name, HyPerCol *hc) : HyPerConn() {
   initialize_base();
   initialize(name, hc);
}

MomentumConn::~MomentumConn() {
   if (momentumMethod) {
      free(momentumMethod);
   }
   if (prev_dwDataStart) {
      free(prev_dwDataStart[0]);
      free(prev_dwDataStart);
   }
}

int MomentumConn::initialize_base() {
   prev_dwDataStart = NULL;
   momentumTau      = .25;
   momentumMethod   = NULL;
   momentumDecay    = 0;
   return PV_SUCCESS;
}

int MomentumConn::allocateDataStructures() {
   int status = HyPerConn::allocateDataStructures();
   if (status == PV_POSTPONE) {
      return status;
   }
   if (!plasticityFlag)
      return status;
   int sx       = nfp;
   int sy       = sx * nxp;
   int sp       = sy * nyp;
   int nPatches = getNumDataPatches();

   const int numAxons = numberOfAxonalArborLists();

   // Allocate dw buffer for previous dw
   prev_dwDataStart       = (float **)pvCalloc(numAxons, sizeof(float *));
   std::size_t numWeights = (std::size_t)(numAxons * nxp * nyp * nfp) * (std::size_t)nPatches;
   prev_dwDataStart[0]    = (float *)pvCalloc(numWeights, sizeof(float));
   for (int arborId = 0; arborId < numAxons; arborId++) {
      prev_dwDataStart[arborId] = (prev_dwDataStart[0] + sp * nPatches * arborId);
      pvAssert(prev_dwDataStart[arborId] != NULL);
   } // loop over arbors

   return PV_SUCCESS;
}

int MomentumConn::ioParamsFillGroup(enum ParamsIOFlag ioFlag) {
   int status = HyPerConn::ioParamsFillGroup(ioFlag);
   ioParam_momentumMethod(ioFlag);
   ioParam_momentumTau(ioFlag);
   ioParam_momentumDecay(ioFlag);
   ioParam_batchPeriod(ioFlag);
   return status;
}

void MomentumConn::ioParam_momentumTau(enum ParamsIOFlag ioFlag) {
   pvAssert(!parent->parameters()->presentAndNotBeenRead(name, "plasticityFlag"));
   if (plasticityFlag) {
      float defaultVal = 0;
      if (strcmp(momentumMethod, "simple") == 0) {
         defaultVal = .25;
      }
      else if (strcmp(momentumMethod, "viscosity") == 0) {
         defaultVal = 100;
      }
      else if (strcmp(momentumMethod, "alex") == 0) {
         defaultVal = .9;
      }

      parent->parameters()->ioParamValue(ioFlag, name, "momentumTau", &momentumTau, defaultVal);
   }
}

/**
 * @brief momentumMethod: The momentum method to use
 * @details Assuming a = dwMax * pre * post
 * simple: deltaW(t) = a + momentumTau * deltaW(t-1)
 * viscosity: deltaW(t) = (deltaW(t-1) * exp(-1/momentumTau)) + a
 * alex: deltaW(t) = momentumTau * delta(t-1) - momentumDecay * dwMax * w(t) + a
 */
void MomentumConn::ioParam_momentumMethod(enum ParamsIOFlag ioFlag) {
   pvAssert(!parent->parameters()->presentAndNotBeenRead(name, "plasticityFlag"));
   if (plasticityFlag) {
      parent->parameters()->ioParamStringRequired(ioFlag, name, "momentumMethod", &momentumMethod);
      if (strcmp(momentumMethod, "simple") != 0 && strcmp(momentumMethod, "viscosity") != 0
          && strcmp(momentumMethod, "alex")) {
         Fatal() << "MomentumConn " << name << ": momentumMethod of " << momentumMethod
                 << " is not known, options are \"simple\", \"viscosity\", and \"alex\"\n";
      }
   }
}

void MomentumConn::ioParam_momentumDecay(enum ParamsIOFlag ioFlag) {
   pvAssert(!parent->parameters()->presentAndNotBeenRead(name, "plasticityFlag"));
   if (plasticityFlag) {
      parent->parameters()->ioParamValue(
            ioFlag, name, "momentumDecay", &momentumDecay, momentumDecay);
      if (momentumDecay < 0 || momentumDecay > 1) {
         Fatal() << "MomentumConn " << name
                 << ": momentumDecay must be between 0 and 1 inclusive\n";
      }
   }
}

// batchPeriod parameter was marked obsolete Jan 17, 2017.
void MomentumConn::ioParam_batchPeriod(enum ParamsIOFlag ioFlag) {
   pvAssert(!parent->parameters()->presentAndNotBeenRead(name, "plasticityFlag"));
   if (plasticityFlag and parent->parameters()->present(name, "batchPeriod")) {
      int obsoleteBatchPeriod = (int)parent->parameters()->value(name, "batchPeriod");
      if (obsoleteBatchPeriod != 1) {
         if (parent->getCommunicator()->globalCommRank() == 0) {
            ErrorLog() << getDescription() << ": MomentumConn parameter batchPeriod is obsolete. "
                       << "Instead use the HyPerCol nbatch parameter.\n";
         }
         MPI_Barrier(parent->getCommunicator()->globalCommunicator());
         exit(EXIT_FAILURE);
      }
   }
}

int MomentumConn::updateWeights(int arborId) {
   // Add momentum right before updateWeights
   for (int kArbor = 0; kArbor < this->numberOfAxonalArborLists(); kArbor++) {
      applyMomentum(arborId);
   }

   // Saved to prevweights
   pvAssert(prev_dwDataStart);
   std::memcpy(
         *prev_dwDataStart,
         *get_dwDataStart(),
         sizeof(float) * numberOfAxonalArborLists() * nxp * nyp * nfp * getNumDataPatches());

   // add dw to w
   for (int kArbor = 0; kArbor < this->numberOfAxonalArborLists(); kArbor++) {
      float *w_data_start = get_wDataStart(kArbor);
      for (long int k = 0; k < patchStartIndex(getNumDataPatches()); k++) {
         w_data_start[k] += get_dwDataStart(kArbor)[k];
      }
   }
   return PV_BREAK;
}

int MomentumConn::applyMomentum(int arbor_ID) {
   int nExt              = preSynapticLayer()->getNumExtended();
   const PVLayerLoc *loc = preSynapticLayer()->getLayerLoc();
   int numKernels        = getNumDataPatches();

   // Shared weights done in parallel, parallel in numkernels
   if (!strcmp(momentumMethod, "simple")) {
#ifdef PV_USE_OPENMP_THREADS
#pragma omp parallel for
#endif
      for (int kernelIdx = 0; kernelIdx < numKernels; kernelIdx++) {
         float *dwdata_start        = get_dwDataHead(arbor_ID, kernelIdx);
         float const *prev_dw_start = get_prev_dwDataHead(arbor_ID, kernelIdx);
         float const *wdata_start   = get_wDataHead(arbor_ID, kernelIdx);
         for (int k = 0; k < nxp * nyp * nfp; k++) {
            dwdata_start[k] += momentumTau * prev_dw_start[k] - momentumDecay * wdata_start[k];
         }
      }
   }
   else if (!strcmp(momentumMethod, "viscosity")) {
      float const tauFactor = exp(-1.0f / momentumTau);
#ifdef PV_USE_OPENMP_THREADS
#pragma omp parallel for
#endif
      for (int kernelIdx = 0; kernelIdx < numKernels; kernelIdx++) {
         float *dwdata_start        = get_dwDataHead(arbor_ID, kernelIdx);
         float const *prev_dw_start = get_prev_dwDataHead(arbor_ID, kernelIdx);
         float const *wdata_start   = get_wDataHead(arbor_ID, kernelIdx);
         for (int k = 0; k < nxp * nyp * nfp; k++) {
            dwdata_start[k] += tauFactor * prev_dw_start[k] - momentumDecay * wdata_start[k];
         }
      }
   }
   else if (!strcmp(momentumMethod, "alex")) {
      float const decayFactor = momentumDecay * getDWMax();
#ifdef PV_USE_OPENMP_THREADS
#pragma omp parallel for
#endif
      for (int kernelIdx = 0; kernelIdx < numKernels; kernelIdx++) {
         float *dwdata_start        = get_dwDataHead(arbor_ID, kernelIdx);
         float const *prev_dw_start = get_prev_dwDataHead(arbor_ID, kernelIdx);
         float const *wdata_start   = get_wDataHead(arbor_ID, kernelIdx);
         for (int k = 0; k < nxp * nyp * nfp; k++) {
            dwdata_start[k] += momentumTau * prev_dw_start[k] - decayFactor * wdata_start[k];
         }
      }
   }
   else {
      pvAssertMessage(0, "Unrecognized momentumMethod\n");
   }
   return PV_SUCCESS;
}

// TODO checkpointing not working with batching, must write checkpoint exactly at period
int MomentumConn::registerData(Checkpointer *checkpointer, std::string const &objName) {
   int status = HyPerConn::registerData(checkpointer, objName);
   if (plasticityFlag) {
      checkpointWeightPvp(checkpointer, "prev_dW", prev_dwDataStart);
   }
}

int MomentumConn::readStateFromCheckpoint(Checkpointer *checkpointer) {
   int status = PV_SUCCESS;
   if (initializeFromCheckpointFlag) {
      status = HyPerConn::readStateFromCheckpoint(checkpointer);
      if (plasticityFlag) {
         checkpointer->readNamedCheckpointEntry(std::string(name), std::string("prev_dW"));
      }
   }
   return status;
}

} // end namespace PV
<commit_msg>Hotfix: missing return value<commit_after>/*
 * MomentumConn.cpp
 *
 *  Created on: Feburary 27, 2014
 *      Author: slundquist
 */

#include "MomentumConn.hpp"
#include <cstring>

namespace PV {

MomentumConn::MomentumConn() { initialize_base(); }

MomentumConn::MomentumConn(const char *name, HyPerCol *hc) : HyPerConn() {
   initialize_base();
   initialize(name, hc);
}

MomentumConn::~MomentumConn() {
   if (momentumMethod) {
      free(momentumMethod);
   }
   if (prev_dwDataStart) {
      free(prev_dwDataStart[0]);
      free(prev_dwDataStart);
   }
}

int MomentumConn::initialize_base() {
   prev_dwDataStart = NULL;
   momentumTau      = .25;
   momentumMethod   = NULL;
   momentumDecay    = 0;
   return PV_SUCCESS;
}

int MomentumConn::allocateDataStructures() {
   int status = HyPerConn::allocateDataStructures();
   if (status == PV_POSTPONE) {
      return status;
   }
   if (!plasticityFlag)
      return status;
   int sx       = nfp;
   int sy       = sx * nxp;
   int sp       = sy * nyp;
   int nPatches = getNumDataPatches();

   const int numAxons = numberOfAxonalArborLists();

   // Allocate dw buffer for previous dw
   prev_dwDataStart       = (float **)pvCalloc(numAxons, sizeof(float *));
   std::size_t numWeights = (std::size_t)(numAxons * nxp * nyp * nfp) * (std::size_t)nPatches;
   prev_dwDataStart[0]    = (float *)pvCalloc(numWeights, sizeof(float));
   for (int arborId = 0; arborId < numAxons; arborId++) {
      prev_dwDataStart[arborId] = (prev_dwDataStart[0] + sp * nPatches * arborId);
      pvAssert(prev_dwDataStart[arborId] != NULL);
   } // loop over arbors

   return PV_SUCCESS;
}

int MomentumConn::ioParamsFillGroup(enum ParamsIOFlag ioFlag) {
   int status = HyPerConn::ioParamsFillGroup(ioFlag);
   ioParam_momentumMethod(ioFlag);
   ioParam_momentumTau(ioFlag);
   ioParam_momentumDecay(ioFlag);
   ioParam_batchPeriod(ioFlag);
   return status;
}

void MomentumConn::ioParam_momentumTau(enum ParamsIOFlag ioFlag) {
   pvAssert(!parent->parameters()->presentAndNotBeenRead(name, "plasticityFlag"));
   if (plasticityFlag) {
      float defaultVal = 0;
      if (strcmp(momentumMethod, "simple") == 0) {
         defaultVal = .25;
      }
      else if (strcmp(momentumMethod, "viscosity") == 0) {
         defaultVal = 100;
      }
      else if (strcmp(momentumMethod, "alex") == 0) {
         defaultVal = .9;
      }

      parent->parameters()->ioParamValue(ioFlag, name, "momentumTau", &momentumTau, defaultVal);
   }
}

/**
 * @brief momentumMethod: The momentum method to use
 * @details Assuming a = dwMax * pre * post
 * simple: deltaW(t) = a + momentumTau * deltaW(t-1)
 * viscosity: deltaW(t) = (deltaW(t-1) * exp(-1/momentumTau)) + a
 * alex: deltaW(t) = momentumTau * delta(t-1) - momentumDecay * dwMax * w(t) + a
 */
void MomentumConn::ioParam_momentumMethod(enum ParamsIOFlag ioFlag) {
   pvAssert(!parent->parameters()->presentAndNotBeenRead(name, "plasticityFlag"));
   if (plasticityFlag) {
      parent->parameters()->ioParamStringRequired(ioFlag, name, "momentumMethod", &momentumMethod);
      if (strcmp(momentumMethod, "simple") != 0 && strcmp(momentumMethod, "viscosity") != 0
          && strcmp(momentumMethod, "alex")) {
         Fatal() << "MomentumConn " << name << ": momentumMethod of " << momentumMethod
                 << " is not known, options are \"simple\", \"viscosity\", and \"alex\"\n";
      }
   }
}

void MomentumConn::ioParam_momentumDecay(enum ParamsIOFlag ioFlag) {
   pvAssert(!parent->parameters()->presentAndNotBeenRead(name, "plasticityFlag"));
   if (plasticityFlag) {
      parent->parameters()->ioParamValue(
            ioFlag, name, "momentumDecay", &momentumDecay, momentumDecay);
      if (momentumDecay < 0 || momentumDecay > 1) {
         Fatal() << "MomentumConn " << name
                 << ": momentumDecay must be between 0 and 1 inclusive\n";
      }
   }
}

// batchPeriod parameter was marked obsolete Jan 17, 2017.
void MomentumConn::ioParam_batchPeriod(enum ParamsIOFlag ioFlag) {
   pvAssert(!parent->parameters()->presentAndNotBeenRead(name, "plasticityFlag"));
   if (plasticityFlag and parent->parameters()->present(name, "batchPeriod")) {
      int obsoleteBatchPeriod = (int)parent->parameters()->value(name, "batchPeriod");
      if (obsoleteBatchPeriod != 1) {
         if (parent->getCommunicator()->globalCommRank() == 0) {
            ErrorLog() << getDescription() << ": MomentumConn parameter batchPeriod is obsolete. "
                       << "Instead use the HyPerCol nbatch parameter.\n";
         }
         MPI_Barrier(parent->getCommunicator()->globalCommunicator());
         exit(EXIT_FAILURE);
      }
   }
}

int MomentumConn::updateWeights(int arborId) {
   // Add momentum right before updateWeights
   for (int kArbor = 0; kArbor < this->numberOfAxonalArborLists(); kArbor++) {
      applyMomentum(arborId);
   }

   // Saved to prevweights
   pvAssert(prev_dwDataStart);
   std::memcpy(
         *prev_dwDataStart,
         *get_dwDataStart(),
         sizeof(float) * numberOfAxonalArborLists() * nxp * nyp * nfp * getNumDataPatches());

   // add dw to w
   for (int kArbor = 0; kArbor < this->numberOfAxonalArborLists(); kArbor++) {
      float *w_data_start = get_wDataStart(kArbor);
      for (long int k = 0; k < patchStartIndex(getNumDataPatches()); k++) {
         w_data_start[k] += get_dwDataStart(kArbor)[k];
      }
   }
   return PV_BREAK;
}

int MomentumConn::applyMomentum(int arbor_ID) {
   int nExt              = preSynapticLayer()->getNumExtended();
   const PVLayerLoc *loc = preSynapticLayer()->getLayerLoc();
   int numKernels        = getNumDataPatches();

   // Shared weights done in parallel, parallel in numkernels
   if (!strcmp(momentumMethod, "simple")) {
#ifdef PV_USE_OPENMP_THREADS
#pragma omp parallel for
#endif
      for (int kernelIdx = 0; kernelIdx < numKernels; kernelIdx++) {
         float *dwdata_start        = get_dwDataHead(arbor_ID, kernelIdx);
         float const *prev_dw_start = get_prev_dwDataHead(arbor_ID, kernelIdx);
         float const *wdata_start   = get_wDataHead(arbor_ID, kernelIdx);
         for (int k = 0; k < nxp * nyp * nfp; k++) {
            dwdata_start[k] += momentumTau * prev_dw_start[k] - momentumDecay * wdata_start[k];
         }
      }
   }
   else if (!strcmp(momentumMethod, "viscosity")) {
      float const tauFactor = exp(-1.0f / momentumTau);
#ifdef PV_USE_OPENMP_THREADS
#pragma omp parallel for
#endif
      for (int kernelIdx = 0; kernelIdx < numKernels; kernelIdx++) {
         float *dwdata_start        = get_dwDataHead(arbor_ID, kernelIdx);
         float const *prev_dw_start = get_prev_dwDataHead(arbor_ID, kernelIdx);
         float const *wdata_start   = get_wDataHead(arbor_ID, kernelIdx);
         for (int k = 0; k < nxp * nyp * nfp; k++) {
            dwdata_start[k] += tauFactor * prev_dw_start[k] - momentumDecay * wdata_start[k];
         }
      }
   }
   else if (!strcmp(momentumMethod, "alex")) {
      float const decayFactor = momentumDecay * getDWMax();
#ifdef PV_USE_OPENMP_THREADS
#pragma omp parallel for
#endif
      for (int kernelIdx = 0; kernelIdx < numKernels; kernelIdx++) {
         float *dwdata_start        = get_dwDataHead(arbor_ID, kernelIdx);
         float const *prev_dw_start = get_prev_dwDataHead(arbor_ID, kernelIdx);
         float const *wdata_start   = get_wDataHead(arbor_ID, kernelIdx);
         for (int k = 0; k < nxp * nyp * nfp; k++) {
            dwdata_start[k] += momentumTau * prev_dw_start[k] - decayFactor * wdata_start[k];
         }
      }
   }
   else {
      pvAssertMessage(0, "Unrecognized momentumMethod\n");
   }
   return PV_SUCCESS;
}

// TODO checkpointing not working with batching, must write checkpoint exactly at period
int MomentumConn::registerData(Checkpointer *checkpointer, std::string const &objName) {
   int status = HyPerConn::registerData(checkpointer, objName);
   if (plasticityFlag) {
      checkpointWeightPvp(checkpointer, "prev_dW", prev_dwDataStart);
   }
   return status;
}

int MomentumConn::readStateFromCheckpoint(Checkpointer *checkpointer) {
   int status = PV_SUCCESS;
   if (initializeFromCheckpointFlag) {
      status = HyPerConn::readStateFromCheckpoint(checkpointer);
      if (plasticityFlag) {
         checkpointer->readNamedCheckpointEntry(std::string(name), std::string("prev_dW"));
      }
   }
   return status;
}

} // end namespace PV
<|endoftext|>


<commit_before>//
//  MCIndexSet.cpp
//  mailcore2
//
//  Created by DINH Viêt Hoà on 3/4/13.
//  Copyright (c) 2013 MailCore. All rights reserved.
//

#include "MCIndexSet.h"

#include "MCString.h"
#include "MCAssert.h"
#include "MCRange.h"
#include "MCLog.h"
#include "MCArray.h"
#include "MCHashMap.h"
#include "MCUtils.h"

using namespace mailcore;

void IndexSet::init()
{
    mRanges = NULL;
    mAllocated = 0;
    mCount = 0;
}

IndexSet::IndexSet()
{
    init();
}

IndexSet::IndexSet(IndexSet * o)
{
    init();
    mRanges = new Range[o->mAllocated];
    for(unsigned int i = 0 ; i < o->mCount ; i ++) {
        mRanges[i] = o->mRanges[i];
    }
    mAllocated = o->mAllocated;
    mCount = o->mCount;
}

IndexSet::~IndexSet()
{
    removeAllIndexes();
}

IndexSet * IndexSet::indexSet()
{
    IndexSet * result = new IndexSet();
    result->autorelease();
    return result;
}

IndexSet * IndexSet::indexSetWithRange(Range range)
{
    IndexSet * result = new IndexSet();
    result->autorelease();
    result->addRange(range);
    return result;
}

IndexSet * IndexSet::indexSetWithIndex(uint64_t idx)
{
    IndexSet * result = new IndexSet();
    result->autorelease();
    result->addIndex(idx);
    return result;
}

unsigned int IndexSet::count()
{
    unsigned int total = 0;
    for(unsigned int i = 0 ; i < mCount ; i ++) {
        total += mRanges[i].length + 1;
    }
    return total;
}

int IndexSet::rangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right)
{
    unsigned int middle = (left + right) / 2;

    Range middleRange = mRanges[middle];

    if (left == right) {
        if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) {
            return left;
        }
        return -1;
    }

    if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) {
        return middle;
    }
    if (idx < middleRange.location) {
        return rangeIndexForIndexWithBounds(idx, left, middle);
    }
    else {
        return rangeIndexForIndexWithBounds(idx, middle + 1, right);
    }
}

int IndexSet::rangeIndexForIndex(uint64_t idx)
{
    if (mCount == 0)
        return -1;

    return rangeIndexForIndexWithBounds(idx, 0, mCount - 1);
}

int IndexSet::rightRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right)
{
    unsigned int middle = (left + right) / 2;

    Range middleRange = mRanges[middle];

    if (left == right) {
        if (idx > middleRange.location + middleRange.length) {
            return left + 1;
        }
        else {
            return left;
        }
    }

    if (idx < middleRange.location + middleRange.length) {
        return rightRangeIndexForIndexWithBounds(idx, left, middle);
    }
    else {
        return rightRangeIndexForIndexWithBounds(idx, middle + 1, right);
    }
}

int IndexSet::rightRangeIndexForIndex(uint64_t idx)
{
    if (mCount == 0)
        return 0;

    return rightRangeIndexForIndexWithBounds(idx, 0, mCount - 1);
}

int IndexSet::leftRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right)
{
    unsigned int middle = (left + right) / 2;

    Range middleRange = mRanges[middle];

    if (left == right) {
        if (idx <= middleRange.location) {
            return left;
        }
        else {
            return left + 1;
        }
    }

    if (idx <= middleRange.location) {
        return leftRangeIndexForIndexWithBounds(idx, left, middle);
    }
    else {
        return leftRangeIndexForIndexWithBounds(idx, middle + 1, right);
    }
}

int IndexSet::leftRangeIndexForIndex(uint64_t idx)
{
    if (mCount == 0)
        return 0;

    return leftRangeIndexForIndexWithBounds(idx, 0, mCount - 1);
}

void IndexSet::addRangeIndex(unsigned int rangeIndex)
{
    if (mAllocated < mCount + 1) {
        while (mAllocated < mCount + 1) {
            if (mAllocated == 0) {
                mAllocated = 4;
            }
            mAllocated *= 2;
        }

        Range * rangesReplacement = new Range[mAllocated];
        for(unsigned int i = 0 ; i < rangeIndex ; i ++) {
            rangesReplacement[i] = mRanges[i];
        }
        for(unsigned int i = rangeIndex ; i < mCount ; i ++) {
            rangesReplacement[i + 1] = mRanges[i];
        }
        mCount ++;
        rangesReplacement[rangeIndex].location = 0;
        rangesReplacement[rangeIndex].length = 0;
        delete [] mRanges;
        mRanges = rangesReplacement;
    }
    else {
        if (mCount > 0) {
            for(int i = mCount - 1 ; i >= (int) rangeIndex ; i --) {
                mRanges[i + 1] = mRanges[i];
            }
        }
        mCount ++;
        mRanges[rangeIndex].location = 0;
        mRanges[rangeIndex].length = 0;
    }
}

void IndexSet::addRange(Range range)
{
    int rangeIndex = leftRangeIndexForIndex(range.location);
    addRangeIndex(rangeIndex);
    mRanges[rangeIndex] = range;

    mergeRanges(rangeIndex);
    if (rangeIndex > 0) {
        tryToMergeAdjacentRanges(rangeIndex - 1);
    }
    if (rangeIndex < mCount - 1) {
        tryToMergeAdjacentRanges(rangeIndex);
    }
}

void IndexSet::tryToMergeAdjacentRanges(unsigned int rangeIndex)
{
    if (RangeRightBound(mRanges[rangeIndex]) == UINT64_MAX)
        return;

    if (RangeRightBound(mRanges[rangeIndex]) + 1 != mRanges[rangeIndex + 1].location) {
        return;
    }

    uint64_t right = RangeRightBound(mRanges[rangeIndex + 1]);
    removeRangeIndex(rangeIndex + 1, 1);
    mRanges[rangeIndex].length = right - mRanges[rangeIndex].location;
}

void IndexSet::mergeRanges(unsigned int rangeIndex)
{
    int right = rangeIndex;

    for(int i = rangeIndex ; i < mCount ; i ++) {
        if (RangeHasIntersection(mRanges[rangeIndex], mRanges[i])) {
            right = i;
        }
        else {
            break;
        }
    }

    if (right == rangeIndex)
        return;

    IndexSet * indexSet = RangeUnion(mRanges[rangeIndex], mRanges[right]);
    MCAssert(indexSet->rangesCount() > 0);
    Range range = indexSet->allRanges()[0];
    removeRangeIndex(rangeIndex + 1, right - rangeIndex);
    mRanges[rangeIndex] = range;
}

void IndexSet::addIndex(uint64_t idx)
{
    addRange(RangeMake(idx, 0));
}

void IndexSet::removeRangeIndex(unsigned int rangeIndex, unsigned int count)
{
    for(unsigned int i = rangeIndex + count ; i < mCount ; i ++) {
        mRanges[i - count] = mRanges[i];
    }
    mCount -= count;
}

void IndexSet::removeRange(Range range)
{
    int left = -1;
    int right = -1;
    int leftRangeIndex = leftRangeIndexForIndex(range.location);
    for(int i = leftRangeIndex ; i < mCount ; i ++) {
        if (RangeHasIntersection(mRanges[i], range)) {
            IndexSet * indexSet = RangeRemoveRange(mRanges[i], range);
            if (indexSet->rangesCount() == 0) {
                if (left == -1) {
                    left = i;
                }
                right = i;
                mRanges[i] = RangeEmpty;
            }
            else if (indexSet->rangesCount() == 1) {
                mRanges[i] = indexSet->allRanges()[0];
            }
            else {
                MCAssert(indexSet->rangesCount() == 2);
                addRangeIndex(i);
                mRanges[i] = indexSet->allRanges()[0];
                mRanges[i + 1] = indexSet->allRanges()[1];
            }
        }
        else {
            break;
        }
    }

    if (left != -1) {
        removeRangeIndex(left, right - left + 1);
    }
}

void IndexSet::removeIndex(uint64_t idx)
{
    removeRange(RangeMake(idx, 0));
}

bool IndexSet::containsIndex(uint64_t idx)
{
    int rangeIndex = rangeIndexForIndex(idx);
    return rangeIndex != -1;
}

unsigned int IndexSet::rangesCount()
{
    return mCount;
}

Range * IndexSet::allRanges()
{
    return mRanges;
}

void IndexSet::removeAllIndexes()
{
    if (mRanges != NULL) {
        delete[] mRanges;
        mRanges = NULL;
    }
    mAllocated = 0;
    mCount = 0;
}

String * IndexSet::description()
{
    String * result = String::string();
    for(unsigned int i = 0 ; i < mCount ; i ++) {
        if (i != 0) {
            result->appendUTF8Format(",");
        }
        if (mRanges[i].length == 0) {
            result->appendUTF8Format("%llu",
                                     (unsigned long long) mRanges[i].location);
        }
        else {
            result->appendUTF8Format("%llu-%llu",
                                     (unsigned long long) mRanges[i].location,
                                     (unsigned long long) (mRanges[i].location + mRanges[i].length));
        }
    }
    return result;
}

Object * IndexSet::copy()
{
    return new IndexSet(this);
}

void IndexSet::intersectsRange(Range range)
{
    uint64_t right = RangeRightBound(range);
    if (right == UINT64_MAX) {
        removeRange(RangeMake(0, range.location - 1));
    }
    else {
        removeRange(RangeMake(0, range.location - 1));
        removeRange(RangeMake(right, UINT64_MAX));
    }
}

HashMap * IndexSet::serializable()
{
    HashMap * result = Object::serializable();
    Array * ranges = Array::array();
    for(unsigned int i = 0 ; i < mCount ; i ++) {
        ranges->addObject(RangeToString(mRanges[i]));
    }
    result->setObjectForKey(MCSTR("ranges"), ranges);
    return result;
}

void IndexSet::importSerializable(HashMap * serializable)
{
    Array * ranges = (Array *) serializable->objectForKey(MCSTR("ranges"));
    for(unsigned int i = 0 ; i < ranges->count() ; i ++) {
        String * rangeStr = (String *) ranges->objectAtIndex(i);
        addRange(RangeFromString(rangeStr));
    }
}

void IndexSet::addIndexSet(IndexSet * indexSet)
{
    for(unsigned int i = 0 ; i < indexSet->count() ; i ++) {
        addRange(indexSet->allRanges()[i]);
    }
}

void IndexSet::removeIndexSet(IndexSet * indexSet)
{
    for(unsigned int i = 0 ; i < indexSet->count() ; i ++) {
        removeRange(indexSet->allRanges()[i]);
    }
}

void IndexSet::intersectsIndexSet(IndexSet * indexSet)
{
    IndexSet * result = new IndexSet();
    for(unsigned int i = 0 ; i < indexSet->count() ; i ++) {
        IndexSet * rangeIntersect = (IndexSet *) copy();
        rangeIntersect->intersectsRange(indexSet->allRanges()[i]);
        result->addIndexSet(rangeIntersect);
        rangeIntersect->release();
    }
    removeAllIndexes();
    addIndexSet(result);
    result->release();
}

static void * createObject()
{
    return new IndexSet();
}

__attribute__((constructor))
static void initialize()
{
    Object::registerObjectConstructor("mailcore::IndexSet", &createObject);
}
<commit_msg>Fixed some IndexSet operations<commit_after>//
//  MCIndexSet.cpp
//  mailcore2
//
//  Created by DINH Viêt Hoà on 3/4/13.
//  Copyright (c) 2013 MailCore. All rights reserved.
//

#include "MCIndexSet.h"

#include "MCString.h"
#include "MCAssert.h"
#include "MCRange.h"
#include "MCLog.h"
#include "MCArray.h"
#include "MCHashMap.h"
#include "MCUtils.h"

using namespace mailcore;

void IndexSet::init()
{
    mRanges = NULL;
    mAllocated = 0;
    mCount = 0;
}

IndexSet::IndexSet()
{
    init();
}

IndexSet::IndexSet(IndexSet * o)
{
    init();
    mRanges = new Range[o->mAllocated];
    for(unsigned int i = 0 ; i < o->mCount ; i ++) {
        mRanges[i] = o->mRanges[i];
    }
    mAllocated = o->mAllocated;
    mCount = o->mCount;
}

IndexSet::~IndexSet()
{
    removeAllIndexes();
}

IndexSet * IndexSet::indexSet()
{
    IndexSet * result = new IndexSet();
    result->autorelease();
    return result;
}

IndexSet * IndexSet::indexSetWithRange(Range range)
{
    IndexSet * result = new IndexSet();
    result->autorelease();
    result->addRange(range);
    return result;
}

IndexSet * IndexSet::indexSetWithIndex(uint64_t idx)
{
    IndexSet * result = new IndexSet();
    result->autorelease();
    result->addIndex(idx);
    return result;
}

unsigned int IndexSet::count()
{
    unsigned int total = 0;
    for(unsigned int i = 0 ; i < mCount ; i ++) {
        total += mRanges[i].length + 1;
    }
    return total;
}

int IndexSet::rangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right)
{
    unsigned int middle = (left + right) / 2;

    Range middleRange = mRanges[middle];

    if (left == right) {
        if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) {
            return left;
        }
        return -1;
    }

    if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) {
        return middle;
    }
    if (idx < middleRange.location) {
        return rangeIndexForIndexWithBounds(idx, left, middle);
    }
    else {
        return rangeIndexForIndexWithBounds(idx, middle + 1, right);
    }
}

int IndexSet::rangeIndexForIndex(uint64_t idx)
{
    if (mCount == 0)
        return -1;

    return rangeIndexForIndexWithBounds(idx, 0, mCount - 1);
}

int IndexSet::rightRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right)
{
    unsigned int middle = (left + right) / 2;

    Range middleRange = mRanges[middle];

    if (left == right) {
        if (idx > middleRange.location + middleRange.length) {
            return left + 1;
        }
        else {
            return left;
        }
    }

    if (idx < middleRange.location + middleRange.length) {
        return rightRangeIndexForIndexWithBounds(idx, left, middle);
    }
    else {
        return rightRangeIndexForIndexWithBounds(idx, middle + 1, right);
    }
}

int IndexSet::rightRangeIndexForIndex(uint64_t idx)
{
    if (mCount == 0)
        return 0;

    return rightRangeIndexForIndexWithBounds(idx, 0, mCount - 1);
}

int IndexSet::leftRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right)
{
    unsigned int middle = (left + right) / 2;

    Range middleRange = mRanges[middle];

    if (left == right) {
        if (idx <= middleRange.location) {
            return left;
        }
        else {
            return left + 1;
        }
    }

    if (idx <= middleRange.location) {
        return leftRangeIndexForIndexWithBounds(idx, left, middle);
    }
    else {
        return leftRangeIndexForIndexWithBounds(idx, middle + 1, right);
    }
}

int IndexSet::leftRangeIndexForIndex(uint64_t idx)
{
    if (mCount == 0)
        return 0;

    return leftRangeIndexForIndexWithBounds(idx, 0, mCount - 1);
}

void IndexSet::addRangeIndex(unsigned int rangeIndex)
{
    if (mAllocated < mCount + 1) {
        while (mAllocated < mCount + 1) {
            if (mAllocated == 0) {
                mAllocated = 4;
            }
            mAllocated *= 2;
        }

        Range * rangesReplacement = new Range[mAllocated];
        for(unsigned int i = 0 ; i < rangeIndex ; i ++) {
            rangesReplacement[i] = mRanges[i];
        }
        for(unsigned int i = rangeIndex ; i < mCount ; i ++) {
            rangesReplacement[i + 1] = mRanges[i];
        }
        mCount ++;
        rangesReplacement[rangeIndex].location = 0;
        rangesReplacement[rangeIndex].length = 0;
        delete [] mRanges;
        mRanges = rangesReplacement;
    }
    else {
        if (mCount > 0) {
            for(int i = mCount - 1 ; i >= (int) rangeIndex ; i --) {
                mRanges[i + 1] = mRanges[i];
            }
        }
        mCount ++;
        mRanges[rangeIndex].location = 0;
        mRanges[rangeIndex].length = 0;
    }
}

void IndexSet::addRange(Range range)
{
    int rangeIndex = leftRangeIndexForIndex(range.location);
    addRangeIndex(rangeIndex);
    mRanges[rangeIndex] = range;

    mergeRanges(rangeIndex);
    if (rangeIndex > 0) {
        tryToMergeAdjacentRanges(rangeIndex - 1);
    }
    if (rangeIndex < mCount - 1) {
        tryToMergeAdjacentRanges(rangeIndex);
    }
}

void IndexSet::tryToMergeAdjacentRanges(unsigned int rangeIndex)
{
    if (RangeRightBound(mRanges[rangeIndex]) == UINT64_MAX)
        return;

    if (RangeRightBound(mRanges[rangeIndex]) + 1 != mRanges[rangeIndex + 1].location) {
        return;
    }

    uint64_t right = RangeRightBound(mRanges[rangeIndex + 1]);
    removeRangeIndex(rangeIndex + 1, 1);
    mRanges[rangeIndex].length = right - mRanges[rangeIndex].location;
}

void IndexSet::mergeRanges(unsigned int rangeIndex)
{
    int right = rangeIndex;

    for(int i = rangeIndex ; i < mCount ; i ++) {
        if (RangeHasIntersection(mRanges[rangeIndex], mRanges[i])) {
            right = i;
        }
        else {
            break;
        }
    }

    if (right == rangeIndex)
        return;

    IndexSet * indexSet = RangeUnion(mRanges[rangeIndex], mRanges[right]);
    MCAssert(indexSet->rangesCount() > 0);
    Range range = indexSet->allRanges()[0];
    removeRangeIndex(rangeIndex + 1, right - rangeIndex);
    mRanges[rangeIndex] = range;
}

void IndexSet::addIndex(uint64_t idx)
{
    addRange(RangeMake(idx, 0));
}

void IndexSet::removeRangeIndex(unsigned int rangeIndex, unsigned int count)
{
    for(unsigned int i = rangeIndex + count ; i < mCount ; i ++) {
        mRanges[i - count] = mRanges[i];
    }
    mCount -= count;
}

void IndexSet::removeRange(Range range)
{
    int left = -1;
    int right = -1;
    int leftRangeIndex = leftRangeIndexForIndex(range.location);
    for(int i = leftRangeIndex ; i < mCount ; i ++) {
        if (RangeHasIntersection(mRanges[i], range)) {
            IndexSet * indexSet = RangeRemoveRange(mRanges[i], range);
            if (indexSet->rangesCount() == 0) {
                if (left == -1) {
                    left = i;
                }
                right = i;
                mRanges[i] = RangeEmpty;
            }
            else if (indexSet->rangesCount() == 1) {
                mRanges[i] = indexSet->allRanges()[0];
            }
            else {
                MCAssert(indexSet->rangesCount() == 2);
                addRangeIndex(i);
                mRanges[i] = indexSet->allRanges()[0];
                mRanges[i + 1] = indexSet->allRanges()[1];
            }
        }
        else {
            break;
        }
    }

    if (left != -1) {
        removeRangeIndex(left, right - left + 1);
    }
}

void IndexSet::removeIndex(uint64_t idx)
{
    removeRange(RangeMake(idx, 0));
}

bool IndexSet::containsIndex(uint64_t idx)
{
    int rangeIndex = rangeIndexForIndex(idx);
    return rangeIndex != -1;
}

unsigned int IndexSet::rangesCount()
{
    return mCount;
}

Range * IndexSet::allRanges()
{
    return mRanges;
}

void IndexSet::removeAllIndexes()
{
    if (mRanges != NULL) {
        delete[] mRanges;
        mRanges = NULL;
    }
    mAllocated = 0;
    mCount = 0;
}

String * IndexSet::description()
{
    String * result = String::string();
    for(unsigned int i = 0 ; i < mCount ; i ++) {
        if (i != 0) {
            result->appendUTF8Format(",");
        }
        if (mRanges[i].length == 0) {
            result->appendUTF8Format("%llu",
                                     (unsigned long long) mRanges[i].location);
        }
        else {
            result->appendUTF8Format("%llu-%llu",
                                     (unsigned long long) mRanges[i].location,
                                     (unsigned long long) (mRanges[i].location + mRanges[i].length));
        }
    }
    return result;
}

Object * IndexSet::copy()
{
    return new IndexSet(this);
}

void IndexSet::intersectsRange(Range range)
{
    uint64_t right = RangeRightBound(range);
    if (right == UINT64_MAX) {
        removeRange(RangeMake(0, range.location - 1));
    }
    else {
        removeRange(RangeMake(0, range.location - 1));
        removeRange(RangeMake(right, UINT64_MAX));
    }
}

HashMap * IndexSet::serializable()
{
    HashMap * result = Object::serializable();
    Array * ranges = Array::array();
    for(unsigned int i = 0 ; i < mCount ; i ++) {
        ranges->addObject(RangeToString(mRanges[i]));
    }
    result->setObjectForKey(MCSTR("ranges"), ranges);
    return result;
}

void IndexSet::importSerializable(HashMap * serializable)
{
    Array * ranges = (Array *) serializable->objectForKey(MCSTR("ranges"));
    for(unsigned int i = 0 ; i < ranges->count() ; i ++) {
        String * rangeStr = (String *) ranges->objectAtIndex(i);
        addRange(RangeFromString(rangeStr));
    }
}

void IndexSet::addIndexSet(IndexSet * indexSet)
{
    for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) {
        addRange(indexSet->allRanges()[i]);
    }
}

void IndexSet::removeIndexSet(IndexSet * indexSet)
{
    for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) {
        removeRange(indexSet->allRanges()[i]);
    }
}

void IndexSet::intersectsIndexSet(IndexSet * indexSet)
{
    IndexSet * result = new IndexSet();
    for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) {
        IndexSet * rangeIntersect = (IndexSet *) copy();
        rangeIntersect->intersectsRange(indexSet->allRanges()[i]);
        result->addIndexSet(rangeIntersect);
        rangeIntersect->release();
    }
    removeAllIndexes();
    addIndexSet(result);
    result->release();
}

static void * createObject()
{
    return new IndexSet();
}

__attribute__((constructor))
static void initialize()
{
    Object::registerObjectConstructor("mailcore::IndexSet", &createObject);
}
<|endoftext|>


<commit_before>/**
 * @file
 * @brief Implementation of messenger
 *
 * @copyright MIT License
 */

#include "Messenger.hpp"

#include <memory>
#include <stdexcept>
#include <string>
#include <typeindex>

#include "Message.hpp"
#include "core/module/Module.hpp"
#include "core/utils/log.h"
#include "core/utils/type.h"
#include "delegates.h"

using namespace allpix;

Messenger::Messenger() = default;
#ifdef NDEBUG
Messenger::~Messenger() = default;
#else
Messenger::~Messenger() {
    assert(delegate_to_iterator_.empty());
}
#endif

// Check if the detectors match for the message and the delegate
static bool check_send(BaseMessage* message, BaseDelegate* delegate) {
    if(delegate->getDetector() != nullptr &&
       (message->getDetector() == nullptr || delegate->getDetector()->getName() != message->getDetector()->getName())) {
        return false;
    }
    return true;
}

/**
 * Messages should be bound during construction, so this function only gives useful information outside the constructor
 */
bool Messenger::hasReceiver(Module* source, const std::shared_ptr<BaseMessage>& message) {
    const BaseMessage* inst = message.get();
    std::type_index type_idx = typeid(*inst);

    // Get the name of the output message
    std::string name = source->get_configuration().get<std::string>("output");

    // Check if a normal specific listener exists
    for(auto& delegate : delegates_[type_idx][name]) {
        if(check_send(message.get(), delegate.get())) {
            return true;
        }
    }
    // Check if a normal generic listener exists
    for(auto& delegate : delegates_[type_idx]["*"]) {
        if(check_send(message.get(), delegate.get())) {
            return true;
        }
    }
    // Check if a base message specific listener exists
    for(auto& delegate : delegates_[typeid(BaseMessage)][name]) {
        if(check_send(message.get(), delegate.get())) {
            return true;
        }
    }
    // Check if a base message generic listener exists
    for(auto& delegate : delegates_[typeid(BaseMessage)]["*"]) {
        if(check_send(message.get(), delegate.get())) {
            return true;
        }
    }

    return false;
}

/**
 * Send messages to all specific listeners and also to all generic listeners (listening to all incoming messages)
 */
void Messenger::dispatch_message(Module* source, const std::shared_ptr<BaseMessage>& message, std::string name) {
    // Get the name of the output message
    if(name == "-") {
        name = source->get_configuration().get<std::string>("output");
    }

    bool send = false;

    // Send to specific listeners
    send = dispatch_message(source, message, name, name) || send;

    // Send to generic listeners
    send = dispatch_message(source, message, name, "*") || send;
}

/**
 * Messages are only dispatched to delegates listening to the exact same type and the exact same name.
 */
bool Messenger::dispatch_message(Module* source,
                                 const std::shared_ptr<BaseMessage>& message,
                                 const std::string& name,
                                 const std::string& id) {
    bool send = false;

    // Create type identifier from the typeid
    const BaseMessage* inst = message.get();
    std::type_index type_idx = typeid(*inst);

    // Send messages only to their specific listeners
    for(auto& delegate : delegates_[type_idx][id]) {
        if(check_send(message.get(), delegate.get())) {
            LOG(TRACE) << "Sending message " << allpix::demangle(type_idx.name()) << " from " << source->getUniqueName()
                       << " to " << delegate->getUniqueName();
            delegate->process(message, name);
            send = true;
        }
    }

    // Dispatch to base message listeners
    assert(typeid(BaseMessage) != typeid(*inst));
    for(auto& delegate : delegates_[typeid(BaseMessage)][id]) {
        if(check_send(message.get(), delegate.get())) {
            LOG(TRACE) << "Sending message " << allpix::demangle(type_idx.name()) << " from " << source->getUniqueName()
                       << " to generic listener " << delegate->getUniqueName();
            delegate->process(message, name);
            send = true;
        }
    }

    return send;
}

void Messenger::add_delegate(const std::type_info& message_type, Module* module, std::unique_ptr<BaseDelegate> delegate) {
    // Register generic or specific delegate depending on flag
    std::string message_name;
    if((delegate->getFlags() & MsgFlags::IGNORE_NAME) != MsgFlags::NONE) {
        message_name = "*";
    } else {
        message_name = module->get_configuration().get<std::string>("input");
    }

    // Register delegate internally
    delegates_[std::type_index(message_type)][message_name].push_back(std::move(delegate));
    auto delegate_iter = --delegates_[std::type_index(message_type)][message_name].end();
    delegate_to_iterator_.emplace(delegate_iter->get(),
                                  std::make_tuple(std::type_index(message_type), message_name, delegate_iter));

    // Add delegate to the module itself
    module->add_delegate(this, delegate_iter->get());
}

/**
 * @throws std::out_of_range If a delegate is removed which is never registered
 */
void Messenger::remove_delegate(BaseDelegate* delegate) {
    auto iter = delegate_to_iterator_.find(delegate);
    if(iter == delegate_to_iterator_.end()) {
        throw std::out_of_range("delegate not found in listeners");
    }
    delegates_[std::get<0>(iter->second)][std::get<1>(iter->second)].erase(std::get<2>(iter->second));
    delegate_to_iterator_.erase(iter);
}
<commit_msg>Add TRACE info about dispatched messages without receiver as it can still be useful<commit_after>/**
 * @file
 * @brief Implementation of messenger
 *
 * @copyright MIT License
 */

#include "Messenger.hpp"

#include <memory>
#include <stdexcept>
#include <string>
#include <typeindex>

#include "Message.hpp"
#include "core/module/Module.hpp"
#include "core/utils/log.h"
#include "core/utils/type.h"
#include "delegates.h"

using namespace allpix;

Messenger::Messenger() = default;
#ifdef NDEBUG
Messenger::~Messenger() = default;
#else
Messenger::~Messenger() {
    assert(delegate_to_iterator_.empty());
}
#endif

// Check if the detectors match for the message and the delegate
static bool check_send(BaseMessage* message, BaseDelegate* delegate) {
    if(delegate->getDetector() != nullptr &&
       (message->getDetector() == nullptr || delegate->getDetector()->getName() != message->getDetector()->getName())) {
        return false;
    }
    return true;
}

/**
 * Messages should be bound during construction, so this function only gives useful information outside the constructor
 */
bool Messenger::hasReceiver(Module* source, const std::shared_ptr<BaseMessage>& message) {
    const BaseMessage* inst = message.get();
    std::type_index type_idx = typeid(*inst);

    // Get the name of the output message
    std::string name = source->get_configuration().get<std::string>("output");

    // Check if a normal specific listener exists
    for(auto& delegate : delegates_[type_idx][name]) {
        if(check_send(message.get(), delegate.get())) {
            return true;
        }
    }
    // Check if a normal generic listener exists
    for(auto& delegate : delegates_[type_idx]["*"]) {
        if(check_send(message.get(), delegate.get())) {
            return true;
        }
    }
    // Check if a base message specific listener exists
    for(auto& delegate : delegates_[typeid(BaseMessage)][name]) {
        if(check_send(message.get(), delegate.get())) {
            return true;
        }
    }
    // Check if a base message generic listener exists
    for(auto& delegate : delegates_[typeid(BaseMessage)]["*"]) {
        if(check_send(message.get(), delegate.get())) {
            return true;
        }
    }

    return false;
}

/**
 * Send messages to all specific listeners and also to all generic listeners (listening to all incoming messages)
 */
void Messenger::dispatch_message(Module* source, const std::shared_ptr<BaseMessage>& message, std::string name) {
    // Get the name of the output message
    if(name == "-") {
        name = source->get_configuration().get<std::string>("output");
    }

    bool send = false;

    // Send to specific listeners
    send = dispatch_message(source, message, name, name) || send;

    // Send to generic listeners
    send = dispatch_message(source, message, name, "*") || send;

    // Display a TRACE log message if the message is send to no receiver
    if(!send) {
        const BaseMessage* inst = message.get();
        LOG(TRACE) << "Dispatched message " << allpix::demangle(typeid(*inst).name()) << " from " << source->getUniqueName()
                   << " has no receivers!";
    }
}

/**
 * Messages are only dispatched to delegates listening to the exact same type and the exact same name.
 */
bool Messenger::dispatch_message(Module* source,
                                 const std::shared_ptr<BaseMessage>& message,
                                 const std::string& name,
                                 const std::string& id) {
    bool send = false;

    // Create type identifier from the typeid
    const BaseMessage* inst = message.get();
    std::type_index type_idx = typeid(*inst);

    // Send messages only to their specific listeners
    for(auto& delegate : delegates_[type_idx][id]) {
        if(check_send(message.get(), delegate.get())) {
            LOG(TRACE) << "Sending message " << allpix::demangle(type_idx.name()) << " from " << source->getUniqueName()
                       << " to " << delegate->getUniqueName();
            delegate->process(message, name);
            send = true;
        }
    }

    // Dispatch to base message listeners
    assert(typeid(BaseMessage) != typeid(*inst));
    for(auto& delegate : delegates_[typeid(BaseMessage)][id]) {
        if(check_send(message.get(), delegate.get())) {
            LOG(TRACE) << "Sending message " << allpix::demangle(type_idx.name()) << " from " << source->getUniqueName()
                       << " to generic listener " << delegate->getUniqueName();
            delegate->process(message, name);
            send = true;
        }
    }

    return send;
}

void Messenger::add_delegate(const std::type_info& message_type, Module* module, std::unique_ptr<BaseDelegate> delegate) {
    // Register generic or specific delegate depending on flag
    std::string message_name;
    if((delegate->getFlags() & MsgFlags::IGNORE_NAME) != MsgFlags::NONE) {
        message_name = "*";
    } else {
        message_name = module->get_configuration().get<std::string>("input");
    }

    // Register delegate internally
    delegates_[std::type_index(message_type)][message_name].push_back(std::move(delegate));
    auto delegate_iter = --delegates_[std::type_index(message_type)][message_name].end();
    delegate_to_iterator_.emplace(delegate_iter->get(),
                                  std::make_tuple(std::type_index(message_type), message_name, delegate_iter));

    // Add delegate to the module itself
    module->add_delegate(this, delegate_iter->get());
}

/**
 * @throws std::out_of_range If a delegate is removed which is never registered
 */
void Messenger::remove_delegate(BaseDelegate* delegate) {
    auto iter = delegate_to_iterator_.find(delegate);
    if(iter == delegate_to_iterator_.end()) {
        throw std::out_of_range("delegate not found in listeners");
    }
    delegates_[std::get<0>(iter->second)][std::get<1>(iter->second)].erase(std::get<2>(iter->second));
    delegate_to_iterator_.erase(iter);
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/idle_timer.h"

// We may not want to port idle_timer to Linux, but we have implemented it
// anyway.  Define this to 1 to enable the Linux idle timer and then add the
// libs that need to be linked (Xss).
#define ENABLE_XSS_SUPPORT 0

#if defined(OS_MACOSX)
#include <ApplicationServices/ApplicationServices.h>
#endif

#if defined(OS_LINUX) && ENABLE_XSS_SUPPORT
// We may not want to port idle_timer to Linux, but we have implemented it
// anyway.  Remove the 0 above if we want it.
#include <gdk/gdkx.h>
#include <X11/extensions/scrnsaver.h>
#include "base/lazy_instance.h"
#include "base/thread_local.h"
#endif

#include "base/message_loop.h"
#include "base/time.h"

namespace base {

#if defined(OS_WIN)
bool OSIdleTimeSource(int32 *milliseconds_interval_since_last_event) {
  LASTINPUTINFO lastInputInfo;
  lastInputInfo.cbSize = sizeof(lastInputInfo);
  if (GetLastInputInfo(&lastInputInfo) == 0) {
    return false;
  }
  int32 last_input_time = lastInputInfo.dwTime;

  // Note: On Windows GetLastInputInfo returns a 32bit value which rolls over
  // ~49days.
  int32 current_time = GetTickCount();
  int32 delta = current_time - last_input_time;
  // delta will go negative if we've been idle for 2GB of ticks.
  if (delta < 0)
    delta = -delta;
  *milliseconds_interval_since_last_event = delta;
  return true;
}
#elif defined(OS_MACOSX)
bool OSIdleTimeSource(int32 *milliseconds_interval_since_last_event) {
  *milliseconds_interval_since_last_event =
      CGEventSourceSecondsSinceLastEventType(
          kCGEventSourceStateCombinedSessionState,
          kCGAnyInputEventType) * 1000.0;
  return true;
}
#elif defined(OS_LINUX) && ENABLE_XSS_SUPPORT
class IdleState {
 public:
  IdleState() {
    int event_base, error_base;
    have_idle_info_ = XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base,
                                                 &error_base);
    if (have_idle_info_)
      *idle_info_.Get() = XScreenSaverAllocInfo();
  }

  ~IdleState() {
    if (*idle_info_.Get()) {
      XFree(*idle_info_.Get());
      idle_info_.~ThreadLocalPointer();
    }
  }

  int32 IdleTime() {
    if (have_idle_info_ && idle_info_.Get()) {
      XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
                            *idle_info_.Get());
      return (*idle_info_.Get())->idle;
    }
    return -1;
  }

 private:
  bool have_idle_info_;
  ThreadLocalPointer<XScreenSaverInfo*> idle_info_;

  DISALLOW_COPY_AND_ASSIGN(IdleState);
};

bool OSIdleTimeSource(int32* milliseconds_interval_since_last_event) {
  static LazyInstance<IdleState> state_instance(base::LINKER_INITIALIZED);
  IdleState* state = state_instance.Pointer();
  int32 idle_time = state->IdleTime();
  if (0 < idle_time) {
    *milliseconds_interval_since_last_event = idle_time;
    return true;
  }
  return false;
}
#endif

IdleTimer::IdleTimer(TimeDelta idle_time, bool repeat)
    : idle_interval_(idle_time),
      repeat_(repeat),
      idle_time_source_(OSIdleTimeSource) {
  DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type()) <<
      "Requires a thread that processes Windows UI events";
}

IdleTimer::~IdleTimer() {
  Stop();
}

void IdleTimer::Start() {
  StartTimer();
}

void IdleTimer::Stop() {
  timer_.Stop();
}

void IdleTimer::Run() {
  // Verify we can fire the idle timer.
  if (TimeUntilIdle().InMilliseconds() <= 0) {
    OnIdle();
    last_time_fired_ = Time::Now();
  }
  Stop();
  StartTimer();  // Restart the timer for next run.
}

void IdleTimer::StartTimer() {
  DCHECK(!timer_.IsRunning());
  TimeDelta delay = TimeUntilIdle();
  if (delay.InMilliseconds() < 0)
    delay = TimeDelta();
  timer_.Start(delay, this, &IdleTimer::Run);
}

TimeDelta IdleTimer::CurrentIdleTime() {
  int32 interval = 0;
  if (idle_time_source_(&interval)) {
    return TimeDelta::FromMilliseconds(interval);
  }
  NOTREACHED();
  return TimeDelta::FromMilliseconds(0);
}

TimeDelta IdleTimer::TimeUntilIdle() {
  TimeDelta time_since_last_fire = Time::Now() - last_time_fired_;
  TimeDelta current_idle_time = CurrentIdleTime();
  if (current_idle_time > time_since_last_fire) {
    if (repeat_)
      return idle_interval_ - time_since_last_fire;
    return idle_interval_;
  }
  return idle_interval_ - current_idle_time;
}

}  // namespace base
<commit_msg><commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/idle_timer.h"

// We may not want to port idle_timer to Linux, but we have implemented it
// anyway.  Define this to 1 to enable the Linux idle timer and then add the
// libs that need to be linked (Xss).
#define ENABLE_XSS_SUPPORT 0

#if defined(OS_MACOSX)
#include <ApplicationServices/ApplicationServices.h>
#endif

#if defined(OS_LINUX) && ENABLE_XSS_SUPPORT
// We may not want to port idle_timer to Linux, but we have implemented it
// anyway.  Remove the 0 above if we want it.
#include <gdk/gdkx.h>
#include <X11/extensions/scrnsaver.h>
#include "base/lazy_instance.h"
#include "base/thread_local.h"
#endif

#include "base/message_loop.h"
#include "base/time.h"

namespace base {

#if defined(OS_WIN)
bool OSIdleTimeSource(int32 *milliseconds_interval_since_last_event) {
  LASTINPUTINFO lastInputInfo;
  lastInputInfo.cbSize = sizeof(lastInputInfo);
  if (GetLastInputInfo(&lastInputInfo) == 0) {
    return false;
  }
  int32 last_input_time = lastInputInfo.dwTime;

  // Note: On Windows GetLastInputInfo returns a 32bit value which rolls over
  // ~49days.
  int32 current_time = GetTickCount();
  int32 delta = current_time - last_input_time;
  // delta will go negative if we've been idle for 2GB of ticks.
  if (delta < 0)
    delta = -delta;
  *milliseconds_interval_since_last_event = delta;
  return true;
}
#elif defined(OS_MACOSX)
bool OSIdleTimeSource(int32 *milliseconds_interval_since_last_event) {
  *milliseconds_interval_since_last_event =
      CGEventSourceSecondsSinceLastEventType(
          kCGEventSourceStateCombinedSessionState,
          kCGAnyInputEventType) * 1000.0;
  return true;
}
#elif defined(OS_LINUX) && ENABLE_XSS_SUPPORT
class IdleState {
 public:
  IdleState() {
    int event_base, error_base;
    have_idle_info_ = XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base,
                                                 &error_base);
    if (have_idle_info_)
      idle_info_.Set(XScreenSaverAllocInfo());
  }

  ~IdleState() {
    if (idle_info_.Get()) {
      XFree(idle_info_.Get());
      idle_info_.~ThreadLocalPointer();
    }
  }

  int32 IdleTime() {
    if (have_idle_info_ && idle_info_.Get()) {
      XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
                            idle_info_.Get());
      return idle_info_.Get()->idle;
    }
    return -1;
  }

 private:
  bool have_idle_info_;
  ThreadLocalPointer<XScreenSaverInfo> idle_info_;

  DISALLOW_COPY_AND_ASSIGN(IdleState);
};

bool OSIdleTimeSource(int32* milliseconds_interval_since_last_event) {
  static LazyInstance<IdleState> state_instance(base::LINKER_INITIALIZED);
  IdleState* state = state_instance.Pointer();
  int32 idle_time = state->IdleTime();
  if (0 < idle_time) {
    *milliseconds_interval_since_last_event = idle_time;
    return true;
  }
  return false;
}
#endif

IdleTimer::IdleTimer(TimeDelta idle_time, bool repeat)
    : idle_interval_(idle_time),
      repeat_(repeat),
      idle_time_source_(OSIdleTimeSource) {
  DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type()) <<
      "Requires a thread that processes Windows UI events";
}

IdleTimer::~IdleTimer() {
  Stop();
}

void IdleTimer::Start() {
  StartTimer();
}

void IdleTimer::Stop() {
  timer_.Stop();
}

void IdleTimer::Run() {
  // Verify we can fire the idle timer.
  if (TimeUntilIdle().InMilliseconds() <= 0) {
    OnIdle();
    last_time_fired_ = Time::Now();
  }
  Stop();
  StartTimer();  // Restart the timer for next run.
}

void IdleTimer::StartTimer() {
  DCHECK(!timer_.IsRunning());
  TimeDelta delay = TimeUntilIdle();
  if (delay.InMilliseconds() < 0)
    delay = TimeDelta();
  timer_.Start(delay, this, &IdleTimer::Run);
}

TimeDelta IdleTimer::CurrentIdleTime() {
  int32 interval = 0;
  if (idle_time_source_(&interval)) {
    return TimeDelta::FromMilliseconds(interval);
  }
  NOTREACHED();
  return TimeDelta::FromMilliseconds(0);
}

TimeDelta IdleTimer::TimeUntilIdle() {
  TimeDelta time_since_last_fire = Time::Now() - last_time_fired_;
  TimeDelta current_idle_time = CurrentIdleTime();
  if (current_idle_time > time_since_last_fire) {
    if (repeat_)
      return idle_interval_ - time_since_last_fire;
    return idle_interval_;
  }
  return idle_interval_ - current_idle_time;
}

}  // namespace base
<|endoftext|>


<commit_before>#include "lcio.h"
#include <stdio.h>

#include "IO/LCReader.h"
#include "IMPL/LCTOOLS.h"
#include "EVENT/LCRunHeader.h"

#include "EVENT/SimCalorimeterHit.h"
#include "EVENT/CalorimeterHit.h"
#include "EVENT/RawCalorimeterHit.h"
// #include "EVENT/SimTrackerHit.h"

#include "UTIL/CellIDDecoder.h"

#include <cstdlib>

using namespace std ;
using namespace lcio ;

/** dump the given event to screen
 */

int main(int argc, char** argv ){

  char* FILEN ;
  int runNumber=0 ;
  int evtNumber=0 ;
  int nthEvent=1 ;

  // read file name from command line (only argument)
  if( argc < 3 ) {

    cout << " usage: dumpevent filename runNum evtNum " << endl ;
    cout << "    or: dumpevent filename n      " << endl ;
    cout << "  where the first dumps the event with the specified run and event number" << endl ;
    cout << "  and the second simply dumps the n-th event in the file" << endl ;

    exit(1) ;
  }

  FILEN = argv[1] ;

  bool dumpNthEvent( argc == 3 ) ;

  if( dumpNthEvent ) {

    nthEvent  = atoi( argv[2] ) ;

    if( nthEvent < 1 ) {

      cout << " usage: dumpevent filename n   -   whith  n > 0 !  " << endl ;

      exit(1) ;
    }

  }else{

    runNumber = atoi( argv[2] ) ;
    evtNumber = atoi( argv[3] ) ;
  }

  // set the default encoding for cellid's according to the old Mokka convention
  CellIDDecoder<SimCalorimeterHit>::setDefaultEncoding("M:3,S-1:3,I:9,J:9,K-1:6") ;
  CellIDDecoder<CalorimeterHit>::setDefaultEncoding("M:3,S-1:3,I:9,J:9,K-1:6") ;
  CellIDDecoder<RawCalorimeterHit>::setDefaultEncoding("M:3,S-1:3,I:9,J:9,K-1:6") ;

  LCReader* lcReader ;
  if ( getenv ("LCIO_DIRECT_ACCESS") !=0  )
    lcReader = LCFactory::getInstance()->createLCReader(LCReader::directAccess) ;
  else
    lcReader = LCFactory::getInstance()->createLCReader() ;

  LCEvent* evt(0) ;

  try{

     lcReader->open( FILEN ) ;

     if( dumpNthEvent ) {

       if( nthEvent > 1 )
	 lcReader->skipNEvents(  nthEvent - 1 ) ;

       evt = lcReader->readNextEvent() ;

     }else{

       evt = lcReader->readEvent(runNumber,  evtNumber) ;
     }

     //   } catch( EndOfDataException& e) {
     //     cout << " couldn't find event " << evtNumber << " - run " << runNumber
     // 	 << " in file " << FILEN << endl ;
     //     exit(1) ;

     if( !evt  ){

       if(dumpNthEvent){

	 cout << " less than " << nthEvent << "  events in  file " << FILEN << endl ;

       }else{

	 cout << " couldn't find event " << evtNumber << " - run " << runNumber
	      << " in file " << FILEN << endl ;
       }

       exit(1) ;
     }

     LCTOOLS::dumpEventDetailed( evt ) ;

     lcReader->close() ;

   }
   catch( IOException& e) {
     cout << e.what() << endl ;
     exit(1) ;
   }

//    catch( Exception& e) {
//      cout << e.what() << endl ;
//      exit(1) ;
//    }
   return 0 ;
}

<commit_msg>switch to direct access automatically when evtnum and runnum specified<commit_after>#include "lcio.h"
#include <stdio.h>

#include "IO/LCReader.h"
#include "IMPL/LCTOOLS.h"
#include "EVENT/LCRunHeader.h"

#include "EVENT/SimCalorimeterHit.h"
#include "EVENT/CalorimeterHit.h"
#include "EVENT/RawCalorimeterHit.h"
// #include "EVENT/SimTrackerHit.h"

#include "UTIL/CellIDDecoder.h"

#include <cstdlib>

using namespace std ;
using namespace lcio ;

/** dump the given event to screen
 */

int main(int argc, char** argv ){

  char* FILEN ;
  int runNumber=0 ;
  int evtNumber=0 ;
  int nthEvent=1 ;

  // read file name from command line (only argument)
  if( argc < 3 ) {

    cout << " usage: dumpevent filename runNum evtNum " << endl ;
    cout << "    or: dumpevent filename n      " << endl ;
    cout << "  where the first dumps the event with the specified run and event number" << endl ;
    cout << "  and the second simply dumps the n-th event in the file" << endl ;

    exit(1) ;
  }

  FILEN = argv[1] ;

  bool dumpNthEvent( argc == 3 ) ;

  if( dumpNthEvent ) {

    nthEvent  = atoi( argv[2] ) ;

    if( nthEvent < 1 ) {

      cout << " usage: dumpevent filename n   -   whith  n > 0 !  " << endl ;

      exit(1) ;
    }

  }else{

    runNumber = atoi( argv[2] ) ;
    evtNumber = atoi( argv[3] ) ;
  }

  // set the default encoding for cellid's according to the old Mokka convention
  CellIDDecoder<SimCalorimeterHit>::setDefaultEncoding("M:3,S-1:3,I:9,J:9,K-1:6") ;
  CellIDDecoder<CalorimeterHit>::setDefaultEncoding("M:3,S-1:3,I:9,J:9,K-1:6") ;
  CellIDDecoder<RawCalorimeterHit>::setDefaultEncoding("M:3,S-1:3,I:9,J:9,K-1:6") ;

  LCReader* lcReader ;
  if( dumpNthEvent )
    lcReader = LCFactory::getInstance()->createLCReader() ;
  else
    lcReader = LCFactory::getInstance()->createLCReader(LCReader::directAccess) ;

  LCEvent* evt(0) ;

  try{

     lcReader->open( FILEN ) ;

     if( dumpNthEvent ) {

       if( nthEvent > 1 )
	 lcReader->skipNEvents(  nthEvent - 1 ) ;

       evt = lcReader->readNextEvent() ;

     }else{

       evt = lcReader->readEvent(runNumber,  evtNumber) ;
     }

     //   } catch( EndOfDataException& e) {
     //     cout << " couldn't find event " << evtNumber << " - run " << runNumber
     // 	 << " in file " << FILEN << endl ;
     //     exit(1) ;

     if( !evt  ){

       if(dumpNthEvent){

	 cout << " less than " << nthEvent << "  events in  file " << FILEN << endl ;

       }else{

	 cout << " couldn't find event " << evtNumber << " - run " << runNumber
	      << " in file " << FILEN << endl ;
       }

       exit(1) ;
     }

     LCTOOLS::dumpEventDetailed( evt ) ;

     lcReader->close() ;

   }
   catch( IOException& e) {
     cout << e.what() << endl ;
     exit(1) ;
   }

//    catch( Exception& e) {
//      cout << e.what() << endl ;
//      exit(1) ;
//    }
   return 0 ;
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SVX_POSTDLG_HXX
#define _SVX_POSTDLG_HXX

// include ---------------------------------------------------------------

#include <vcl/group.hxx>
#include <vcl/button.hxx>
#include <vcl/edit.hxx>
#include <svtools/stdctrl.hxx>
#include <sfx2/basedlgs.hxx>
#include <svtools/svmedit.hxx>

// class SvxPostItDialog -------------------------------------------------
/*
    {k:\svx\prototyp\dialog\memo.bmp}

    [Description]
    In this dialog a note can be created or edited. If the
    application holds a list of notes, it can be iterated
    over this list with links.

    [Items]
    <SvxPostitAuthorItem><SID_ATTR_POSTIT_AUTHOR>
    <SvxPostitDateItem><SID_ATTR_POSTIT_DATE>
    <SvxPostitTextItem><SID_ATTR_POSTIT_TEXT>
*/

class SvxPostItDialog : public SfxModalDialog
{
public:
    SvxPostItDialog( Window* pParent, const SfxItemSet& rCoreSet,
                     sal_Bool bPrevNext = sal_False, sal_Bool bRedline = sal_False );
    ~SvxPostItDialog();

    static sal_uInt16*      GetRanges();
    const SfxItemSet*   GetOutputItemSet() const { return pOutSet; }

    Link                GetPrevHdl() const { return aPrevHdlLink; }
    void                SetPrevHdl( const Link& rLink )
                            { aPrevHdlLink = rLink; }
    Link                GetNextHdl() const { return aNextHdlLink; }
    void                SetNextHdl( const Link& rLink )
                            { aNextHdlLink = rLink; }

    void                EnableTravel(sal_Bool bNext, sal_Bool bPrev);
    inline String       GetNote() { return aEditED.GetText(); }
    inline void         SetNote(const String& rTxt) { aEditED.SetText(rTxt); }

    void                ShowLastAuthor(const String& rAuthor, const String& rDate);
    inline void         DontChangeAuthor()  { aAuthorBtn.Enable(sal_False); }
    inline void         HideAuthor()        { aAuthorBtn.Hide(); }
    inline void         SetReadonlyPostIt(sal_Bool bDisable)
                            {
                                aOKBtn.Enable( !bDisable );
                                aEditED.SetReadOnly( bDisable );
                                aAuthorBtn.Enable( !bDisable );
                            }
    inline sal_Bool         IsOkEnabled() const { return aOKBtn.IsEnabled(); }

private:
    FixedLine           aPostItFL;
    FixedText           aLastEditLabelFT;
    FixedInfo           aLastEditFT;

    FixedText           aEditFT;
    MultiLineEdit       aEditED;

    FixedText           aAuthorFT;
    PushButton          aAuthorBtn;

    OKButton            aOKBtn;
    CancelButton        aCancelBtn;
    HelpButton          aHelpBtn;

    ImageButton         aPrevBtn;
    ImageButton         aNextBtn;

    const SfxItemSet&   rSet;
    SfxItemSet*         pOutSet;

    Link                aPrevHdlLink;
    Link                aNextHdlLink;

#ifdef _SVX_POSTDLG_CXX
    DECL_LINK(Stamp, void *);
    DECL_LINK(OKHdl, void *);
    DECL_LINK(PrevHdl, void *);
    DECL_LINK(NextHdl, void *);
#endif
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Hide aAuthorFT fixed text, too, when the button is hidden<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SVX_POSTDLG_HXX
#define _SVX_POSTDLG_HXX

// include ---------------------------------------------------------------

#include <vcl/group.hxx>
#include <vcl/button.hxx>
#include <vcl/edit.hxx>
#include <svtools/stdctrl.hxx>
#include <sfx2/basedlgs.hxx>
#include <svtools/svmedit.hxx>

// class SvxPostItDialog -------------------------------------------------
/*
    {k:\svx\prototyp\dialog\memo.bmp}

    [Description]
    In this dialog a note can be created or edited. If the
    application holds a list of notes, it can be iterated
    over this list with links.

    [Items]
    <SvxPostitAuthorItem><SID_ATTR_POSTIT_AUTHOR>
    <SvxPostitDateItem><SID_ATTR_POSTIT_DATE>
    <SvxPostitTextItem><SID_ATTR_POSTIT_TEXT>
*/

class SvxPostItDialog : public SfxModalDialog
{
public:
    SvxPostItDialog( Window* pParent, const SfxItemSet& rCoreSet,
                     sal_Bool bPrevNext = sal_False, sal_Bool bRedline = sal_False );
    ~SvxPostItDialog();

    static sal_uInt16*      GetRanges();
    const SfxItemSet*   GetOutputItemSet() const { return pOutSet; }

    Link                GetPrevHdl() const { return aPrevHdlLink; }
    void                SetPrevHdl( const Link& rLink )
                            { aPrevHdlLink = rLink; }
    Link                GetNextHdl() const { return aNextHdlLink; }
    void                SetNextHdl( const Link& rLink )
                            { aNextHdlLink = rLink; }

    void                EnableTravel(sal_Bool bNext, sal_Bool bPrev);
    inline String       GetNote() { return aEditED.GetText(); }
    inline void         SetNote(const String& rTxt) { aEditED.SetText(rTxt); }

    void                ShowLastAuthor(const String& rAuthor, const String& rDate);
    inline void         DontChangeAuthor()  { aAuthorBtn.Enable(sal_False); }
    inline void         HideAuthor()        { aAuthorFT.Hide(); aAuthorBtn.Hide(); }
    inline void         SetReadonlyPostIt(sal_Bool bDisable)
                            {
                                aOKBtn.Enable( !bDisable );
                                aEditED.SetReadOnly( bDisable );
                                aAuthorBtn.Enable( !bDisable );
                            }
    inline sal_Bool         IsOkEnabled() const { return aOKBtn.IsEnabled(); }

private:
    FixedLine           aPostItFL;
    FixedText           aLastEditLabelFT;
    FixedInfo           aLastEditFT;

    FixedText           aEditFT;
    MultiLineEdit       aEditED;

    FixedText           aAuthorFT;
    PushButton          aAuthorBtn;

    OKButton            aOKBtn;
    CancelButton        aCancelBtn;
    HelpButton          aHelpBtn;

    ImageButton         aPrevBtn;
    ImageButton         aNextBtn;

    const SfxItemSet&   rSet;
    SfxItemSet*         pOutSet;

    Link                aPrevHdlLink;
    Link                aNextHdlLink;

#ifdef _SVX_POSTDLG_CXX
    DECL_LINK(Stamp, void *);
    DECL_LINK(OKHdl, void *);
    DECL_LINK(PrevHdl, void *);
    DECL_LINK(NextHdl, void *);
#endif
};

#endif

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


<commit_before>#include "../../../Generator/Generator.h"
#include "../../../Node/Node.h"
#include "../../../ParseResult/ParseResult.h"
#include "../../../Element/Function/Function.h"
#include "../Inst/Inst.h"
#include "../../../llvm_Function.h"

namespace dale
{
namespace Form
{
namespace Proc
{
namespace Setf
{
bool parse(Generator *gen,
           Element::Function *fn,
           llvm::BasicBlock *block,
           Node *node,
           bool get_address,
           bool prefixed_with_core,
           ParseResult *pr)
{
    Context *ctx = gen->ctx;

    assert(node->list && "parseSetf must receive a list!");

    symlist *lst = node->list;

    if (!ctx->er->assertArgNums("setf", node, 2, 2)) {
        return false;
    }

    /* Used to use getAddress for the first argument, but now setf
     * always takes a pointer as its first argument, to facilitate
     * overloading etc. */

    ParseResult pr_variable;
    bool res =
        Form::Proc::Inst::parse(gen, fn, block, (*lst)[1], false,
                                    false, NULL,
                                    &pr_variable);

    if (!res) {
        return false;
    }

    /* Make sure that the first argument is a pointer. */

    if (!pr_variable.type->points_to) {
        Error *e = new Error(
            ErrorInst::Generator::IncorrectArgType,
            (*lst)[1],
            "setf", "a pointer", "1", "a value"
        );
        ctx->er->addError(e);
        return false;
    }

    /* Can't modify const variables. */

    if (pr_variable.type->points_to->is_const) {
        Error *e = new Error(
            ErrorInst::Generator::CannotModifyConstVariable,
            node
        );
        ctx->er->addError(e);
        return false;
    }

    Node *val_node = (*lst)[2];
    val_node = gen->parseOptionalMacroCall(val_node);
    if (!val_node) {
        return false;
    }

    llvm::IRBuilder<> builder(pr_variable.block);
    ParseResult pr_value;
    Element::Variable *var_value = NULL;
    std::vector<Node *> *lst = val_node->list;

    /* If the value is a variable, or a variable dereference, load the
     * underlying value directly, to shortcut setf-copy for types that
     * define it. */

    if (val_node->is_token
            && (var_value = ctx->getVariable(
                    val_node->token->str_value.c_str()))) {
        pr_value.value = var_value->value;
        pr_value.type  = ctx->tr->getPointerType(var_value->type);
        pr_value.do_not_destruct = 1;
        pr_value.block = pr_variable.block;
    } else if (val_node->is_list
                && (lst->size() == 2)
                && (lst->at(0)->is_token)
                && (!lst->at(0)->token->str_value.compare("@"))
                && (lst->at(1)->is_token)
                && (var_value = ctx->getVariable(
                        lst->at(1)->token->str_value.c_str()))) {
        pr_value.value = builder.CreateLoad(var_value->value);
        pr_value.type  = var_value->type;
        pr_value.do_not_destruct = 1;
        pr_value.block = pr_variable.block;
    } else {
        res =
            Form::Proc::Inst::parse(gen,
                fn, pr_variable.block, val_node, false,
                false,
                pr_variable.type->points_to,
                &pr_value
            );

        if (!res) {
            return false;
        }
    }

    builder.SetInsertPoint(pr_value.block);

    /* If overridden setf exists, and pr_value is a value of the
     * pointee type of pr_variable, then call overridden setf
     * after allocating memory for pr_value and copying it into
     * place. */

    if (!prefixed_with_core
            && pr_value.type->isEqualTo(pr_variable.type->points_to)) {
        std::vector<Element::Type *> types;
        types.push_back(pr_variable.type);
        types.push_back(pr_variable.type);
        Element::Function *over_setf =
            ctx->getFunction("setf-assign", &types, NULL, 0);
        if (!over_setf) {
            goto cont1;
        }
        llvm::Value *new_ptr2 = llvm::cast<llvm::Value>(
                                    builder.CreateAlloca(
                                        ctx->toLLVMType(pr_value.type,
                                                        NULL, false,
                                                        false)
                                    )
                                );
        builder.CreateStore(pr_value.value, new_ptr2);
        std::vector<llvm::Value *> call_args;
        call_args.push_back(pr_variable.value);
        call_args.push_back(new_ptr2);
        llvm::Value *ret =
            builder.CreateCall(over_setf->llvm_function,
                               llvm::ArrayRef<llvm::Value*>(call_args));

        ParseResult temp;
        pr_variable.block = pr_value.block;
        bool mres = gen->destructIfApplicable(&pr_variable, &builder, &temp);
        if (!mres) {
            return false;
        }
        pr_value.block = temp.block;
        mres = gen->destructIfApplicable(&pr_value, &builder, &temp);
        if (!mres) {
            return false;
        }
        pr->set(temp.block, ctx->tr->type_bool, ret);
        return true;
    }

cont1:

    /* If an appropriate setf definition exists, which matches
     * the arguments exactly, then use it. */

    if (!prefixed_with_core) {
        std::vector<Element::Type *> types;
        types.push_back(pr_variable.type);
        types.push_back(pr_value.type);
        Element::Function *over_setf =
            ctx->getFunction("setf-assign", &types, NULL, 0);
        if (!over_setf) {
            goto cont2;
        }
        std::vector<llvm::Value *> call_args;
        call_args.push_back(pr_variable.value);
        call_args.push_back(pr_value.value);
        llvm::Value *ret =
            builder.CreateCall(over_setf->llvm_function,
                               llvm::ArrayRef<llvm::Value*>(call_args));

        ParseResult temp;
        pr_variable.block = pr_value.block;
        bool mres = gen->destructIfApplicable(&pr_variable, &builder, &temp);
        if (!mres) {
            return false;
        }
        pr_value.block = temp.block;
        mres = gen->destructIfApplicable(&pr_value, &builder, &temp);
        if (!mres) {
            return false;
        }

        pr->set(temp.block, ctx->tr->type_bool, ret);
        return true;
    }

cont2:

    /* var_value is only present to support the overridden set
     * operations: if this point is reached, then fall back to the
     * standard form-processing logic. */

    if (var_value) {
        res =
            Form::Proc::Inst::parse(gen,
                fn, pr_value.block, val_node, false,
                false,
                pr_variable.type->points_to,
                &pr_value
            );

        if (!res) {
            return false;
        }
    }

    if (pr_value.type->isEqualTo(pr_variable.type->points_to)) {
        builder.CreateStore(pr_value.value, pr_variable.value);

        ParseResult temp;
        pr_variable.block = pr_value.block;
        bool mres = gen->destructIfApplicable(&pr_variable, &builder, &temp);
        if (!mres) {
            return false;
        }
        pr_value.block = temp.block;
        mres = gen->destructIfApplicable(&pr_value, &builder, &temp);
        if (!mres) {
            return false;
        }

        pr->set(temp.block, ctx->tr->type_bool,
                llvm::ConstantInt::get(
                    llvm::IntegerType::get(llvm::getGlobalContext(), 1), 1
                ));
        pr->do_not_copy_with_setf = 1;
        return true;
    }

    /* todo: it would be good to also show the setf-assign
     * candidates here, if applicable. */
    ctx->er->assertTypeEquality("setf", (*lst)[2],
                            pr_value.type,
                            pr_variable.type->points_to,
                            false);

    return false;
}
}
}
}
}
<commit_msg>bad variable name<commit_after>#include "../../../Generator/Generator.h"
#include "../../../Node/Node.h"
#include "../../../ParseResult/ParseResult.h"
#include "../../../Element/Function/Function.h"
#include "../Inst/Inst.h"
#include "../../../llvm_Function.h"

namespace dale
{
namespace Form
{
namespace Proc
{
namespace Setf
{
bool parse(Generator *gen,
           Element::Function *fn,
           llvm::BasicBlock *block,
           Node *node,
           bool get_address,
           bool prefixed_with_core,
           ParseResult *pr)
{
    Context *ctx = gen->ctx;

    assert(node->list && "parseSetf must receive a list!");

    symlist *lst = node->list;

    if (!ctx->er->assertArgNums("setf", node, 2, 2)) {
        return false;
    }

    /* Used to use getAddress for the first argument, but now setf
     * always takes a pointer as its first argument, to facilitate
     * overloading etc. */

    ParseResult pr_variable;
    bool res =
        Form::Proc::Inst::parse(gen, fn, block, (*lst)[1], false,
                                    false, NULL,
                                    &pr_variable);

    if (!res) {
        return false;
    }

    /* Make sure that the first argument is a pointer. */

    if (!pr_variable.type->points_to) {
        Error *e = new Error(
            ErrorInst::Generator::IncorrectArgType,
            (*lst)[1],
            "setf", "a pointer", "1", "a value"
        );
        ctx->er->addError(e);
        return false;
    }

    /* Can't modify const variables. */

    if (pr_variable.type->points_to->is_const) {
        Error *e = new Error(
            ErrorInst::Generator::CannotModifyConstVariable,
            node
        );
        ctx->er->addError(e);
        return false;
    }

    Node *val_node = (*lst)[2];
    val_node = gen->parseOptionalMacroCall(val_node);
    if (!val_node) {
        return false;
    }

    llvm::IRBuilder<> builder(pr_variable.block);
    ParseResult pr_value;
    Element::Variable *var_value = NULL;
    symlist *vlst = val_node->list;

    /* If the value is a variable, or a variable dereference, load the
     * underlying value directly, to shortcut setf-copy for types that
     * define it. */

    if (val_node->is_token
            && (var_value = ctx->getVariable(
                    val_node->token->str_value.c_str()))) {
        pr_value.value = var_value->value;
        pr_value.type  = ctx->tr->getPointerType(var_value->type);
        pr_value.do_not_destruct = 1;
        pr_value.block = pr_variable.block;
    } else if (val_node->is_list
                && (vlst->size() == 2)
                && (vlst->at(0)->is_token)
                && (!vlst->at(0)->token->str_value.compare("@"))
                && (vlst->at(1)->is_token)
                && (var_value = ctx->getVariable(
                        vlst->at(1)->token->str_value.c_str()))) {
        pr_value.value = builder.CreateLoad(var_value->value);
        pr_value.type  = var_value->type;
        pr_value.do_not_destruct = 1;
        pr_value.block = pr_variable.block;
    } else {
        res =
            Form::Proc::Inst::parse(gen,
                fn, pr_variable.block, val_node, false,
                false,
                pr_variable.type->points_to,
                &pr_value
            );

        if (!res) {
            return false;
        }
    }

    builder.SetInsertPoint(pr_value.block);

    /* If overridden setf exists, and pr_value is a value of the
     * pointee type of pr_variable, then call overridden setf
     * after allocating memory for pr_value and copying it into
     * place. */

    if (!prefixed_with_core
            && pr_value.type->isEqualTo(pr_variable.type->points_to)) {
        std::vector<Element::Type *> types;
        types.push_back(pr_variable.type);
        types.push_back(pr_variable.type);
        Element::Function *over_setf =
            ctx->getFunction("setf-assign", &types, NULL, 0);
        if (!over_setf) {
            goto cont1;
        }
        llvm::Value *new_ptr2 = llvm::cast<llvm::Value>(
                                    builder.CreateAlloca(
                                        ctx->toLLVMType(pr_value.type,
                                                        NULL, false,
                                                        false)
                                    )
                                );
        builder.CreateStore(pr_value.value, new_ptr2);
        std::vector<llvm::Value *> call_args;
        call_args.push_back(pr_variable.value);
        call_args.push_back(new_ptr2);
        llvm::Value *ret =
            builder.CreateCall(over_setf->llvm_function,
                               llvm::ArrayRef<llvm::Value*>(call_args));

        ParseResult temp;
        pr_variable.block = pr_value.block;
        bool mres = gen->destructIfApplicable(&pr_variable, &builder, &temp);
        if (!mres) {
            return false;
        }
        pr_value.block = temp.block;
        mres = gen->destructIfApplicable(&pr_value, &builder, &temp);
        if (!mres) {
            return false;
        }
        pr->set(temp.block, ctx->tr->type_bool, ret);
        return true;
    }

cont1:

    /* If an appropriate setf definition exists, which matches
     * the arguments exactly, then use it. */

    if (!prefixed_with_core) {
        std::vector<Element::Type *> types;
        types.push_back(pr_variable.type);
        types.push_back(pr_value.type);
        Element::Function *over_setf =
            ctx->getFunction("setf-assign", &types, NULL, 0);
        if (!over_setf) {
            goto cont2;
        }
        std::vector<llvm::Value *> call_args;
        call_args.push_back(pr_variable.value);
        call_args.push_back(pr_value.value);
        llvm::Value *ret =
            builder.CreateCall(over_setf->llvm_function,
                               llvm::ArrayRef<llvm::Value*>(call_args));

        ParseResult temp;
        pr_variable.block = pr_value.block;
        bool mres = gen->destructIfApplicable(&pr_variable, &builder, &temp);
        if (!mres) {
            return false;
        }
        pr_value.block = temp.block;
        mres = gen->destructIfApplicable(&pr_value, &builder, &temp);
        if (!mres) {
            return false;
        }

        pr->set(temp.block, ctx->tr->type_bool, ret);
        return true;
    }

cont2:

    /* var_value is only present to support the overridden set
     * operations: if this point is reached, then fall back to the
     * standard form-processing logic. */

    if (var_value) {
        res =
            Form::Proc::Inst::parse(gen,
                fn, pr_value.block, val_node, false,
                false,
                pr_variable.type->points_to,
                &pr_value
            );

        if (!res) {
            return false;
        }
    }

    if (pr_value.type->isEqualTo(pr_variable.type->points_to)) {
        builder.CreateStore(pr_value.value, pr_variable.value);

        ParseResult temp;
        pr_variable.block = pr_value.block;
        bool mres = gen->destructIfApplicable(&pr_variable, &builder, &temp);
        if (!mres) {
            return false;
        }
        pr_value.block = temp.block;
        mres = gen->destructIfApplicable(&pr_value, &builder, &temp);
        if (!mres) {
            return false;
        }

        pr->set(temp.block, ctx->tr->type_bool,
                llvm::ConstantInt::get(
                    llvm::IntegerType::get(llvm::getGlobalContext(), 1), 1
                ));
        pr->do_not_copy_with_setf = 1;
        return true;
    }

    /* todo: it would be good to also show the setf-assign
     * candidates here, if applicable. */
    ctx->er->assertTypeEquality("setf", (*lst)[2],
                            pr_value.type,
                            pr_variable.type->points_to,
                            false);

    return false;
}
}
}
}
}
<|endoftext|>


<commit_before>#include <boost/mpi.hpp>
#include <iostream>
#include <string>
#include <set>
#include <boost/serialization/string.hpp>
#include <boost/program_options.hpp>
#include "InstrumentFactories.h"
#include "Stochastic.h"
#include "Ising.h"
#include "Measurement.h"
#include "cli.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#else
#define PACKAGE_STRING "UNKNOWN"
#define PACKAGE_VERSION "UNKNOWN"
#endif

namespace mpi = boost::mpi;
namespace opt = boost::program_options;

int main(int argc, char* argv[]) {
    bool verbose = false;
    opt::options_description desc = optionsDescription();
    opt::variables_map vmap;
    opt::store(opt::parse_command_line(argc,argv,desc),vmap);
    opt::notify(vmap);

    if (vmap.count("help")) {
        std::cout << desc << "\n";
        return 1;
    }

    if(vmap.count("distribution")) {
        isingEnergyDistribution(vmap["dimension"].as<int>(),
                                vmap["clusters"].as<int>());
        exit(0);
    }

    verbose = vmap.count("verbose");

    size_t iterations = vmap["iterations"].as<size_t>();

    ReservoirFactory *rFactory = NULL;
    if ( vmap.count("ising") )  {
        if (!vmap.count("dimension")) {
            std::clog << "Option --ising requires -d\n";
            exit(1);
        }

        int dim = vmap["dimension"].as<int>();
        int clst = vmap["clusters"].as<int>();
        rFactory = new IsingReservoir::IsingFactory(dim,clst);
    } else {
        //Assume stochastic
        rFactory = new DefaultArgsReservoirFactory<StochasticReservoir>;
    }

    SystemFactory *sFactory = new BinomialSystemFactory;

    assert(rFactory);
    assert(sFactory);

    int dimension = 50;
    const double tau = vmap["tau"].as<double>();

    mpi::environment env(argc, argv);
    mpi::communicator world;
    char hostname[256];
    int requester;

    if (world.rank()==0) {
        std::string args;
        for (int k=1; k!=argc; ++k) {
            args += argv[k];
            args += " ";
        }
        printf("%s%s\n",PACKAGE_STRING,args.c_str());
        std::clog << "Running v" << PACKAGE_VERSION << " on " << world.size()
                    << " nodes." << std::endl;
        std::clog << (double)(dimension*dimension*iterations)/world.size()
                    << " simulations per node." << std::endl;
        printf("%s\n",outputHeader().c_str());
    }

    world.barrier();

    gethostname(hostname,255);
    std::clog << "Hello world from host "
                << hostname
                << " (rank "
                << world.rank()
                << ")"
                << std::endl;

    Experiment::range work;
    Experiment experiment;
    experiment.iterations = iterations;
    experiment.dimension = dimension;
    experiment.sfactory = sFactory;
    experiment.rfactory = rFactory;

    for (int k=world.rank(); k<dimension*dimension; k+=world.size()) {
        MeasurementResult result = experiment.performIteration(k);
        printf("%s\n",outputString(result).c_str());
    }

    std::clog<<"Rank "<< world.rank()<<" finished.\n";
    return 0;
}
<commit_msg>Fix a race condition with the process checkins at the beginning of the MPI run.<commit_after>#include <boost/mpi.hpp>
#include <iostream>
#include <string>
#include <set>
#include <boost/serialization/string.hpp>
#include <boost/program_options.hpp>
#include "InstrumentFactories.h"
#include "Stochastic.h"
#include "Ising.h"
#include "Measurement.h"
#include "cli.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#else
#define PACKAGE_STRING "UNKNOWN"
#define PACKAGE_VERSION "UNKNOWN"
#endif

namespace mpi = boost::mpi;
namespace opt = boost::program_options;

int main(int argc, char* argv[]) {
    bool verbose = false;
    opt::options_description desc = optionsDescription();
    opt::variables_map vmap;
    opt::store(opt::parse_command_line(argc,argv,desc),vmap);
    opt::notify(vmap);

    if (vmap.count("help")) {
        std::cout << desc << "\n";
        return 1;
    }

    if(vmap.count("distribution")) {
        isingEnergyDistribution(vmap["dimension"].as<int>(),
                                vmap["clusters"].as<int>());
        exit(0);
    }

    verbose = vmap.count("verbose");

    size_t iterations = vmap["iterations"].as<size_t>();

    ReservoirFactory *rFactory = NULL;
    if ( vmap.count("ising") )  {
        if (!vmap.count("dimension")) {
            std::clog << "Option --ising requires -d\n";
            exit(1);
        }

        int dim = vmap["dimension"].as<int>();
        int clst = vmap["clusters"].as<int>();
        rFactory = new IsingReservoir::IsingFactory(dim,clst);
    } else {
        //Assume stochastic
        rFactory = new DefaultArgsReservoirFactory<StochasticReservoir>;
    }

    SystemFactory *sFactory = new BinomialSystemFactory;

    assert(rFactory);
    assert(sFactory);

    int dimension = 50;
    const double tau = vmap["tau"].as<double>();

    mpi::environment env(argc, argv);
    mpi::communicator world;
    char hostname[256];
    int requester;

    if (world.rank()==0) {
        std::string args;
        for (int k=1; k!=argc; ++k) {
            args += argv[k];
            args += " ";
        }
        printf("%s%s\n",PACKAGE_STRING,args.c_str());
        std::clog << "Running v" << PACKAGE_VERSION << " on " << world.size()
                    << " nodes." << std::endl;
        std::clog << (double)(dimension*dimension*iterations)/world.size()
                    << " simulations per node." << std::endl;
        printf("%s\n",outputHeader().c_str());
    }

    world.barrier();

    gethostname(hostname,255);
    fprintf(stderr, "Hello world from host %s (rank %d)\n",hostname,world.rank());

    Experiment::range work;
    Experiment experiment;
    experiment.iterations = iterations;
    experiment.dimension = dimension;
    experiment.sfactory = sFactory;
    experiment.rfactory = rFactory;

    for (int k=world.rank(); k<dimension*dimension; k+=world.size()) {
        MeasurementResult result = experiment.performIteration(k);
        printf("%s\n",outputString(result).c_str());
    }

    std::clog<<"Rank "<< world.rank()<<" finished.\n";
    return 0;
}
<|endoftext|>