<commit_before>namespace iox
{
template <uint64_t Capacity, typename ValueType>
IndexQueue<Capacity, ValueType>::IndexQueue(ConstructEmpty_t)
    : m_readPosition(Index(Capacity))
    , m_writePosition(Index(Capacity))
{
}

template <uint64_t Capacity, typename ValueType>
IndexQueue<Capacity, ValueType>::IndexQueue(ConstructFull_t)
    : m_readPosition(Index(0))
    , m_writePosition(Index(Capacity))
{
    for (uint64_t i = 0; i < Capacity; ++i)
    {
        m_cells[i].store(Index(i));
    }
}

template <uint64_t Capacity, typename ValueType>
constexpr uint64_t IndexQueue<Capacity, ValueType>::capacity()
{
    return Capacity;
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::push(ValueType index)
{
    // we need the CAS loop here since we may fail due to concurrent push operations
    // note that we are always able to succeed to publish since we have
    // enough capacity for all unique indices used

    // case analyis
    // (1) loaded value is exactly one cycle behind:
    //     value is from the last cycle
    //     we can try to publish
    // (2) loaded value has the same cycle:
    //     some other push has published but not updated the write position
    //     help updating the write position
    // (3) loaded value is more than one cycle behind:
    //     this should only happen due to wrap around when push is interrupted for a long time
    //     reload write position and try again
    //     note that a complete wraparound can lead to a false detection of 1) (ABA problem)
    //     but this is very unlikely with e.g. a 64 bit value type
    // (4) loaded value is some cycle ahead:
    //     write position is outdated, there must have been other pushes concurrently
    //     reload write position and try again

    constexpr bool notPublished = true;
    auto writePosition = loadNextWritePosition();
    do
    {
        auto oldValue = loadValueAt(writePosition);

        auto isFreeToPublish = [&]() { return oldValue.isOneCycleBehind(writePosition); };

        if (isFreeToPublish())
        {
            // case (1)
            Index newValue(index, writePosition.getCycle());

            // if publish fails, another thread has published before us
            if (tryToPublishAt(writePosition, oldValue, newValue))
            {
                break;
            }
        }

        // even if we are not able to publish, we check whether some other push has already updated the writePosition
        // before trying again to publish
        auto writePositionWasNotUpdated = [&]() { return oldValue.getCycle() == writePosition.getCycle(); };

        if (writePositionWasNotUpdated())
        {
            // case (2)
            // the writePosition was not updated yet by another push but the value was already written
            // help with the update
            updateNextWritePosition(writePosition);
        }
        else
        {
            // case (3) and (4)
            // note: we do not call updateNextWritePosition here, the CAS is bound to fail anyway
            // (our value of writePosition is not up to date so needs to be loaded again)
            writePosition = loadNextWritePosition();
        }

    } while (notPublished);

    updateNextWritePosition(writePosition);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::pop(ValueType& index)
{
    // we need the CAS loop here since we may fail due to concurrent pop operations
    // we leave when we detect an empty queue, otherwise we retry the pop operation

    // case analyis
    // (1) loaded value has the same cycle:
    //     value was not popped before
    //     try to get ownership
    // (2) loaded value is exactly one cycle behind:
    //     value is from the last cycle which means the queue is empty
    //     return false
    // (3) loaded value is more than one cycle behind:
    //     this should only happen due to wrap around when push is interrupted for a long time
    //     reload read position and try again
    // (4) loaded value is some cycle ahead:
    //     read position is outdated, there must have been pushes concurrently
    //     reload read position and try again

    constexpr bool ownerShipGained = true;
    Index value;
    auto readPosition = loadNextReadPosition();
    do
    {
        value = loadValueAt(readPosition);

        // we only dequeue if value and readPosition are in the same cycle
        auto isValidToRead = [&]() { return readPosition.getCycle() == value.getCycle(); };
        // readPosition is ahead by one cycle, queue was empty at loadValueAt(..)
        auto isEmpty = [&]() { return value.isOneCycleBehind(readPosition); };

        if (isValidToRead())
        {
            // case (1)
            if (tryToGainOwnershipAt(readPosition))
            {
                break; // pop successful
            }
            else
            {
                // retry, readPosition was already updated via CAS in tryToGainOwnershipAt
                // todo: maybe refactor to eliminate the continue but still skip the reload of
                // readPosition
                continue;
            }
        }
        else if (isEmpty())
        {
            // case (2)
            return false;
        }
        // else readPosition is outdated, retry operation

        // case (3) and (4)

        readPosition = loadNextReadPosition();

    } while (!ownerShipGained); // we leave if we gain ownership of readPosition

    index = value.getIndex();
    return true;
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::popIfFull(ValueType& index)
{
    // we do NOT need a CAS loop here since if we detect that the queue is not full
    // someone else popped an element and we do not retry to check whether it was filled AGAIN
    // concurrently (which will usually not be the case and then we would return false anyway)
    // if it is filled again we can (and will) retry popIfFull from the call site

    // the queue is full if and only if write position and read position are the same but read position is
    // one cycle behind write position
    // unfortunately it seems impossible in this design to check this condition without loading
    // write posiion and read position (which causes more contention)

    auto writePosition = loadNextWritePosition();
    auto readPosition = loadNextReadPosition();
    auto value = loadValueAt(readPosition);

    auto isFull = [&]() {
        return writePosition.getIndex() == readPosition.getIndex() && readPosition.isOneCycleBehind(writePosition);
    };

    if (isFull())
    {
        if (tryToGainOwnershipAt(readPosition))
        {
            index = value.getIndex();
            return true;
        }
    } // else someone else has popped an index
    return false;
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::empty()
{
    auto oldReadIndex = m_readPosition.load(std::memory_order_relaxed);
    auto value = m_cells[oldReadIndex.getIndex()].load(std::memory_order_relaxed);

    // if m_readPosition is ahead by one cycle compared to the value stored at head,
    // the queue was empty at the time of the loads above (but might not be anymore!)
    return value.isOneCycleBehind(oldReadIndex);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index IndexQueue<Capacity, ValueType>::loadNextReadPosition() const
{
    return m_readPosition.load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index IndexQueue<Capacity, ValueType>::loadNextWritePosition() const
{
    return m_writePosition.load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index
IndexQueue<Capacity, ValueType>::loadValueAt(typename IndexQueue<Capacity, ValueType>::Index position) const
{
    return m_cells[position.getIndex()].load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::tryToPublishAt(typename IndexQueue<Capacity, ValueType>::Index writePosition,
                                                     Index& oldValue,
                                                     Index newValue)
{
    return m_cells[writePosition.getIndex()].compare_exchange_strong(
        oldValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::updateNextWritePosition(Index& writePosition)
{
    // compare_exchange updates writePosition if NOT successful
    Index newWritePosition(writePosition + 1);
    auto updateSucceeded = m_writePosition.compare_exchange_strong(
        writePosition, newWritePosition, std::memory_order_relaxed, std::memory_order_relaxed);

    // not needed in the successful case, we do not retry
    // if (updateSucceeded)
    // {
    //     writePosition = newWritePosition;
    // }
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::tryToGainOwnershipAt(Index& oldReadPosition)
{
    Index newReadPosition(oldReadPosition + 1);
    return m_readPosition.compare_exchange_strong(
        oldReadPosition, newReadPosition, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::push(const UniqueIndex& index)
{
    push(*index);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::UniqueIndex IndexQueue<Capacity, ValueType>::pop()
{
    ValueType value;
    if (pop(value))
    {
        return UniqueIndex(value);
    }
    return UniqueIndex::invalid;
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::UniqueIndex IndexQueue<Capacity, ValueType>::popIfFull()
{
    ValueType value;
    if (popIfFull(value))
    {
        return UniqueIndex(value);
    }
    return UniqueIndex::invalid;
}

} // namespace iox<commit_msg>iox-#80 refactor code in index queue for comprehensibility<commit_after>namespace iox
{
template <uint64_t Capacity, typename ValueType>
IndexQueue<Capacity, ValueType>::IndexQueue(ConstructEmpty_t)
    : m_readPosition(Index(Capacity))
    , m_writePosition(Index(Capacity))
{
}

template <uint64_t Capacity, typename ValueType>
IndexQueue<Capacity, ValueType>::IndexQueue(ConstructFull_t)
    : m_readPosition(Index(0))
    , m_writePosition(Index(Capacity))
{
    for (uint64_t i = 0; i < Capacity; ++i)
    {
        m_cells[i].store(Index(i));
    }
}

template <uint64_t Capacity, typename ValueType>
constexpr uint64_t IndexQueue<Capacity, ValueType>::capacity()
{
    return Capacity;
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::push(ValueType index)
{
    // we need the CAS loop here since we may fail due to concurrent push operations
    // note that we are always able to succeed to publish since we have
    // enough capacity for all unique indices used

    // case analyis
    // (1) loaded value is exactly one cycle behind:
    //     value is from the last cycle
    //     we can try to publish
    // (2) loaded value has the same cycle:
    //     some other push has published but not updated the write position
    //     help updating the write position
    // (3) loaded value is more than one cycle behind:
    //     this should only happen due to wrap around when push is interrupted for a long time
    //     reload write position and try again
    //     note that a complete wraparound can lead to a false detection of 1) (ABA problem)
    //     but this is very unlikely with e.g. a 64 bit value type
    // (4) loaded value is some cycle ahead:
    //     write position is outdated, there must have been other pushes concurrently
    //     reload write position and try again

    constexpr bool notPublished = true;
    auto writePosition = loadNextWritePosition();
    do
    {
        auto oldValue = loadValueAt(writePosition);

        auto cellIsFree = oldValue.isOneCycleBehind(writePosition);

        if (cellIsFree)
        {
            // case (1)
            Index newValue(index, writePosition.getCycle());

            // if publish fails, another thread has published before us
            if (tryToPublishAt(writePosition, oldValue, newValue))
            {
                break;
            }
        }

        // even if we are not able to publish, we check whether some other push has already updated the writePosition
        // before trying again to publish
        auto writePositionRequiresUpdate = oldValue.getCycle() == writePosition.getCycle();

        if (writePositionRequiresUpdate)
        {
            // case (2)
            // the writePosition was not updated yet by another push but the value was already written
            // help with the update
            updateNextWritePosition(writePosition);
        }
        else
        {
            // case (3) and (4)
            // note: we do not call updateNextWritePosition here, the CAS is bound to fail anyway
            // (since our value of writePosition is not up to date so needs to be loaded again)
            writePosition = loadNextWritePosition();
        }

    } while (notPublished);

    updateNextWritePosition(writePosition);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::pop(ValueType& index)
{
    // we need the CAS loop here since we may fail due to concurrent pop operations
    // we leave when we detect an empty queue, otherwise we retry the pop operation

    // case analyis
    // (1) loaded value has the same cycle:
    //     value was not popped before
    //     try to get ownership
    // (2) loaded value is exactly one cycle behind:
    //     value is from the last cycle which means the queue is empty
    //     return false
    // (3) loaded value is more than one cycle behind:
    //     this should only happen due to wrap around when push is interrupted for a long time
    //     reload read position and try again
    // (4) loaded value is some cycle ahead:
    //     read position is outdated, there must have been pushes concurrently
    //     reload read position and try again

    constexpr bool ownerShipGained = true;
    Index value;
    auto readPosition = loadNextReadPosition();
    do
    {
        value = loadValueAt(readPosition);

        // we only dequeue if value and readPosition are in the same cycle
        auto cellIsValidToRead = readPosition.getCycle() == value.getCycle();

        if (cellIsValidToRead)
        {
            // case (1)
            if (tryToGainOwnershipAt(readPosition))
            {
                break; // pop successful
            }
            // retry, readPosition was already updated via CAS in tryToGainOwnershipAt
        }
        else
        {
            // readPosition is ahead by one cycle, queue was empty at loadValueAt(..)
            auto isEmpty = value.isOneCycleBehind(readPosition);

            if (isEmpty)
            {
                // case (2)
                return false;
            }

            // case (3) and (4) requires loading readPosition again
            readPosition = loadNextReadPosition();
        }

        // readPosition is outdated, retry operation

    } while (!ownerShipGained); // we leave if we gain ownership of readPosition

    index = value.getIndex();
    return true;
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::popIfFull(ValueType& index)
{
    // we do NOT need a CAS loop here since if we detect that the queue is not full
    // someone else popped an element and we do not retry to check whether it was filled AGAIN
    // concurrently (which will usually not be the case and then we would return false anyway)
    // if it is filled again we can (and will) retry popIfFull from the call site

    // the queue is full if and only if write position and read position are the same but read position is
    // one cycle behind write position
    // unfortunately it seems impossible in this design to check this condition without loading
    // write posiion and read position (which causes more contention)

    auto writePosition = loadNextWritePosition();
    auto readPosition = loadNextReadPosition();
    auto value = loadValueAt(readPosition);

    auto isFull = writePosition.getIndex() == readPosition.getIndex() && readPosition.isOneCycleBehind(writePosition);

    if (isFull)
    {
        if (tryToGainOwnershipAt(readPosition))
        {
            index = value.getIndex();
            return true;
        }
    }

    // otherwise someone else has dequeued an index and the queue was not full at the start of this popIfFull
    return false;
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::empty()
{
    auto oldReadIndex = m_readPosition.load(std::memory_order_relaxed);
    auto value = m_cells[oldReadIndex.getIndex()].load(std::memory_order_relaxed);

    // if m_readPosition is ahead by one cycle compared to the value stored at head,
    // the queue was empty at the time of the loads above (but might not be anymore!)
    return value.isOneCycleBehind(oldReadIndex);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index IndexQueue<Capacity, ValueType>::loadNextReadPosition() const
{
    return m_readPosition.load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index IndexQueue<Capacity, ValueType>::loadNextWritePosition() const
{
    return m_writePosition.load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index
IndexQueue<Capacity, ValueType>::loadValueAt(typename IndexQueue<Capacity, ValueType>::Index position) const
{
    return m_cells[position.getIndex()].load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::tryToPublishAt(typename IndexQueue<Capacity, ValueType>::Index writePosition,
                                                     Index& oldValue,
                                                     Index newValue)
{
    return m_cells[writePosition.getIndex()].compare_exchange_strong(
        oldValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::updateNextWritePosition(Index& writePosition)
{
    // compare_exchange updates writePosition if NOT successful
    Index newWritePosition(writePosition + 1);
    auto updateSucceeded = m_writePosition.compare_exchange_strong(
        writePosition, newWritePosition, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::tryToGainOwnershipAt(Index& oldReadPosition)
{
    Index newReadPosition(oldReadPosition + 1);
    return m_readPosition.compare_exchange_strong(
        oldReadPosition, newReadPosition, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::push(const UniqueIndex& index)
{
    push(*index);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::UniqueIndex IndexQueue<Capacity, ValueType>::pop()
{
    ValueType value;
    if (pop(value))
    {
        return UniqueIndex(value);
    }
    return UniqueIndex::invalid;
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::UniqueIndex IndexQueue<Capacity, ValueType>::popIfFull()
{
    ValueType value;
    if (popIfFull(value))
    {
        return UniqueIndex(value);
    }
    return UniqueIndex::invalid;
}

} // namespace iox<|endoftext|>


<commit_before>namespace mant {
  namespace bbob {
    template <typename T = double>
    class BlackBoxOptimisationBenchmark : public OptimisationProblem<T, T> {
    static_assert(std::is_floating_point<T>::value, "T must be a floating point type.");

      public:
        explicit BlackBoxOptimisationBenchmark(
            const std::size_t numberOfDimensions) noexcept;

        virtual ~BlackBoxOptimisationBenchmark() = default;

      protected:
        arma::Col<T> getRandomParameterTranslation() const noexcept;

        arma::Col<T> getParameterConditioning(
            const T conditionNumber) const noexcept;

        arma::Col<T> getConditionedParameter(
            const arma::Col<T>& parameter) const noexcept;

        arma::Col<T> getAsymmetricParameter(
            const T asymmetry,
            const arma::Col<T>& parameter) const noexcept;

        T getOscillatedValue(
            const T oscilliation) const noexcept;

        arma::Col<T> getOscillatedParameter(
            const arma::Col<T>& parameter) const noexcept;

        T getBoundConstraintsValue(
            const arma::Col<T>& parameter) const noexcept;

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
        friend class OptimisationAlgorithm;

        std::vector<double> serialise() const noexcept;

        void deserialise(
            const std::vector<double>& serialisedOptimisationProblem);
#endif
    };

    //
    // Implementation
    //

    template <typename T>
    BlackBoxOptimisationBenchmark<T>::BlackBoxOptimisationBenchmark(
        const std::size_t numberOfDimensions) noexcept
      : OptimisationProblem<T>(numberOfDimensions) {
      this->setLowerBounds(arma::zeros<arma::Col<T>>(this->numberOfDimensions_) - 5.0);
      this->setUpperBounds(arma::zeros<arma::Col<T>>(this->numberOfDimensions_) + 5.0);
      this->setObjectiveValueTranslation(std::min(1000.0, std::max(-1000.0, std::floor(std::cauchy_distribution<double>(0.0, 100.0)(Rng::getGenerator()) * 100) / 100)));
      this->setAcceptableObjectiveValue(this->objectiveValueTranslation_ + 1.0e-8);
    }

    template <typename T>
    arma::Col<T> BlackBoxOptimisationBenchmark<T>::getRandomParameterTranslation() const noexcept {
      arma::Col<T> randomParameterTranslation = arma::floor(arma::randu<arma::Col<T>>(this->numberOfDimensions_) * 1.0e4) / 1.0e4 * 8.0 - 4.0;
      randomParameterTranslation.elem(arma::find(randomParameterTranslation == 0)).fill(-1.0e-5);
      return randomParameterTranslation;
    }

    template <typename T>
    arma::Col<T> BlackBoxOptimisationBenchmark<T>::getParameterConditioning(
        const T conditionNumber) const noexcept {
      arma::Col<T> parameterConditioning = arma::linspace<arma::Col<T>>(0.0, 1.0, this->numberOfDimensions_);

      for (T& conditioning : parameterConditioning) {
        conditioning = std::pow(conditionNumber, conditioning);
      }

      return parameterConditioning;
    }

    template <typename T>
    arma::Col<T> BlackBoxOptimisationBenchmark<T>::getConditionedParameter(
        const arma::Col<T>& parameter) const noexcept {
      arma::Col<T> conditionedParameter = arma::linspace<arma::Col<T>>(0.0, 1.0, this->numberOfDimensions_);

      for (std::size_t n = 0; n < parameter.n_elem; ++n) {
        conditionedParameter(n) = std::pow(parameter(n), conditionedParameter(n));
      }

      return conditionedParameter;
    }

    template <typename T>
    arma::Col<T> BlackBoxOptimisationBenchmark<T>::getAsymmetricParameter(
        const T asymmetry,
        const arma::Col<T>& parameter) const noexcept {
      arma::Col<T> asymmetricParameter(parameter.n_elem);
      const arma::Col<T>& spacing = arma::linspace<arma::Col<T>>(0.0, 1.0, this->numberOfDimensions_);

      for (std::size_t n = 0; n < parameter.n_elem; ++n) {
        const T value = parameter(n);

        if (value > 0.0) {
          asymmetricParameter(n) = std::pow(value, 1 + asymmetry * spacing(n) * std::sqrt(value));
        } else {
          asymmetricParameter(n) = value;
        }
      }

      return asymmetricParameter;
    }

    template <typename T>
    T BlackBoxOptimisationBenchmark<T>::getOscillatedValue(
        const T value) const noexcept {
      if (value != 0.0) {
        T c1;
        T c2;
        if (value > 0.0) {
          c1 = 10.0;
          c2 = 7.9;
        } else {
          c1 = 5.5;
          c2 = 3.1;
        }

        const T& logAbsoluteValue = std::log(std::abs(value));
        return std::copysign(1.0, value) * std::exp(logAbsoluteValue + 0.049 * (std::sin(c1 * logAbsoluteValue) + std::sin(c2 * logAbsoluteValue)));
      } else {
        return 0.0;
      }
    }

    template <typename T>
    arma::Col<T> BlackBoxOptimisationBenchmark<T>::getOscillatedParameter(
        const arma::Col<T>& parameter) const noexcept {
      arma::Col<T> oscillatedParameter(parameter.n_elem);

      for (std::size_t n = 0; n < parameter.n_elem; ++n) {
        oscillatedParameter(n) = getOscillatedValue(parameter(n));
      }

      return oscillatedParameter;
    }

    template <typename T>
    T BlackBoxOptimisationBenchmark<T>::getBoundConstraintsValue(
        const arma::Col<T>& parameter) const noexcept {
      T boundConstraintsValue = 0.0;

      for (std::size_t n = 0; n < parameter.n_elem; ++n) {
        boundConstraintsValue += std::pow(std::max(0.0, std::abs(parameter(n)) - 5.0), 2.0);
      }

      return boundConstraintsValue;
    }

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
    template <typename T>
    std::vector<double> BlackBoxOptimisationBenchmark<T>::serialise() const noexcept {
      return OptimisationProblem<T, T>::serialise();
    }

    template <typename T>
    void BlackBoxOptimisationBenchmark<T>::deserialise(
        const std::vector<double>& serialisedOptimisationProblem) {
      OptimisationProblem<T, T>::deserialise(serialisedOptimisationProblem);
    }
#endif
  }
}
<commit_msg>Added codomain templating to the BBOB base class<commit_after>namespace mant {
  namespace bbob {
    template <typename T, typename U = double>
    class BlackBoxOptimisationBenchmark : public OptimisationProblem<T, U> {
    static_assert(std::is_floating_point<T>::value, "T must be a floating point type.");
    static_assert(std::is_floating_point<U>::value, "The codomain type U must be a floating point type.");

      public:
        explicit BlackBoxOptimisationBenchmark(
            const std::size_t numberOfDimensions) noexcept;

        virtual ~BlackBoxOptimisationBenchmark() = default;

      protected:
        arma::Col<T> getRandomParameterTranslation() const noexcept;

        arma::Col<T> getParameterConditioning(
            const T conditionNumber) const noexcept;

        arma::Col<T> getConditionedParameter(
            const arma::Col<T>& parameter) const noexcept;

        arma::Col<T> getAsymmetricParameter(
            const T asymmetry,
            const arma::Col<T>& parameter) const noexcept;

        U getOscillatedValue(
            const U oscilliation) const noexcept;

        T getOscillatedValue(
            const T oscilliation) const noexcept;

        arma::Col<T> getOscillatedParameter(
            const arma::Col<T>& parameter) const noexcept;

        U getBoundConstraintsValue(
            const arma::Col<T>& parameter) const noexcept;

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
        friend class OptimisationAlgorithm;

        std::vector<double> serialise() const noexcept;

        void deserialise(
            const std::vector<double>& serialisedOptimisationProblem);
#endif
    };

    //
    // Implementation
    //

    template <typename T, typename U>
    BlackBoxOptimisationBenchmark<T, U>::BlackBoxOptimisationBenchmark(
        const std::size_t numberOfDimensions) noexcept
      : OptimisationProblem<T, U>(numberOfDimensions) {
      this->setLowerBounds(arma::zeros<arma::Col<T>>(this->numberOfDimensions_) - static_cast<T>(5.0L));
      this->setUpperBounds(arma::zeros<arma::Col<T>>(this->numberOfDimensions_) + static_cast<T>(5.0L));
      this->setObjectiveValueTranslation(std::min(static_cast<U>(1000.0L), std::max(static_cast<U>(-1000.0L), std::floor(std::cauchy_distribution<U>(static_cast<U>(0.0L), static_cast<U>(100.0L))(Rng::getGenerator()) * static_cast<U>(100.0L)) / static_cast<U>(100.0L))));
      this->setAcceptableObjectiveValue(this->objectiveValueTranslation_ + static_cast<U>(1.0e-8L));
    }

    template <typename T, typename U>
    arma::Col<T> BlackBoxOptimisationBenchmark<T, U>::getRandomParameterTranslation() const noexcept {
      arma::Col<T> randomParameterTranslation = arma::floor(arma::randu<arma::Col<T>>(this->numberOfDimensions_) * static_cast<T>(1.0e4L)) / static_cast<T>(1.0e4L) * static_cast<T>(8.0L) - static_cast<T>(4.0L);
      randomParameterTranslation.elem(arma::find(randomParameterTranslation == static_cast<T>(0.0L))).fill(static_cast<T>(-1.0e-5L));
      return randomParameterTranslation;
    }

    template <typename T, typename U>
    arma::Col<T> BlackBoxOptimisationBenchmark<T, U>::getParameterConditioning(
        const T conditionNumber) const noexcept {
      arma::Col<T> parameterConditioning = arma::linspace<arma::Col<T>>(static_cast<T>(0.0L), static_cast<T>(1.0L), this->numberOfDimensions_);

      for (T& conditioning : parameterConditioning) {
        conditioning = std::pow(conditionNumber, conditioning);
      }

      return parameterConditioning;
    }

    template <typename T, typename U>
    arma::Col<T> BlackBoxOptimisationBenchmark<T, U>::getConditionedParameter(
        const arma::Col<T>& parameter) const noexcept {
      arma::Col<T> conditionedParameter = arma::linspace<arma::Col<T>>(static_cast<T>(0.0L), static_cast<T>(1.0L), this->numberOfDimensions_);

      for (std::size_t n = 0; n < parameter.n_elem; ++n) {
        conditionedParameter(n) = std::pow(parameter(n), conditionedParameter(n));
      }

      return conditionedParameter;
    }

    template <typename T, typename U>
    arma::Col<T> BlackBoxOptimisationBenchmark<T, U>::getAsymmetricParameter(
        const T asymmetry,
        const arma::Col<T>& parameter) const noexcept {
      arma::Col<T> asymmetricParameter(parameter.n_elem);
      const arma::Col<T>& spacing = arma::linspace<arma::Col<T>>(static_cast<T>(0.0L), static_cast<T>(1.0L), this->numberOfDimensions_);

      for (std::size_t n = 0; n < parameter.n_elem; ++n) {
        const T value = parameter(n);

        if (value > static_cast<T>(0.0L)) {
          asymmetricParameter(n) = std::pow(value, static_cast<T>(1.0L) + asymmetry * spacing(n) * std::sqrt(value));
        } else {
          asymmetricParameter(n) = value;
        }
      }

      return asymmetricParameter;
    }

    template <typename T, typename U>
    U BlackBoxOptimisationBenchmark<T, U>::getOscillatedValue(
        const U value) const noexcept {
      if (value != static_cast<U>(0.0L)) {
        T c1;
        T c2;
        if (value > static_cast<U>(0.0L)) {
          c1 = static_cast<U>(10.0L);
          c2 = static_cast<U>(7.9L);
        } else {
          c1 = static_cast<U>(5.5L);
          c2 = static_cast<U>(3.1L);
        }

        const T& logAbsoluteValue = std::log(std::abs(value));
        return std::copysign(static_cast<U>(1.0L), value) * std::exp(logAbsoluteValue + static_cast<U>(0.049L) * (std::sin(c1 * logAbsoluteValue) + std::sin(c2 * logAbsoluteValue)));
      } else {
        return static_cast<U>(0.0L);
      }
    }

    template <typename T, typename U>
    T BlackBoxOptimisationBenchmark<T, U>::getOscillatedValue(
        const T value) const noexcept {
      if (value != static_cast<U>(0.0L)) {
        T c1;
        T c2;
        if (value > static_cast<U>(0.0L)) {
          c1 = static_cast<U>(10.0L);
          c2 = static_cast<U>(7.9L);
        } else {
          c1 = static_cast<U>(5.5L);
          c2 = static_cast<U>(3.1L);
        }

        const T& logAbsoluteValue = std::log(std::abs(value));
        return std::copysign(static_cast<U>(1.0L), value) * std::exp(logAbsoluteValue + static_cast<U>(0.049L) * (std::sin(c1 * logAbsoluteValue) + std::sin(c2 * logAbsoluteValue)));
      } else {
        return static_cast<U>(0.0L);
      }
    }

    template <typename T, typename U>
    arma::Col<T> BlackBoxOptimisationBenchmark<T, U>::getOscillatedParameter(
        const arma::Col<T>& parameter) const noexcept {
      arma::Col<T> oscillatedParameter(parameter.n_elem);

      for (std::size_t n = 0; n < parameter.n_elem; ++n) {
        oscillatedParameter(n) = getOscillatedValue(parameter(n));
      }

      return oscillatedParameter;
    }

    template <typename T, typename U>
    U BlackBoxOptimisationBenchmark<T, U>::getBoundConstraintsValue(
        const arma::Col<T>& parameter) const noexcept {
      U boundConstraintsValue = static_cast<U>(0.0L);

      for (std::size_t n = 0; n < parameter.n_elem; ++n) {
        boundConstraintsValue += std::pow(std::max(static_cast<U>(0.0L), std::abs(parameter(n)) - static_cast<U>(5.0L)), static_cast<U>(2.0L));
      }

      return boundConstraintsValue;
    }

#if defined(MANTELLA_USE_PARALLEL_ALGORITHMS)
    template <typename T, typename U>
    std::vector<double> BlackBoxOptimisationBenchmark<T, U>::serialise() const noexcept {
      return OptimisationProblem<T, U>::serialise();
    }

    template <typename T, typename U>
    void BlackBoxOptimisationBenchmark<T, U>::deserialise(
        const std::vector<double>& serialisedOptimisationProblem) {
      OptimisationProblem<T, U>::deserialise(serialisedOptimisationProblem);
    }
#endif
  }
}
<|endoftext|>


<commit_before>/***************************************************************************
    copyright            : (C) 2002 - 2008 by Scott Wheeler
    email                : wheeler@kde.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License version   *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
 *   02110-1301  USA                                                       *
 *                                                                         *
 *   Alternatively, this file is available under the Mozilla Public        *
 *   License Version 1.1.  You may obtain a copy of the License at         *
 *   http://www.mozilla.org/MPL/                                           *
 ***************************************************************************/

#include <tbytevector.h>
#include <tdebug.h>

#include <flacpicture.h>
#include <xiphcomment.h>
#include <tpropertymap.h>

using namespace TagLib;

typedef List<FLAC::Picture*> PictureList;

class Ogg::XiphComment::XiphCommentPrivate
{
public:
  FieldListMap fieldListMap;
  String vendorID;
  String commentField;
  PictureList pictureList;
};

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

Ogg::XiphComment::XiphComment() : TagLib::Tag()
{
  d = new XiphCommentPrivate;
}

Ogg::XiphComment::XiphComment(const ByteVector &data) : TagLib::Tag()
{
  d = new XiphCommentPrivate;
  parse(data);
}

Ogg::XiphComment::~XiphComment()
{
  delete d;
}

String Ogg::XiphComment::title() const
{
  if(d->fieldListMap["TITLE"].isEmpty())
    return String::null;
  return d->fieldListMap["TITLE"].toString();
}

String Ogg::XiphComment::artist() const
{
  if(d->fieldListMap["ARTIST"].isEmpty())
    return String::null;
  return d->fieldListMap["ARTIST"].toString();
}

String Ogg::XiphComment::album() const
{
  if(d->fieldListMap["ALBUM"].isEmpty())
    return String::null;
  return d->fieldListMap["ALBUM"].toString();
}

String Ogg::XiphComment::comment() const
{
  if(!d->fieldListMap["DESCRIPTION"].isEmpty()) {
    d->commentField = "DESCRIPTION";
    return d->fieldListMap["DESCRIPTION"].toString();
  }

  if(!d->fieldListMap["COMMENT"].isEmpty()) {
    d->commentField = "COMMENT";
    return d->fieldListMap["COMMENT"].toString();
  }

  return String::null;
}

String Ogg::XiphComment::genre() const
{
  if(d->fieldListMap["GENRE"].isEmpty())
    return String::null;
  return d->fieldListMap["GENRE"].toString();
}

TagLib::uint Ogg::XiphComment::year() const
{
  if(!d->fieldListMap["DATE"].isEmpty())
    return d->fieldListMap["DATE"].front().toInt();
  if(!d->fieldListMap["YEAR"].isEmpty())
    return d->fieldListMap["YEAR"].front().toInt();
  return 0;
}

TagLib::uint Ogg::XiphComment::track() const
{
  if(!d->fieldListMap["TRACKNUMBER"].isEmpty())
    return d->fieldListMap["TRACKNUMBER"].front().toInt();
  if(!d->fieldListMap["TRACKNUM"].isEmpty())
    return d->fieldListMap["TRACKNUM"].front().toInt();
  return 0;
}

void Ogg::XiphComment::setTitle(const String &s)
{
  addField("TITLE", s);
}

void Ogg::XiphComment::setArtist(const String &s)
{
  addField("ARTIST", s);
}

void Ogg::XiphComment::setAlbum(const String &s)
{
  addField("ALBUM", s);
}

void Ogg::XiphComment::setComment(const String &s)
{
  addField(d->commentField.isEmpty() ? "DESCRIPTION" : d->commentField, s);
}

void Ogg::XiphComment::setGenre(const String &s)
{
  addField("GENRE", s);
}

void Ogg::XiphComment::setYear(uint i)
{
  removeField("YEAR");
  if(i == 0)
    removeField("DATE");
  else
    addField("DATE", String::number(i));
}

void Ogg::XiphComment::setTrack(uint i)
{
  removeField("TRACKNUM");
  if(i == 0)
    removeField("TRACKNUMBER");
  else
    addField("TRACKNUMBER", String::number(i));
}

bool Ogg::XiphComment::isEmpty() const
{
  FieldListMap::ConstIterator it = d->fieldListMap.begin();
  for(; it != d->fieldListMap.end(); ++it)
    if(!(*it).second.isEmpty())
      return false;

  return true;
}

TagLib::uint Ogg::XiphComment::fieldCount() const
{
  uint count = 0;

  FieldListMap::ConstIterator it = d->fieldListMap.begin();
  for(; it != d->fieldListMap.end(); ++it)
    count += (*it).second.size();

  count += d->pictureList.size();

  return count;
}

const Ogg::FieldListMap &Ogg::XiphComment::fieldListMap() const
{
  return d->fieldListMap;
}

PropertyMap Ogg::XiphComment::properties() const
{
  return d->fieldListMap;
}

PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties)
{
  // check which keys are to be deleted
  StringList toRemove;
  for(FieldListMap::ConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it)
    if (!properties.contains(it->first))
      toRemove.append(it->first);

  for(StringList::ConstIterator it = toRemove.begin(); it != toRemove.end(); ++it)
      removeField(*it);

  // now go through keys in \a properties and check that the values match those in the xiph comment
  PropertyMap invalid;
  PropertyMap::ConstIterator it = properties.begin();
  for(; it != properties.end(); ++it)
  {
    if(!checkKey(it->first))
      invalid.insert(it->first, it->second);
    else if(!d->fieldListMap.contains(it->first) || !(it->second == d->fieldListMap[it->first])) {
      const StringList &sl = it->second;
      if(sl.size() == 0)
        // zero size string list -> remove the tag with all values
        removeField(it->first);
      else {
        // replace all strings in the list for the tag
        StringList::ConstIterator valueIterator = sl.begin();
        addField(it->first, *valueIterator, true);
        ++valueIterator;
        for(; valueIterator != sl.end(); ++valueIterator)
          addField(it->first, *valueIterator, false);
      }
    }
  }
  return invalid;
}

bool Ogg::XiphComment::checkKey(const String &key)
{
  if(key.size() < 1)
    return false;
  for(String::ConstIterator it = key.begin(); it != key.end(); it++)
      // forbid non-printable, non-ascii, '=' (#61) and '~' (#126)
      if (*it < 32 || *it >= 128 || *it == 61 || *it == 126)
        return false;
  return true;
}

String Ogg::XiphComment::vendorID() const
{
  return d->vendorID;
}

void Ogg::XiphComment::addField(const String &key, const String &value, bool replace)
{
  if(replace)
    removeField(key.upper());

  if(!key.isEmpty() && !value.isEmpty())
    d->fieldListMap[key.upper()].append(value);
}

void Ogg::XiphComment::removeField(const String &key, const String &value)
{
  if(!value.isNull()) {
    StringList::Iterator it = d->fieldListMap[key].begin();
    while(it != d->fieldListMap[key].end()) {
      if(value == *it)
        it = d->fieldListMap[key].erase(it);
      else
        it++;
    }
  }
  else
    d->fieldListMap.erase(key);
}

bool Ogg::XiphComment::contains(const String &key) const
{
  return d->fieldListMap.contains(key) && !d->fieldListMap[key].isEmpty();
}

void Ogg::XiphComment::removePicture(FLAC::Picture *picture, bool del)
{
  List<FLAC::Picture *>::Iterator it = d->pictureList.find(picture);
  if(it != d->pictureList.end())
    d->pictureList.erase(it);

  if(del)
    delete picture;
}

void Ogg::XiphComment::removePictures()
{
  PictureList newList;
  for(uint i = 0; i < d->pictureList.size(); i++) {
    delete d->pictureList[i];
  }
  d->pictureList = newList;
}

void Ogg::XiphComment::addPicture(FLAC::Picture * picture)
{
  d->pictureList.append(picture);
}

List<FLAC::Picture *> Ogg::XiphComment::pictureList()
{
  return d->pictureList;
}

ByteVector Ogg::XiphComment::render() const
{
  return render(true);
}

ByteVector Ogg::XiphComment::render(bool addFramingBit) const
{
  ByteVector data;

  // Add the vendor ID length and the vendor ID.  It's important to use the
  // length of the data(String::UTF8) rather than the length of the the string
  // since this is UTF8 text and there may be more characters in the data than
  // in the UTF16 string.

  ByteVector vendorData = d->vendorID.data(String::UTF8);

  data.append(ByteVector::fromUInt(vendorData.size(), false));
  data.append(vendorData);

  // Add the number of fields.

  data.append(ByteVector::fromUInt(fieldCount(), false));

  // Iterate over the the field lists.  Our iterator returns a
  // std::pair<String, StringList> where the first String is the field name and
  // the StringList is the values associated with that field.

  FieldListMap::ConstIterator it = d->fieldListMap.begin();
  for(; it != d->fieldListMap.end(); ++it) {

    // And now iterate over the values of the current list.

    String fieldName = (*it).first;
    StringList values = (*it).second;

    StringList::ConstIterator valuesIt = values.begin();
    for(; valuesIt != values.end(); ++valuesIt) {
      ByteVector fieldData = fieldName.data(String::UTF8);
      fieldData.append('=');
      fieldData.append((*valuesIt).data(String::UTF8));

      data.append(ByteVector::fromUInt(fieldData.size(), false));
      data.append(fieldData);
    }
  }

  for(PictureList::ConstIterator it = d->pictureList.begin(); it != d->pictureList.end(); ++it) {
    ByteVector picture = (*it)->render().toBase64();
    data.append(ByteVector::fromUInt(picture.size()+23,false));
    data.append("METADATA_BLOCK_PICTURE=");
    data.append(picture);
  }

  // Append the "framing bit".

  if(addFramingBit)
    data.append(char(1));

  return data;
}

////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////

void Ogg::XiphComment::parse(const ByteVector &data)
{
  // The first thing in the comment data is the vendor ID length, followed by a
  // UTF8 string with the vendor ID.

  uint pos = 0;

  const uint vendorLength = data.toUInt(0, false);
  pos += 4;

  d->vendorID = String(data.mid(pos, vendorLength), String::UTF8);
  pos += vendorLength;

  // Next the number of fields in the comment vector.

  const uint commentFields = data.toUInt(pos, false);
  pos += 4;

  if(commentFields > (data.size() - 8) / 4) {
    return;
  }

  for(uint i = 0; i < commentFields; i++) {

    // Each comment field is in the format "KEY=value" in a UTF8 string and has
    // 4 bytes before the text starts that gives the length.

    const uint commentLength = data.toUInt(pos, false);
    pos += 4;

    ByteVector entry = data.mid(pos, commentLength);

    // Don't go past data end
    pos+=commentLength;
    if (pos>data.size())
      break;

    // Handle Pictures separately
    if(entry.startsWith("METADATA_BLOCK_PICTURE=")) {

      // Decode base64 picture data
      ByteVector picturedata = entry.mid(23, entry.size()-23).fromBase64();

      if(picturedata.size()==0) {
        debug("Empty picture data. Discarding content");
        continue;
        }

      FLAC::Picture * picture = new FLAC::Picture();
      if(picture->parse(picturedata))
        d->pictureList.append(picture);
      else
        debug("Unable to parse METADATA_BLOCK_PICTURE. Discarding content.");
    }
    else {

      // Check for field separator
      int sep = entry.find('=');
      if (sep == -1)
        break;

      // Parse key and value
      String key = String(entry.mid(0,sep), String::UTF8);
      String value = String(entry.mid(sep+1, commentLength-sep), String::UTF8);
      addField(key, value, false);
    }
  }
}
<commit_msg>Delete pictures in XiphComment destructor<commit_after>/***************************************************************************
    copyright            : (C) 2002 - 2008 by Scott Wheeler
    email                : wheeler@kde.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License version   *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
 *   02110-1301  USA                                                       *
 *                                                                         *
 *   Alternatively, this file is available under the Mozilla Public        *
 *   License Version 1.1.  You may obtain a copy of the License at         *
 *   http://www.mozilla.org/MPL/                                           *
 ***************************************************************************/

#include <tbytevector.h>
#include <tdebug.h>

#include <flacpicture.h>
#include <xiphcomment.h>
#include <tpropertymap.h>

using namespace TagLib;

typedef List<FLAC::Picture*> PictureList;

class Ogg::XiphComment::XiphCommentPrivate
{
public:
  FieldListMap fieldListMap;
  String vendorID;
  String commentField;
  PictureList pictureList;
};

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

Ogg::XiphComment::XiphComment() : TagLib::Tag()
{
  d = new XiphCommentPrivate;
}

Ogg::XiphComment::XiphComment(const ByteVector &data) : TagLib::Tag()
{
  d = new XiphCommentPrivate;
  parse(data);
}

Ogg::XiphComment::~XiphComment()
{
  removePictures();
  delete d;
}

String Ogg::XiphComment::title() const
{
  if(d->fieldListMap["TITLE"].isEmpty())
    return String::null;
  return d->fieldListMap["TITLE"].toString();
}

String Ogg::XiphComment::artist() const
{
  if(d->fieldListMap["ARTIST"].isEmpty())
    return String::null;
  return d->fieldListMap["ARTIST"].toString();
}

String Ogg::XiphComment::album() const
{
  if(d->fieldListMap["ALBUM"].isEmpty())
    return String::null;
  return d->fieldListMap["ALBUM"].toString();
}

String Ogg::XiphComment::comment() const
{
  if(!d->fieldListMap["DESCRIPTION"].isEmpty()) {
    d->commentField = "DESCRIPTION";
    return d->fieldListMap["DESCRIPTION"].toString();
  }

  if(!d->fieldListMap["COMMENT"].isEmpty()) {
    d->commentField = "COMMENT";
    return d->fieldListMap["COMMENT"].toString();
  }

  return String::null;
}

String Ogg::XiphComment::genre() const
{
  if(d->fieldListMap["GENRE"].isEmpty())
    return String::null;
  return d->fieldListMap["GENRE"].toString();
}

TagLib::uint Ogg::XiphComment::year() const
{
  if(!d->fieldListMap["DATE"].isEmpty())
    return d->fieldListMap["DATE"].front().toInt();
  if(!d->fieldListMap["YEAR"].isEmpty())
    return d->fieldListMap["YEAR"].front().toInt();
  return 0;
}

TagLib::uint Ogg::XiphComment::track() const
{
  if(!d->fieldListMap["TRACKNUMBER"].isEmpty())
    return d->fieldListMap["TRACKNUMBER"].front().toInt();
  if(!d->fieldListMap["TRACKNUM"].isEmpty())
    return d->fieldListMap["TRACKNUM"].front().toInt();
  return 0;
}

void Ogg::XiphComment::setTitle(const String &s)
{
  addField("TITLE", s);
}

void Ogg::XiphComment::setArtist(const String &s)
{
  addField("ARTIST", s);
}

void Ogg::XiphComment::setAlbum(const String &s)
{
  addField("ALBUM", s);
}

void Ogg::XiphComment::setComment(const String &s)
{
  addField(d->commentField.isEmpty() ? "DESCRIPTION" : d->commentField, s);
}

void Ogg::XiphComment::setGenre(const String &s)
{
  addField("GENRE", s);
}

void Ogg::XiphComment::setYear(uint i)
{
  removeField("YEAR");
  if(i == 0)
    removeField("DATE");
  else
    addField("DATE", String::number(i));
}

void Ogg::XiphComment::setTrack(uint i)
{
  removeField("TRACKNUM");
  if(i == 0)
    removeField("TRACKNUMBER");
  else
    addField("TRACKNUMBER", String::number(i));
}

bool Ogg::XiphComment::isEmpty() const
{
  FieldListMap::ConstIterator it = d->fieldListMap.begin();
  for(; it != d->fieldListMap.end(); ++it)
    if(!(*it).second.isEmpty())
      return false;

  return true;
}

TagLib::uint Ogg::XiphComment::fieldCount() const
{
  uint count = 0;

  FieldListMap::ConstIterator it = d->fieldListMap.begin();
  for(; it != d->fieldListMap.end(); ++it)
    count += (*it).second.size();

  count += d->pictureList.size();

  return count;
}

const Ogg::FieldListMap &Ogg::XiphComment::fieldListMap() const
{
  return d->fieldListMap;
}

PropertyMap Ogg::XiphComment::properties() const
{
  return d->fieldListMap;
}

PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties)
{
  // check which keys are to be deleted
  StringList toRemove;
  for(FieldListMap::ConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it)
    if (!properties.contains(it->first))
      toRemove.append(it->first);

  for(StringList::ConstIterator it = toRemove.begin(); it != toRemove.end(); ++it)
      removeField(*it);

  // now go through keys in \a properties and check that the values match those in the xiph comment
  PropertyMap invalid;
  PropertyMap::ConstIterator it = properties.begin();
  for(; it != properties.end(); ++it)
  {
    if(!checkKey(it->first))
      invalid.insert(it->first, it->second);
    else if(!d->fieldListMap.contains(it->first) || !(it->second == d->fieldListMap[it->first])) {
      const StringList &sl = it->second;
      if(sl.size() == 0)
        // zero size string list -> remove the tag with all values
        removeField(it->first);
      else {
        // replace all strings in the list for the tag
        StringList::ConstIterator valueIterator = sl.begin();
        addField(it->first, *valueIterator, true);
        ++valueIterator;
        for(; valueIterator != sl.end(); ++valueIterator)
          addField(it->first, *valueIterator, false);
      }
    }
  }
  return invalid;
}

bool Ogg::XiphComment::checkKey(const String &key)
{
  if(key.size() < 1)
    return false;
  for(String::ConstIterator it = key.begin(); it != key.end(); it++)
      // forbid non-printable, non-ascii, '=' (#61) and '~' (#126)
      if (*it < 32 || *it >= 128 || *it == 61 || *it == 126)
        return false;
  return true;
}

String Ogg::XiphComment::vendorID() const
{
  return d->vendorID;
}

void Ogg::XiphComment::addField(const String &key, const String &value, bool replace)
{
  if(replace)
    removeField(key.upper());

  if(!key.isEmpty() && !value.isEmpty())
    d->fieldListMap[key.upper()].append(value);
}

void Ogg::XiphComment::removeField(const String &key, const String &value)
{
  if(!value.isNull()) {
    StringList::Iterator it = d->fieldListMap[key].begin();
    while(it != d->fieldListMap[key].end()) {
      if(value == *it)
        it = d->fieldListMap[key].erase(it);
      else
        it++;
    }
  }
  else
    d->fieldListMap.erase(key);
}

bool Ogg::XiphComment::contains(const String &key) const
{
  return d->fieldListMap.contains(key) && !d->fieldListMap[key].isEmpty();
}

void Ogg::XiphComment::removePicture(FLAC::Picture *picture, bool del)
{
  List<FLAC::Picture *>::Iterator it = d->pictureList.find(picture);
  if(it != d->pictureList.end())
    d->pictureList.erase(it);

  if(del)
    delete picture;
}

void Ogg::XiphComment::removePictures()
{
  PictureList newList;
  for(uint i = 0; i < d->pictureList.size(); i++) {
    delete d->pictureList[i];
  }
  d->pictureList = newList;
}

void Ogg::XiphComment::addPicture(FLAC::Picture * picture)
{
  d->pictureList.append(picture);
}

List<FLAC::Picture *> Ogg::XiphComment::pictureList()
{
  return d->pictureList;
}

ByteVector Ogg::XiphComment::render() const
{
  return render(true);
}

ByteVector Ogg::XiphComment::render(bool addFramingBit) const
{
  ByteVector data;

  // Add the vendor ID length and the vendor ID.  It's important to use the
  // length of the data(String::UTF8) rather than the length of the the string
  // since this is UTF8 text and there may be more characters in the data than
  // in the UTF16 string.

  ByteVector vendorData = d->vendorID.data(String::UTF8);

  data.append(ByteVector::fromUInt(vendorData.size(), false));
  data.append(vendorData);

  // Add the number of fields.

  data.append(ByteVector::fromUInt(fieldCount(), false));

  // Iterate over the the field lists.  Our iterator returns a
  // std::pair<String, StringList> where the first String is the field name and
  // the StringList is the values associated with that field.

  FieldListMap::ConstIterator it = d->fieldListMap.begin();
  for(; it != d->fieldListMap.end(); ++it) {

    // And now iterate over the values of the current list.

    String fieldName = (*it).first;
    StringList values = (*it).second;

    StringList::ConstIterator valuesIt = values.begin();
    for(; valuesIt != values.end(); ++valuesIt) {
      ByteVector fieldData = fieldName.data(String::UTF8);
      fieldData.append('=');
      fieldData.append((*valuesIt).data(String::UTF8));

      data.append(ByteVector::fromUInt(fieldData.size(), false));
      data.append(fieldData);
    }
  }

  for(PictureList::ConstIterator it = d->pictureList.begin(); it != d->pictureList.end(); ++it) {
    ByteVector picture = (*it)->render().toBase64();
    data.append(ByteVector::fromUInt(picture.size()+23,false));
    data.append("METADATA_BLOCK_PICTURE=");
    data.append(picture);
  }

  // Append the "framing bit".

  if(addFramingBit)
    data.append(char(1));

  return data;
}

////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////

void Ogg::XiphComment::parse(const ByteVector &data)
{
  // The first thing in the comment data is the vendor ID length, followed by a
  // UTF8 string with the vendor ID.

  uint pos = 0;

  const uint vendorLength = data.toUInt(0, false);
  pos += 4;

  d->vendorID = String(data.mid(pos, vendorLength), String::UTF8);
  pos += vendorLength;

  // Next the number of fields in the comment vector.

  const uint commentFields = data.toUInt(pos, false);
  pos += 4;

  if(commentFields > (data.size() - 8) / 4) {
    return;
  }

  for(uint i = 0; i < commentFields; i++) {

    // Each comment field is in the format "KEY=value" in a UTF8 string and has
    // 4 bytes before the text starts that gives the length.

    const uint commentLength = data.toUInt(pos, false);
    pos += 4;

    ByteVector entry = data.mid(pos, commentLength);

    // Don't go past data end
    pos+=commentLength;
    if (pos>data.size())
      break;

    // Handle Pictures separately
    if(entry.startsWith("METADATA_BLOCK_PICTURE=")) {

      // Decode base64 picture data
      ByteVector picturedata = entry.mid(23, entry.size()-23).fromBase64();

      if(picturedata.size()==0) {
        debug("Empty picture data. Discarding content");
        continue;
        }

      FLAC::Picture * picture = new FLAC::Picture();
      if(picture->parse(picturedata))
        d->pictureList.append(picture);
      else
        debug("Unable to parse METADATA_BLOCK_PICTURE. Discarding content.");
    }
    else {

      // Check for field separator
      int sep = entry.find('=');
      if (sep == -1)
        break;

      // Parse key and value
      String key = String(entry.mid(0,sep), String::UTF8);
      String value = String(entry.mid(sep+1, commentLength-sep), String::UTF8);
      addField(key, value, false);
    }
  }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <time.h>
#include "../Eigen/Dense"

using namespace Eigen;

// Gaussian elimination
// [ A | b ] = [ U | c ]
bool GaussElimination(const MatrixXf &a, const VectorXf &b, MatrixXf &u, VectorXf &c) {
	// 'a' should be a square matrix
	assert(a.rows() == a.cols());

	// right hand side vector
	c = b;

	// no pivoting upper triangular matrix 'nu' elimination begin with 'a'
	MatrixXf nu = a;

	// row_indexes has row order of 'nu'
	ArrayXi row_indexes(a.rows());
	for (int r = 0; r < a.rows(); r++) {
		row_indexes(r) = r;
	}

	// 'i' is diagonal index of the matrix
	for (int i = 0; i < a.rows(); i++) {
		// find real pivot index
		int pivot_index = row_indexes[i];
		float maximum = abs(nu(pivot_index, i));
		for (int r = i + 1; r < a.rows(); r++) {
			float value = abs(nu(row_indexes[r], i));

			if (value > maximum) {
				pivot_index = row_indexes[r];
				maximum = value;
			}
		}

		// if row exchange is required
		if (pivot_index > i) {
			// swap pivot index with current row index
			std::swap(row_indexes[i], row_indexes[pivot_index]);
			std::swap(c[i], c[pivot_index]);
		}

		// get pivot value
		float pivot = nu(row_indexes[i], i);
		if (pivot == 0.0f) {
			// abandon decomposition if pivot does not exist
			return false;
		}

		for (int r = i + 1; r < a.rows(); r++) {
			// scaler for subtract a row
			float scaler = nu(row_indexes[r], i) / pivot;

			// subtract a row from scaled pivot row
			for (int c = i; c < a.cols(); c++) {
				nu(row_indexes[r], c) -= scaler * nu(row_indexes[i], c);
			}
			c[r] -= scaler * c[i];
		}
	}

	// now row exchanges happen
	for (int r = 0; r < a.rows(); r++) {
		u.row(r) = nu.row(row_indexes[r]);
	}

	return true;
}

// Solve Ux = b, U is upper triangular matrix
const VectorXf SolveUTriangular(const MatrixXf &u, const VectorXf &b) {
	VectorXf x(b.rows());

	for (int r = u.rows() - 1; r >= 0; r--) {
		float k = 0;

		for (int c = r + 1; c < u.cols(); c++) {
			k += u(r, c) * x(c);
		}

		x(r) = (b(r) - k) / u(r, r);
	}

	return x;
}

// Solve Ax = b with gaussian elimination
bool SolveGaussElimination(const MatrixXf &a, const VectorXf &b, VectorXf &x) {
	MatrixXf u(a.rows(), a.cols());
	VectorXf c(b.rows());

	if (!GaussElimination(a, b, u, c)) {
		return false;
	}

	//float determinant = u.diagonal().prod();

	x = SolveUTriangular(u, c);

	return true;
}

void TestGaussElimination() {
	const int DIMENSION = 4;

	MatrixXf a(DIMENSION, DIMENSION);
	a << MatrixXf::Random(DIMENSION, DIMENSION);

	VectorXf b(DIMENSION);
	b << VectorXf::Random(DIMENSION);

	VectorXf x;
	bool invertible = ::SolveGaussElimination(a, b, x);

	if (!invertible) {
		std::cout << "ERROR: A is not invertible !!\n";
		return;
	}

	std::cout << "A =\n";
	std::cout << a << "\n\n";

	std::cout << "b =\n";
	std::cout << b << "\n\n";

	std::cout << "Ax = b, x =\n";
	std::cout << x << "\n\n";

	PartialPivLU<MatrixXf> decomp(a);
	x = decomp.solve(b);
	std::cout << "Ax = b, x =\n";
	std::cout << x << "\n\n";
}

int main() {
	srand((unsigned int)time(0));

	TestGaussElimination();

	getchar();

	return 0;
}
<commit_msg>Code adjustments<commit_after>#include <iostream>
#include <algorithm>
#include <time.h>
#include "../Eigen/Dense"

using namespace Eigen;

// Gaussian elimination
// [ A | b ] = [ U | c ]
bool GaussElimination(const MatrixXf &a, const VectorXf &b, MatrixXf &u, VectorXf &c) {
	// 'a' should be a square matrix
	assert(a.rows() == a.cols());

	// left hand side matrix A
	u = a;

	// right hand side vector b
	c = b;

	// 'i' is diagonal index of the matrix
	for (int i = 0; i < a.rows(); i++) {
		// find real pivot index
		int pivot_index = i;
		float maximum = abs(u(pivot_index, i));
		for (int r = i + 1; r < a.rows(); r++) {
			float value = abs(u(r, i));

			if (value > maximum) {
				pivot_index = r;
				maximum = value;
			}
		}

		// if row exchange is required
		if (pivot_index > i) {
			u.row(i).swap(u.row(pivot_index));
			std::swap(c[i], c[pivot_index]);
		}

		// get pivot value
		float pivot = u(i, i);
		if (pivot == 0.0f) {
			// abandon decomposition if pivot does not exist
			return false;
		}

		for (int r = i + 1; r < a.rows(); r++) {
			// scaler for subtract a row
			float scaler = u(r, i) / pivot;

			// subtract a row from scaled pivot row
			for (int c = i; c < a.cols(); c++) {
				u(r, c) -= scaler * u(i, c);
			}
			c[r] -= scaler * c[i];
		}
	}

	return true;
}

// Solve Ux = b, U is upper triangular matrix
const VectorXf SolveUTriangular(const MatrixXf &u, const VectorXf &b) {
	VectorXf x(b.rows());

	for (int r = u.rows() - 1; r >= 0; r--) {
		float k = 0;

		for (int c = r + 1; c < u.cols(); c++) {
			k += u(r, c) * x(c);
		}

		x(r) = (b(r) - k) / u(r, r);
	}

	return x;
}

// Solve Ax = b with gaussian elimination
bool SolveGaussElimination(const MatrixXf &a, const VectorXf &b, VectorXf &x) {
	MatrixXf u(a.rows(), a.cols());
	VectorXf c(b.rows());

	if (!GaussElimination(a, b, u, c)) {
		return false;
	}

	std::cout << u << std::endl;

	//float determinant = u.diagonal().prod();

	x = SolveUTriangular(u, c);

	return true;
}

void TestGaussElimination() {
	const int DIMENSION = 4;

	MatrixXf a(DIMENSION, DIMENSION);
	a << MatrixXf::Random(DIMENSION, DIMENSION);

	VectorXf b(DIMENSION);
	b << VectorXf::Random(DIMENSION);

	VectorXf x;
	bool invertible = ::SolveGaussElimination(a, b, x);

	if (!invertible) {
		std::cout << "ERROR: A is not invertible !!\n";
		return;
	}

	std::cout << "A =\n";
	std::cout << a << "\n\n";

	std::cout << "b =\n";
	std::cout << b << "\n\n";

	std::cout << "Ax = b, x =\n";
	std::cout << x << "\n\n";

	PartialPivLU<MatrixXf> decomp(a);
	x = decomp.solve(b);
	std::cout << "Ax = b, x =\n";
	std::cout << x << "\n\n";
}

int main() {
	srand((unsigned int)time(0));

	TestGaussElimination();

	getchar();

	return 0;
}
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_DEBUG_HH
#define DUNE_STUFF_DEBUG_HH

#include <cstring>

#define SEGFAULT {int*J=0;*J=9;}

//! from right/bottom limiter for file paths
const char*  rightPathLimiter( const char* path,  int depth = 2  )
{
	char* c = new char[255];
	strcpy(c,path);
	const char* p = strtok( c, "/" );
	int i = 0;
	while ( p && i < depth ){
		p = strtok( NULL, "/" );
	}
	p = strtok( NULL, "\0" );
	return p;
}

#ifndef NDEBUG
	#ifndef LOGIC_ERROR
		#include <stdexcept>
		#include <sstream>
		#define LOGIC_ERROR \
			{\
				std::stringstream ss; ss << __FILE__ << ":" << __LINE__ << " should never be called"; \
				throw std::logic_error(ss.str());\
			}
	#endif
#else
	#define LOGIC_ERROR
#endif

char* copy(const char* s) { int l=strlen(s)+1; char* t = new char[l];  for(int i=0;i<l;i++) { t[i] = s[i]; } return t; }
#define __CLASS__ strtok(copy(__PRETTY_FUNCTION__),"<(")

#ifndef NDEBUG
	#define NEEDS_IMPLEMENTATION\
			{\
				 std::stringstream ss; ss << " implementation missing: " << __CLASS__ << " -- "<< rightPathLimiter(__FILE__ )<< ":" << __LINE__ ; \
				 std::cerr << ss.str() << std::endl;\
			}
#else
	#define NEEDS_IMPLEMENTATION
#endif //NDEBUG

class assert_exception : public std::runtime_error
{
  public:
   assert_exception(std::string msg) : std::runtime_error(msg) {}
};

namespace Stuff {
class singlerun_abort_exception : public std::runtime_error
{
  public:
   singlerun_abort_exception(std::string msg) : std::runtime_error(msg) {}
};
}

#ifndef NDEBUG
#define ASSERT_EXCEPTION(cond,msg) if(!(cond))\
	{ std::string rmsg ( std::string(__FILE__) + std::string(":") + Stuff::toString(__LINE__) + std::string("\n") + std::string(msg) );  \
		throw assert_exception(rmsg); }
#else
	#define ASSERT_EXCEPTION(cond,msg)
#endif

#if 1 /*  there should be no more any compilers needing the "#else" version */
	#define UNUSED(identifier) /* identifier */
#else  /*  stupid, broken compiler */
	#define UNUSED(identifier) identifier
#endif

/*  some arguments are only used in debug mode, but unused in release one */
#ifndef NDEBUG
	#define UNUSED_UNLESS_DEBUG(param)  param
#else
	#define UNUSED_UNLESS_DEBUG(param)  UNUSED(param)
#endif

#endif // DUNE_STUFF_DEBUG_HH
<commit_msg>new ASSERT_LT ASSERT_EQ macros, you want to use them<commit_after>#ifndef DUNE_STUFF_DEBUG_HH
#define DUNE_STUFF_DEBUG_HH

#include <cstring>
#include <boost/assert.hpp>
#include <boost/format.hpp>

#define SEGFAULT {int*J=0;*J=9;}

//! from right/bottom limiter for file paths
const char*  rightPathLimiter( const char* path,  int depth = 2  )
{
	char* c = new char[255];
	strcpy(c,path);
	const char* p = strtok( c, "/" );
	int i = 0;
	while ( p && i < depth ){
		p = strtok( NULL, "/" );
	}
	p = strtok( NULL, "\0" );
	return p;
}

#ifndef NDEBUG
	#ifndef LOGIC_ERROR
		#include <stdexcept>
		#include <sstream>
		#define LOGIC_ERROR \
			{\
				std::stringstream ss; ss << __FILE__ << ":" << __LINE__ << " should never be called"; \
				throw std::logic_error(ss.str());\
			}
	#endif
#else
	#define LOGIC_ERROR
#endif

char* copy(const char* s) { int l=strlen(s)+1; char* t = new char[l];  for(int i=0;i<l;i++) { t[i] = s[i]; } return t; }
#define __CLASS__ strtok(copy(__PRETTY_FUNCTION__),"<(")

#ifndef NDEBUG
	#define NEEDS_IMPLEMENTATION\
			{\
				 std::stringstream ss; ss << " implementation missing: " << __CLASS__ << " -- "<< rightPathLimiter(__FILE__ )<< ":" << __LINE__ ; \
				 std::cerr << ss.str() << std::endl;\
			}
#else
	#define NEEDS_IMPLEMENTATION
#endif //NDEBUG

class assert_exception : public std::runtime_error
{
  public:
   assert_exception(std::string msg) : std::runtime_error(msg) {}
};

namespace Stuff {
class singlerun_abort_exception : public std::runtime_error
{
  public:
   singlerun_abort_exception(std::string msg) : std::runtime_error(msg) {}
};
}

#ifndef NDEBUG
#define ASSERT_EXCEPTION(cond,msg) if(!(cond))\
	{ std::string rmsg ( std::string(__FILE__) + std::string(":") + Stuff::toString(__LINE__) + std::string("\n") + std::string(msg) );  \
		throw assert_exception(rmsg); }
#else
	#define ASSERT_EXCEPTION(cond,msg)
#endif

#if 1 /*  there should be no more any compilers needing the "#else" version */
	#define UNUSED(identifier) /* identifier */
#else  /*  stupid, broken compiler */
	#define UNUSED(identifier) identifier
#endif

/*  some arguments are only used in debug mode, but unused in release one */
#ifndef NDEBUG
	#define UNUSED_UNLESS_DEBUG(param)  param
#else
	#define UNUSED_UNLESS_DEBUG(param)  UNUSED(param)
#endif

#define ASSERT_LT( expt, actual ) \
    BOOST_ASSERT_MSG( (expt<actual),  (boost::format("assertion %1% < %2% failed: %3% >= %4%") % #expt % #actual % expt % actual).str().c_str() )
#define ASSERT_EQ( expt, actual ) \
    BOOST_ASSERT_MSG( (expt==actual),  (boost::format("assertion %1% == %2% failed: %3% != %4%") % #expt % #actual % expt % actual).str().c_str() )

#endif // DUNE_STUFF_DEBUG_HH
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_DEBUG_HH
#define DUNE_STUFF_DEBUG_HH

#define SEGFAULT {int*J=0;*J=9;}

//! from right/bottom limiter for file paths
const char*  rightPathLimiter( const char* path,  int depth = 2  )
{
	char* c = new char[255];
	strcpy(c,path);
	const char* p = strtok( c, "/" );
	int i = 0;
	while ( p && i < depth ){
		p = strtok( NULL, "/" );
	}
	p = strtok( NULL, "\0" );
	return p;
}

#ifndef NDEBUG
	#ifndef LOGIC_ERROR
		#include <stdexcept>
		#include <sstream>
		#define LOGIC_ERROR \
			{\
				std::stringstream ss; ss << __FILE__ << ":" << __LINE__ << " should never be called"; \
				throw std::logic_error(ss.str());\
			}
	#endif
#else
	#define LOGIC_ERROR
#endif

char* copy(const char* s) { int l=strlen(s)+1; char* t = new char[l];  for(int i=0;i<l;i++) { t[i] = s[i]; } return t; }
#define __CLASS__ strtok(copy(__PRETTY_FUNCTION__),"<(")

#ifndef NDEBUG
	#define NEEDS_IMPLEMENTATION\
			{\
				 std::stringstream ss; ss << " implementation missing: " << __CLASS__ << " -- "<< rightPathLimiter(__FILE__ )<< ":" << __LINE__ ; \
				 std::cerr << ss.str() << std::endl;\
			}
#else
	#define NEEDS_IMPLEMENTATION
#endif //NDEBUG

class assert_exception : public std::runtime_error
{
  public:
   assert_exception(std::string msg) : std::runtime_error(msg) {};
};

#ifndef NDEBUG
#define ASSERT_EXCEPTION(cond,msg) if(!(cond))\
	{ std::string rmsg ( std::string(__FILE__) + std::string(":") + Stuff::toString(__LINE__) + std::string("\n") + std::string(msg) );  \
		throw assert_exception(rmsg); }
#else
	#define ASSERT_EXCEPTION(cond,msg)
#endif

#endif // DUNE_STUFF_DEBUG_HH
<commit_msg>new exception type<commit_after>#ifndef DUNE_STUFF_DEBUG_HH
#define DUNE_STUFF_DEBUG_HH

#define SEGFAULT {int*J=0;*J=9;}

//! from right/bottom limiter for file paths
const char*  rightPathLimiter( const char* path,  int depth = 2  )
{
	char* c = new char[255];
	strcpy(c,path);
	const char* p = strtok( c, "/" );
	int i = 0;
	while ( p && i < depth ){
		p = strtok( NULL, "/" );
	}
	p = strtok( NULL, "\0" );
	return p;
}

#ifndef NDEBUG
	#ifndef LOGIC_ERROR
		#include <stdexcept>
		#include <sstream>
		#define LOGIC_ERROR \
			{\
				std::stringstream ss; ss << __FILE__ << ":" << __LINE__ << " should never be called"; \
				throw std::logic_error(ss.str());\
			}
	#endif
#else
	#define LOGIC_ERROR
#endif

char* copy(const char* s) { int l=strlen(s)+1; char* t = new char[l];  for(int i=0;i<l;i++) { t[i] = s[i]; } return t; }
#define __CLASS__ strtok(copy(__PRETTY_FUNCTION__),"<(")

#ifndef NDEBUG
	#define NEEDS_IMPLEMENTATION\
			{\
				 std::stringstream ss; ss << " implementation missing: " << __CLASS__ << " -- "<< rightPathLimiter(__FILE__ )<< ":" << __LINE__ ; \
				 std::cerr << ss.str() << std::endl;\
			}
#else
	#define NEEDS_IMPLEMENTATION
#endif //NDEBUG

class assert_exception : public std::runtime_error
{
  public:
   assert_exception(std::string msg) : std::runtime_error(msg) {};
};

namespace Stuff {
class singlerun_abort_exception : public std::runtime_error
{
  public:
   singlerun_abort_exception(std::string msg) : std::runtime_error(msg) {};
};
}

#ifndef NDEBUG
#define ASSERT_EXCEPTION(cond,msg) if(!(cond))\
	{ std::string rmsg ( std::string(__FILE__) + std::string(":") + Stuff::toString(__LINE__) + std::string("\n") + std::string(msg) );  \
		throw assert_exception(rmsg); }
#else
	#define ASSERT_EXCEPTION(cond,msg)
#endif

#endif // DUNE_STUFF_DEBUG_HH
<|endoftext|>


<commit_before>#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <fstream>
#include <iostream>
#include <vector>

struct Params {
	bool hasFile;
	std::string fileName;
};

Params ParseArgs(int argc, char **argv) {
	Params p;

	std::vector<std::string> args(argv + 1, argv + argc);

	return p;
}

class NullEventHandler: public YAML::EventHandler
{
public:
	virtual void OnDocumentStart(const YAML::Mark&) {}
	virtual void OnDocumentEnd() {}

	virtual void OnNull(const YAML::Mark&, YAML::anchor_t) {}
	virtual void OnAlias(const YAML::Mark&, YAML::anchor_t) {}
	virtual void OnScalar(const YAML::Mark&, const std::string&, YAML::anchor_t, const std::string&) {}

	virtual void OnSequenceStart(const YAML::Mark&, const std::string&, YAML::anchor_t) {}
	virtual void OnSequenceEnd() {}

	virtual void OnMapStart(const YAML::Mark&, const std::string&, YAML::anchor_t) {}
	virtual void OnMapEnd() {}
};

void parse(std::istream& input)
{
	try {
#if YAML_CPP_OLD_API
		YAML::Parser parser(input);
		YAML::Node doc;
		while(parser.GetNextDocument(doc)) {
			YAML::Emitter emitter;
			emitter << doc;
			std::cout << emitter.c_str() << "\n";
		}
#else
		// TODO: Parse with new API
#endif
	} catch(const YAML::Exception& e) {
		std::cerr << e.what() << "\n";
	}
}

int main(int argc, char **argv)
{
	Params p = ParseArgs(argc, argv);

	if(argc > 1) {
		std::ifstream fin;
		fin.open(argv[1]);
		parse(fin);
	} else {
		parse(std::cin);
	}

	return 0;
}
<commit_msg>Set up util/parse for the new API<commit_after>#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <fstream>
#include <iostream>
#include <vector>

struct Params {
	bool hasFile;
	std::string fileName;
};

Params ParseArgs(int argc, char **argv) {
	Params p;

	std::vector<std::string> args(argv + 1, argv + argc);

	return p;
}

class NullEventHandler: public YAML::EventHandler
{
public:
	virtual void OnDocumentStart(const YAML::Mark&) {}
	virtual void OnDocumentEnd() {}

	virtual void OnNull(const YAML::Mark&, YAML::anchor_t) {}
	virtual void OnAlias(const YAML::Mark&, YAML::anchor_t) {}
	virtual void OnScalar(const YAML::Mark&, const std::string&, YAML::anchor_t, const std::string&) {}

	virtual void OnSequenceStart(const YAML::Mark&, const std::string&, YAML::anchor_t) {}
	virtual void OnSequenceEnd() {}

	virtual void OnMapStart(const YAML::Mark&, const std::string&, YAML::anchor_t) {}
	virtual void OnMapEnd() {}
};

void parse(std::istream& input)
{
	try {
#if YAML_CPP_OLD_API
		YAML::Parser parser(input);
		YAML::Node doc;
		while(parser.GetNextDocument(doc)) {
			YAML::Emitter emitter;
			emitter << doc;
			std::cout << emitter.c_str() << "\n";
		}
#else
		YAML::Node doc = YAML::Parse(input);
		std::cout << doc << "\n";
#endif
	} catch(const YAML::Exception& e) {
		std::cerr << e.what() << "\n";
	}
}

int main(int argc, char **argv)
{
	Params p = ParseArgs(argc, argv);

	if(argc > 1) {
		std::ifstream fin;
		fin.open(argv[1]);
		parse(fin);
	} else {
		parse(std::cin);
	}

	return 0;
}
<|endoftext|>


<commit_before>#define _USE_MATH_DEFINES
#include <cmath>
#include "Cylinder.h"
#include <MathGeoLib/include/Math/MathFunc.h>

::Cylinder::Cylinder(GLfloat radius, GLfloat height) :
	Primitive(), Radius(radius), Height(height) {}

::Cylinder::Cylinder(const float3& position, const Quat& rotation, GLfloat radius, GLfloat height) :
	Primitive(position, rotation), Radius(radius), Height(height) {}

::Cylinder::Cylinder(const float3& position, const Quat& rotation, const float3& color, GLfloat radius, GLfloat height) :
	Primitive(position, rotation, color), Radius(radius), Height(height) {}

::Cylinder::~Cylinder() {}

void ::Cylinder::Draw()
{
	glPushMatrix();
	glTranslatef(Position.x, Position.y, Position.z);
	float3 axis = Rotation.Axis();
	glRotatef(RadToDeg(Rotation.Angle()), axis.x, axis.y, axis.z);

	glColor3f(Color.x, Color.y, Color.z);

	GLfloat x = 0.0;
	GLfloat y = 0.0;
	GLfloat angle = 0.0;
	GLfloat angle_stepsize = 0.1f;

	/** Draw the tube */
	glBegin(GL_QUAD_STRIP);
	angle = 0.0;
	while (angle < 2 * M_PI) {
		x = Radius * cos(angle);
		y = Radius * sin(angle);
		glVertex3f(x, y, Height);
		glVertex3f(x, y, 0.0);
		angle = angle + angle_stepsize;
	}
	glVertex3f(Radius, 0.0, Height);
	glVertex3f(Radius, 0.0, 0.0);
	glEnd();

	/** Draw the circle on top of cylinder */
	glBegin(GL_POLYGON);
	angle = 0.0;
	while (angle < 2 * M_PI) {
		x = Radius * cos(angle);
		y = Radius * sin(angle);
		glVertex3f(x, y, Height);
		angle = angle + angle_stepsize;
	}
	glVertex3f(Radius, 0.0, Height);
	glEnd();

	glPopMatrix();
}<commit_msg>Add bottom circle on cylinder<commit_after>#define _USE_MATH_DEFINES
#include <cmath>
#include "Cylinder.h"
#include <MathGeoLib/include/Math/MathFunc.h>

::Cylinder::Cylinder(GLfloat radius, GLfloat height) :
	Primitive(), Radius(radius), Height(height) {}

::Cylinder::Cylinder(const float3& position, const Quat& rotation, GLfloat radius, GLfloat height) :
	Primitive(position, rotation), Radius(radius), Height(height) {}

::Cylinder::Cylinder(const float3& position, const Quat& rotation, const float3& color, GLfloat radius, GLfloat height) :
	Primitive(position, rotation, color), Radius(radius), Height(height) {}

::Cylinder::~Cylinder() {}

void ::Cylinder::Draw()
{
	glPushMatrix();
	glTranslatef(Position.x, Position.y, Position.z);
	float3 axis = Rotation.Axis();
	glRotatef(RadToDeg(Rotation.Angle()), axis.x, axis.y, axis.z);

	glColor3f(Color.x, Color.y, Color.z);

	GLfloat x = 0.0;
	GLfloat y = 0.0;
	GLfloat angle = 0.0;
	GLfloat angle_stepsize = 0.1f;

	/** Draw the tube */
	glBegin(GL_QUAD_STRIP);
	angle = 0.0;
	while (angle < 2 * M_PI) {
		x = Radius * cos(angle);
		y = Radius * sin(angle);
		glVertex3f(x, y, Height);
		glVertex3f(x, y, 0.0);
		angle = angle + angle_stepsize;
	}
	glVertex3f(Radius, 0.0, Height);
	glVertex3f(Radius, 0.0, 0.0);
	glEnd();

	/** Draw the circle on top of cylinder */
	glBegin(GL_POLYGON);
	angle = 0.0;
	while (angle < 2 * M_PI) {
		x = Radius * cos(angle);
		y = Radius * sin(angle);
		glVertex3f(x, y, Height);
		angle = angle + angle_stepsize;
	}
	glVertex3f(Radius, 0.0, Height);
	glEnd();

	/** Draw the circle on bottom of cylinder */
	glBegin(GL_POLYGON);
	angle = 2 * M_PI;
	while (angle > 0.0) {
		x = Radius * cos(angle);
		y = Radius * sin(angle);
		glVertex3f(x, y, 0.0);
		angle = angle - angle_stepsize;
	}
	glVertex3f(Radius, 0.0, 0.0);
	glEnd();

	glPopMatrix();
}<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file    AliFMDBaseDA.cxx
    @author  Hans Hjersing Dalsgaard <canute@nbi.dk>
    @date    Wed Mar 26 11:30:45 2008
    @brief   Base class for detector algorithms.
*/
//
//This is the implementation of the (virtual) base class for the FMD detector
//algorithms(DA). It implements the creation of the relevant containers and handles the
//loop over the raw data. The derived classes can control the parameters and action
//to be taken making this the base class for the Pedestal, Gain and Physics DA.
//

#include "AliFMDBaseDA.h"
#include "iostream"

#include "AliFMDRawReader.h"
#include "AliLog.h"
//_____________________________________________________________________
ClassImp(AliFMDBaseDA)

//_____________________________________________________________________
AliFMDBaseDA::AliFMDBaseDA() : TNamed(),
  fDiagnosticsFilename("diagnosticsHistograms.root"),
  fOutputFile(),
  fConditionsFile(),
  fSaveHistograms(kFALSE),
  fDetectorArray(),
  fRequiredEvents(0),
  fCurrentEvent(0)
{
  fDetectorArray.SetOwner();
  fConditionsFile.open("conditions.csv");
}
//_____________________________________________________________________
AliFMDBaseDA::AliFMDBaseDA(const AliFMDBaseDA & baseDA) :
  TNamed(baseDA),
  fDiagnosticsFilename(baseDA.fDiagnosticsFilename),
  fOutputFile(),
  fConditionsFile(),
  fSaveHistograms(baseDA.fSaveHistograms),
  fDetectorArray(baseDA.fDetectorArray),
  fRequiredEvents(baseDA.fRequiredEvents),
  fCurrentEvent(baseDA.fCurrentEvent)
{
  fDetectorArray.SetOwner();

}

//_____________________________________________________________________
AliFMDBaseDA::~AliFMDBaseDA() {

  //destructor

}

//_____________________________________________________________________
void AliFMDBaseDA::Run(AliRawReader* reader) {

  InitContainer();

  Init();

  TFile* diagFile = 0;
  if(fSaveHistograms)
    {
      diagFile = TFile::Open(fDiagnosticsFilename,"RECREATE");
      for(UShort_t det=1;det<=3;det++) {
	UShort_t FirstRing = (det == 1 ? 1 : 0);

	for (UShort_t ir = FirstRing; ir < 2; ir++) {
	  Char_t   ring = (ir == 0 ? 'O' : 'I');
	  UShort_t nsec = (ir == 0 ? 40  : 20);
	  UShort_t nstr = (ir == 0 ? 256 : 512);

	  gDirectory->cd(Form("%s:/",fDiagnosticsFilename));
	  gDirectory->mkdir(Form("FMD%d%c",det,ring),Form("FMD%d%c",det,ring));
	  for(UShort_t sec =0; sec < nsec;  sec++)  {
	    gDirectory->cd(Form("%s:/FMD%d%c",fDiagnosticsFilename,det,ring));
	    gDirectory->mkdir(Form("sector_%d",sec));
	    for(UShort_t strip = 0; strip < nstr; strip++) {
	      gDirectory->cd(Form("%s:/FMD%d%c/sector_%d",fDiagnosticsFilename,det,ring,sec));
	      gDirectory->mkdir(Form("strip_%d",strip));

	     }
	  }
	}
      }

    }

  reader->Reset();

  AliFMDRawReader* fmdReader = new AliFMDRawReader(reader,0);
  TClonesArray* digitArray   = new TClonesArray("AliFMDDigit",0);

  WriteConditionsData();

  reader->NextEvent();
  reader->NextEvent();

  for(Int_t n =1;n <= GetRequiredEvents(); n++)
    {
      if(!reader->NextEvent())
	continue;

      SetCurrentEvent(*(reader->GetEventId()));

      digitArray->Clear();
      fmdReader->ReadAdcs(digitArray);

      //std::cout<<"In event # "<< *(reader->GetEventId()) << " with " <<digitArray->GetEntries()<<" digits     \r"<<std::flush;

      for(Int_t i = 0; i<digitArray->GetEntries();i++) {
	AliFMDDigit* digit = static_cast<AliFMDDigit*>(digitArray->At(i));
	FillChannels(digit);
      }

      FinishEvent();

    }
  AliInfo(Form("Looped over %d events",GetCurrentEvent()));
  WriteHeaderToFile();

  for(UShort_t det=1;det<=3;det++) {
    UShort_t FirstRing = (det == 1 ? 1 : 0);
    for (UShort_t ir = FirstRing; ir < 2; ir++) {
      Char_t   ring = (ir == 0 ? 'O' : 'I');
      UShort_t nsec = (ir == 0 ? 40  : 20);
      UShort_t nstr = (ir == 0 ? 256 : 512);
      for(UShort_t sec =0; sec < nsec;  sec++)  {
  	for(UShort_t strip = 0; strip < nstr; strip++) {
	  Analyse(det,ring,sec,strip);

  	}
      }
    }
  }

  if(fOutputFile.is_open()) {

    fOutputFile.write("# EOF\n",6);
    fOutputFile.close();

  }

  if(fSaveHistograms ) {
    AliInfo("Closing diagnostics file...please wait");
    diagFile->Close();
  }
}
//_____________________________________________________________________

void AliFMDBaseDA::InitContainer(){

  TObjArray* detArray;
  TObjArray* ringArray;
  TObjArray* sectorArray;

  for(UShort_t det=1;det<=3;det++) {
    detArray = new TObjArray();
    detArray->SetOwner();
    fDetectorArray.AddAtAndExpand(detArray,det);
    UShort_t FirstRing = (det == 1 ? 1 : 0);
    for (UShort_t ir = FirstRing; ir < 2; ir++) {
      Char_t   ring = (ir == 0 ? 'O' : 'I');
      UShort_t nsec = (ir == 0 ? 40  : 20);
      UShort_t nstr = (ir == 0 ? 256 : 512);
      ringArray = new TObjArray();
      ringArray->SetOwner();
      detArray->AddAtAndExpand(ringArray,ir);
      for(UShort_t sec =0; sec < nsec;  sec++)  {
	sectorArray = new TObjArray();
	sectorArray->SetOwner();
	ringArray->AddAtAndExpand(sectorArray,sec);
	for(UShort_t strip = 0; strip < nstr; strip++) {
	  AddChannelContainer(sectorArray, det, ring, sec, strip);
	}
      }
    }
  }
}

//_____________________________________________________________________
void AliFMDBaseDA::WriteConditionsData() {

  AliFMDParameters* pars       = AliFMDParameters::Instance();
  fConditionsFile.write(Form("# %s \n",pars->GetConditionsShuttleID()),14);
  fConditionsFile.write("# Sample Rate, timebins \n",25);

  UInt_t sampleRate = 4;
  UInt_t timebins   = 544;
  fConditionsFile     << sampleRate   << ','
		      << timebins     <<"\n";
  //if(fConditionsFile.is_open()) {
  //
  //  fConditionsFile.write("# EOF\n",6);
  //  fConditionsFile.close();

  //}

}

//_____________________________________________________________________
//
// EOF
//
<commit_msg>New version with sample rate map and progress meter<commit_after>/**************************************************************************
 * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file    AliFMDBaseDA.cxx
    @author  Hans Hjersing Dalsgaard <canute@nbi.dk>
    @date    Wed Mar 26 11:30:45 2008
    @brief   Base class for detector algorithms.
*/
//
//This is the implementation of the (virtual) base class for the FMD detector
//algorithms(DA). It implements the creation of the relevant containers and handles the
//loop over the raw data. The derived classes can control the parameters and action
//to be taken making this the base class for the Pedestal, Gain and Physics DA.
//

#include "AliFMDBaseDA.h"
#include "iostream"

#include "AliFMDRawReader.h"
#include "AliFMDCalibSampleRate.h"
#include "AliLog.h"
//_____________________________________________________________________
ClassImp(AliFMDBaseDA)

//_____________________________________________________________________
AliFMDBaseDA::AliFMDBaseDA() : TNamed(),
  fDiagnosticsFilename("diagnosticsHistograms.root"),
  fOutputFile(),
  fConditionsFile(),
  fSaveHistograms(kFALSE),
  fDetectorArray(),
  fRequiredEvents(0),
  fCurrentEvent(0)
{
  fDetectorArray.SetOwner();
  fConditionsFile.open("conditions.csv");
}
//_____________________________________________________________________
AliFMDBaseDA::AliFMDBaseDA(const AliFMDBaseDA & baseDA) :
  TNamed(baseDA),
  fDiagnosticsFilename(baseDA.fDiagnosticsFilename),
  fOutputFile(),
  fConditionsFile(),
  fSaveHistograms(baseDA.fSaveHistograms),
  fDetectorArray(baseDA.fDetectorArray),
  fRequiredEvents(baseDA.fRequiredEvents),
  fCurrentEvent(baseDA.fCurrentEvent)
{
  fDetectorArray.SetOwner();

}

//_____________________________________________________________________
AliFMDBaseDA::~AliFMDBaseDA() {

  //destructor

}

//_____________________________________________________________________
void AliFMDBaseDA::Run(AliRawReader* reader) {

  InitContainer();

  Init();

  TFile* diagFile = 0;
  if(fSaveHistograms)
    {
      diagFile = TFile::Open(fDiagnosticsFilename,"RECREATE");
      for(UShort_t det=1;det<=3;det++) {
	UShort_t FirstRing = (det == 1 ? 1 : 0);

	for (UShort_t ir = FirstRing; ir < 2; ir++) {
	  Char_t   ring = (ir == 0 ? 'O' : 'I');
	  UShort_t nsec = (ir == 0 ? 40  : 20);
	  UShort_t nstr = (ir == 0 ? 256 : 512);

	  gDirectory->cd(Form("%s:/",fDiagnosticsFilename));
	  gDirectory->mkdir(Form("FMD%d%c",det,ring),Form("FMD%d%c",det,ring));
	  for(UShort_t sec =0; sec < nsec;  sec++)  {
	    gDirectory->cd(Form("%s:/FMD%d%c",fDiagnosticsFilename,det,ring));
	    gDirectory->mkdir(Form("sector_%d",sec));
	    for(UShort_t strip = 0; strip < nstr; strip++) {
	      gDirectory->cd(Form("%s:/FMD%d%c/sector_%d",fDiagnosticsFilename,det,ring,sec));
	      gDirectory->mkdir(Form("strip_%d",strip));

	     }
	  }
	}
      }

    }

  reader->Reset();

  AliFMDRawReader* fmdReader = new AliFMDRawReader(reader,0);
  TClonesArray* digitArray   = new TClonesArray("AliFMDDigit",0);

  WriteConditionsData();

  reader->NextEvent();
  reader->NextEvent();
  int lastProgress = 0;

  for(Int_t n =1;n <= GetRequiredEvents(); n++)
    {
      if(!reader->NextEvent())
	continue;

      SetCurrentEvent(*(reader->GetEventId()));

      digitArray->Clear();
      fmdReader->ReadAdcs(digitArray);

      //std::cout<<"In event # "<< *(reader->GetEventId()) << " with " <<digitArray->GetEntries()<<" digits     \r"<<std::flush;

      for(Int_t i = 0; i<digitArray->GetEntries();i++) {
	AliFMDDigit* digit = static_cast<AliFMDDigit*>(digitArray->At(i));
	FillChannels(digit);
      }

      FinishEvent();
      int progress = int((n *100)/ GetRequiredEvents()) ;
      if (progress <= lastProgress) continue;
      lastProgress = progress;
      std::cout << "Progress: " << lastProgress << " / 100 " << std::endl;

    }
  AliInfo(Form("Looped over %d events",GetCurrentEvent()));
  WriteHeaderToFile();

  for(UShort_t det=1;det<=3;det++) {
    UShort_t FirstRing = (det == 1 ? 1 : 0);
    for (UShort_t ir = FirstRing; ir < 2; ir++) {
      Char_t   ring = (ir == 0 ? 'O' : 'I');
      UShort_t nsec = (ir == 0 ? 40  : 20);
      UShort_t nstr = (ir == 0 ? 256 : 512);
      for(UShort_t sec =0; sec < nsec;  sec++)  {
  	for(UShort_t strip = 0; strip < nstr; strip++) {
	  Analyse(det,ring,sec,strip);

  	}
      }
    }
  }

  if(fOutputFile.is_open()) {

    fOutputFile.write("# EOF\n",6);
    fOutputFile.close();

  }

  if(fSaveHistograms ) {
    AliInfo("Closing diagnostics file...please wait");
    diagFile->Close();
  }
}
//_____________________________________________________________________

void AliFMDBaseDA::InitContainer(){

  TObjArray* detArray;
  TObjArray* ringArray;
  TObjArray* sectorArray;

  for(UShort_t det=1;det<=3;det++) {
    detArray = new TObjArray();
    detArray->SetOwner();
    fDetectorArray.AddAtAndExpand(detArray,det);
    UShort_t FirstRing = (det == 1 ? 1 : 0);
    for (UShort_t ir = FirstRing; ir < 2; ir++) {
      Char_t   ring = (ir == 0 ? 'O' : 'I');
      UShort_t nsec = (ir == 0 ? 40  : 20);
      UShort_t nstr = (ir == 0 ? 256 : 512);
      ringArray = new TObjArray();
      ringArray->SetOwner();
      detArray->AddAtAndExpand(ringArray,ir);
      for(UShort_t sec =0; sec < nsec;  sec++)  {
	sectorArray = new TObjArray();
	sectorArray->SetOwner();
	ringArray->AddAtAndExpand(sectorArray,sec);
	for(UShort_t strip = 0; strip < nstr; strip++) {
	  AddChannelContainer(sectorArray, det, ring, sec, strip);
	}
      }
    }
  }
}

//_____________________________________________________________________
void AliFMDBaseDA::WriteConditionsData() {

  AliFMDParameters* pars       = AliFMDParameters::Instance();
  fConditionsFile.write(Form("# %s \n",pars->GetConditionsShuttleID()),14);
  fConditionsFile.write("# Sample Rate, timebins \n",25);

  UInt_t defSampleRate = 4;
  UInt_t timebins   = 544;
  AliFMDCalibSampleRate* sampleRate = new AliFMDCalibSampleRate();
  for(UShort_t det=1;det<=3;det++) {
    UShort_t FirstRing = (det == 1 ? 1 : 0);
    for (UShort_t ir = FirstRing; ir < 2; ir++) {
      Char_t   ring = (ir == 0 ? 'O' : 'I');
      UShort_t nsec = (ir == 0 ? 40  : 20);
      UShort_t nstr = (ir == 0 ? 256 : 512);
      for(UShort_t sec =0; sec < nsec;  sec++)  {
	for(UShort_t strip = 0; strip < nstr; strip++) {
	  sampleRate->Set(det,ring,sec,strip,defSampleRate);
	}
      }
    }
  }

  pars->SetSampleRate(sampleRate);

  fConditionsFile     << defSampleRate   << ','
		      << timebins     <<"\n";

  if(fConditionsFile.is_open()) {

    //  fConditionsFile.write("# EOF\n",6);
    fConditionsFile.close();

  }

}

//_____________________________________________________________________
//
// EOF
//
<|endoftext|>


<commit_before>#include "tst_qlistobject.h"

void TST_QListObject::test()
{
    CWF::QListObject listObj;

    listObj.add(new QObject);
    listObj.add(new QObject);

    QVERIFY2(listObj.size() == 2, "Should be equal 2");
    QObject *obj = listObj[0];
    QVERIFY2(obj != nullptr, "Should be different nullptr");
    listObj.remove(obj);
    QVERIFY2(listObj.size() == 1, "Should be equal 1");
    listObj.setAutoDelete(true);
    QVERIFY2(listObj.getAutoDelete() == true, "Should be equal true");
}
<commit_msg>tst_qlistobject adjusts<commit_after>#include "tst_qlistobject.h"

void TST_QListObject::test()
{
    CWF::QListObject listObj;

    listObj.add(new QObject);
    listObj.add(new QObject);

    QVERIFY2(listObj.size() == 2, "Should be equal 2");
    QObject *obj = listObj[0];
    QVERIFY2(obj != nullptr, "Should be different nullptr");
    listObj.remove(obj);
    QVERIFY2(listObj.size() == 1, "Should be equal 1");
    listObj.setAutoDelete(false);
    QVERIFY2(listObj.getAutoDelete() == false, "Should be equal false");
}
<|endoftext|>