<commit_before>#ifndef STACKSTRUCTURE_HPP_
#define STACKSTRUCTURE_HPP_

#if defined(__EITOS_PORT__) && !defined(__EITOS_AVR_PORT__)
#error "You are using two different ports."
#endif

#define RETI_LOW_OFFSET      0
#define RETI_HIGH_OFFSET     1
#define SREG_OFFSET          3
#define R0_OFFSET            2
#define R1_OFFSET            4
#define R2_OFFSET            5
#define R3_OFFSET            6
#define R4_OFFSET            7
#define R5_OFFSET            8
#define R6_OFFSET            9
#define R7_OFFSET            10
#define R8_OFFSET            11
#define R9_OFFSET            12
#define R10_OFFSET           13
#define R11_OFFSET           14
#define R12_OFFSET           15
#define R13_OFFSET           16
#define R14_OFFSET           17
#define R15_OFFSET           18
#define R16_OFFSET           19
#define R17_OFFSET           20
#define R18_OFFSET           21
#define R19_OFFSET           22
#define R20_OFFSET           23
#define R21_OFFSET           24
#define R22_OFFSET           25
#define R23_OFFSET           26
#define R24_OFFSET           27
#define R25_OFFSET           28
#define R26_OFFSET           29
#define R27_OFFSET           30
#define R28_OFFSET           31
#define R29_OFFSET           32
#define R30_OFFSET           33
#define R31_OFFSET           34
#define TASK_HEAP_OFFSET     35

#endif /* STACKSTRUCTURE_HPP_ */
<commit_msg>Stack structure changed - added fields for task killer return address<commit_after>#ifndef STACKSTRUCTURE_HPP_
#define STACKSTRUCTURE_HPP_

#if defined(__EITOS_PORT__) && !defined(__EITOS_AVR_PORT__)
#error "You are using two different ports."
#endif

#define KILL_LOW_OFFSET      0
#define KILL_HIGH_OFFSET     1
#define RETI_LOW_OFFSET      2
#define RETI_HIGH_OFFSET     3
#define SREG_OFFSET          5
#define R0_OFFSET            4
#define R1_OFFSET            6
#define R2_OFFSET            7
#define R3_OFFSET            8
#define R4_OFFSET            9
#define R5_OFFSET            10
#define R6_OFFSET            11
#define R7_OFFSET            12
#define R8_OFFSET            13
#define R9_OFFSET            14
#define R10_OFFSET           15
#define R11_OFFSET           16
#define R12_OFFSET           17
#define R13_OFFSET           18
#define R14_OFFSET           19
#define R15_OFFSET           20
#define R16_OFFSET           21
#define R17_OFFSET           22
#define R18_OFFSET           23
#define R19_OFFSET           24
#define R20_OFFSET           25
#define R21_OFFSET           26
#define R22_OFFSET           27
#define R23_OFFSET           28
#define R24_OFFSET           29
#define R25_OFFSET           30
#define R26_OFFSET           31
#define R27_OFFSET           32
#define R28_OFFSET           33
#define R29_OFFSET           34
#define R30_OFFSET           35
#define R31_OFFSET           36
#define TASK_HEAP_OFFSET     37

#endif /* STACKSTRUCTURE_HPP_ */
<|endoftext|>


<commit_before>/**
 * \file
 * Copyright 2018 Jonas Schenke
 *
 * This file is part of alpaka.
 *
 * alpaka is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * alpaka 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 alpaka.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

#include <alpaka/alpaka.hpp>

//#############################################################################
//! An iterator base class.
//!
//! \tparam T The type.
//! \tparam TBuf The buffer type (standard is T).
template <typename T, typename TBuf = T>
class Iterator
{
protected:
    const TBuf *mData;
    uint64_t mIndex;
    const uint64_t mMaximum;

public:
    //-----------------------------------------------------------------------------
    //! Constructor.
    //!
    //! \param data A pointer to the data.
    //! \param index The index.
    //! \param maximum The first index outside of the iterator memory.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE Iterator(const TBuf *data,
                                                 uint32_t index,
                                                 uint64_t maximum)
        : mData(data), mIndex(index), mMaximum(maximum)
    {
    }

    //-----------------------------------------------------------------------------
    //! Constructor.
    //!
    //! \param other The other iterator object.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE Iterator(const Iterator &other) = default;

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns true if objects are equal and false otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator==(const Iterator &other) const -> bool
    {
        return (this->mData == other.mData) && (this->mIndex == other.mIndex) &&
               (this->mMaximum == other.mMaximum);
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns false if objects are equal and true otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator!=(const Iterator &other) const -> bool
    {
        return !operator==(other);
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns false if the other object is equal or smaller and true
    //! otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator<(const Iterator &other) const -> bool
    {
        return mIndex < other.mIndex;
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns false if the other object is equal or bigger and true otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator>(const Iterator &other) const -> bool
    {
        return mIndex > other.mIndex;
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns true if the other object is equal or bigger and false otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator<=(const Iterator &other) const -> bool
    {
        return mIndex <= other.mIndex;
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns true if the other object is equal or smaller and false
    //! otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator>=(const Iterator &other) const -> bool
    {
        return mIndex >= other.mIndex;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator*() -> const T &
    {
        return mData[mIndex];
    }
};

//#############################################################################
//! A CPU memory iterator.
//!
//! \tparam TAcc The accelerator type.
//! \tparam T The type.
//! \tparam TBuf The buffer type (standard is T).
template <typename TAcc, typename T, typename TBuf = T>
class IteratorCpu : public Iterator<T, TBuf>
{
public:
    //-----------------------------------------------------------------------------
    //! Constructor.
    //!
    //! \param acc The accelerator object.
    //! \param data A pointer to the data.
    //! \param linearizedIndex The linearized index.
    //! \param gridSize The grid size.
    //! \param n The problem size.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE IteratorCpu(const TAcc &acc,
                                                    const TBuf *data,
                                                    uint32_t linearizedIndex,
                                                    uint32_t gridSize,
                                                    uint64_t n)
        : Iterator<T, TBuf>(
              data,
              (n * linearizedIndex) / static_cast<uint32_t>(
                  alpaka::math::min(acc, static_cast<uint64_t>(gridSize), n)),
              (n * (linearizedIndex + 1)) / static_cast<uint32_t>(
                                                                  alpaka::math::min(acc, static_cast<uint64_t>(gridSize), n)))
    {
    }

    //-----------------------------------------------------------------------------
    //! Returns the iterator for the last item.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto end() const -> IteratorCpu
    {
        IteratorCpu ret(*this);
        ret.mIndex = this->mMaximum;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Increments the internal pointer to the next one and returns this
    //! element.
    //!
    //! Returns a reference to the next index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++() -> IteratorCpu &
    {
        ++(this->mIndex);
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element and increments the internal pointer to the
    //! next one.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++(int) -> IteratorCpu
    {
        auto ret(*this);
        ++(this->mIndex);
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Decrements the internal pointer to the previous one and returns the this
    //! element.
    //!
    //! Returns a reference to the previous index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--() -> IteratorCpu &
    {
        --(this->mIndex);
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element and decrements the internal pointer to the
    //! previous one.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--(int) -> IteratorCpu
    {
        auto ret(*this);
        --(this->mIndex);
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Returns the index + a supplied offset.
    //!
    //! \param n The offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+(uint64_t n) const
        -> IteratorCpu
    {
        IteratorCpu ret(*this);
        ret.mIndex += n;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Returns the index - a supplied offset.
    //!
    //! \param n The offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-(uint64_t n) const
        -> IteratorCpu
    {
        IteratorCpu ret(*this);
        ret.mIndex -= n;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Addition assignment.
    //!
    //! \param offset The offset.
    //!
    //! Returns the current object offset by the offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+=(uint64_t offset)
        -> IteratorCpu &
    {
        this->mIndex += offset;
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Substraction assignment.
    //!
    //! \param offset The offset.
    //!
    //! Returns the current object offset by the offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-=(uint64_t offset)
        -> IteratorCpu &
    {
        this->mIndex -= offset;
        return *this;
    }
};

//#############################################################################
//! A GPU memory iterator.
//!
//! \tparam TAcc The accelerator type.
//! \tparam T The type.
//! \tparam TBuf The buffer type (standard is T).
template <typename TAcc, typename T, typename TBuf = T>
class IteratorGpu : public Iterator<T, TBuf>
{
private:
    const uint32_t mGridSize;

public:
    //-----------------------------------------------------------------------------
    //! Constructor.
    //!
    //! \param acc The accelerator object.
    //! \param data A pointer to the data.
    //! \param linearizedIndex The linearized index.
    //! \param gridSize The grid size.
    //! \param n The problem size.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE IteratorGpu(const TAcc &,
                                                    const TBuf *data,
                                                    uint32_t linearizedIndex,
                                                    uint32_t gridSize,
                                                    uint64_t n)
        : Iterator<T, TBuf>(data, linearizedIndex, n), mGridSize(gridSize)
    {
    }

    //-----------------------------------------------------------------------------
    //! Returns the iterator for the last item.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto end() const -> IteratorGpu
    {
        IteratorGpu ret(*this);
        ret.mIndex = this->mMaximum;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Increments the internal pointer to the next one and returns this
    //! element.
    //!
    //! Returns a reference to the next index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++() -> IteratorGpu &
    {
        this->mIndex += this->mGridSize;
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element and increments the internal pointer to the
    //! next one.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++(int) -> IteratorGpu
    {
        auto ret(*this);
        this->mIndex += this->mGridSize;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Decrements the internal pointer to the previous one and returns the this
    //! element.
    //!
    //! Returns a reference to the previous index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--() -> IteratorGpu &
    {
        this->mIndex -= this->mGridSize;
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element and decrements the internal pointer to the
    //! previous one.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--(int) -> IteratorGpu
    {
        auto ret(*this);
        this->mIndex -= this->mGridSize;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Returns the index + a supplied offset.
    //!
    //! \param n The offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+(uint64_t n) const
        -> IteratorGpu
    {
        auto ret(*this);
        ret.mIndex += n * mGridSize;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Returns the index - a supplied offset.
    //!
    //! \param n The offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-(uint64_t n) const
        -> IteratorGpu
    {
        auto ret(*this);
        ret.mIndex -= n * mGridSize;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Addition assignment.
    //!
    //! \param offset The offset.
    //!
    //! Returns the current object offset by the offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+=(uint64_t offset)
        -> IteratorGpu &
    {
        this->mIndex += offset * this->mGridSize;
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Substraction assignment.
    //!
    //! \param offset The offset.
    //!
    //! Returns the current object offset by the offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-=(uint64_t offset)
        -> IteratorGpu &
    {
        this->mIndex -= offset * this->mGridSize;
        return *this;
    }
};
<commit_msg>Added conversions in iterator.hpp to satisfy travis ci.<commit_after>/**
 * \file
 * Copyright 2018 Jonas Schenke
 *
 * This file is part of alpaka.
 *
 * alpaka is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * alpaka 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 alpaka.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

#include <alpaka/alpaka.hpp>

//#############################################################################
//! An iterator base class.
//!
//! \tparam T The type.
//! \tparam TBuf The buffer type (standard is T).
template <typename T, typename TBuf = T>
class Iterator
{
protected:
    const TBuf *mData;
    uint64_t mIndex;
    const uint64_t mMaximum;

public:
    //-----------------------------------------------------------------------------
    //! Constructor.
    //!
    //! \param data A pointer to the data.
    //! \param index The index.
    //! \param maximum The first index outside of the iterator memory.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE Iterator(const TBuf *data,
                                                 uint32_t index,
                                                 uint64_t maximum)
        : mData(data), mIndex(index), mMaximum(maximum)
    {
    }

    //-----------------------------------------------------------------------------
    //! Constructor.
    //!
    //! \param other The other iterator object.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE Iterator(const Iterator &other) = default;

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns true if objects are equal and false otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator==(const Iterator &other) const -> bool
    {
        return (this->mData == other.mData) && (this->mIndex == other.mIndex) &&
               (this->mMaximum == other.mMaximum);
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns false if objects are equal and true otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator!=(const Iterator &other) const -> bool
    {
        return !operator==(other);
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns false if the other object is equal or smaller and true
    //! otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator<(const Iterator &other) const -> bool
    {
        return mIndex < other.mIndex;
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns false if the other object is equal or bigger and true otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator>(const Iterator &other) const -> bool
    {
        return mIndex > other.mIndex;
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns true if the other object is equal or bigger and false otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator<=(const Iterator &other) const -> bool
    {
        return mIndex <= other.mIndex;
    }

    //-----------------------------------------------------------------------------
    //! Compare operator.
    //!
    //! \param other The other object.
    //!
    //! Returns true if the other object is equal or smaller and false
    //! otherwise.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto
    operator>=(const Iterator &other) const -> bool
    {
        return mIndex >= other.mIndex;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator*() -> const T &
    {
        return mData[mIndex];
    }
};

//#############################################################################
//! A CPU memory iterator.
//!
//! \tparam TAcc The accelerator type.
//! \tparam T The type.
//! \tparam TBuf The buffer type (standard is T).
template <typename TAcc, typename T, typename TBuf = T>
class IteratorCpu : public Iterator<T, TBuf>
{
public:
    //-----------------------------------------------------------------------------
    //! Constructor.
    //!
    //! \param acc The accelerator object.
    //! \param data A pointer to the data.
    //! \param linearizedIndex The linearized index.
    //! \param gridSize The grid size.
    //! \param n The problem size.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE IteratorCpu(const TAcc &acc,
                                                    const TBuf *data,
                                                    uint32_t linearizedIndex,
                                                    uint32_t gridSize,
                                                    uint64_t n)
        : Iterator<T, TBuf>(
              data,
              static_cast<uint32_t>((n * linearizedIndex) /
                  alpaka::math::min(acc, static_cast<uint64_t>(gridSize), n),
              static_cast<uint32_t>((n * (linearizedIndex + 1)) /
                  alpaka::math::min(acc, static_cast<uint64_t>(gridSize), n)))
    {
    }

    //-----------------------------------------------------------------------------
    //! Returns the iterator for the last item.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto end() const -> IteratorCpu
    {
        IteratorCpu ret(*this);
        ret.mIndex = this->mMaximum;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Increments the internal pointer to the next one and returns this
    //! element.
    //!
    //! Returns a reference to the next index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++() -> IteratorCpu &
    {
        ++(this->mIndex);
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element and increments the internal pointer to the
    //! next one.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++(int) -> IteratorCpu
    {
        auto ret(*this);
        ++(this->mIndex);
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Decrements the internal pointer to the previous one and returns the this
    //! element.
    //!
    //! Returns a reference to the previous index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--() -> IteratorCpu &
    {
        --(this->mIndex);
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element and decrements the internal pointer to the
    //! previous one.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--(int) -> IteratorCpu
    {
        auto ret(*this);
        --(this->mIndex);
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Returns the index + a supplied offset.
    //!
    //! \param n The offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+(uint64_t n) const
        -> IteratorCpu
    {
        IteratorCpu ret(*this);
        ret.mIndex += n;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Returns the index - a supplied offset.
    //!
    //! \param n The offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-(uint64_t n) const
        -> IteratorCpu
    {
        IteratorCpu ret(*this);
        ret.mIndex -= n;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Addition assignment.
    //!
    //! \param offset The offset.
    //!
    //! Returns the current object offset by the offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+=(uint64_t offset)
        -> IteratorCpu &
    {
        this->mIndex += offset;
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Substraction assignment.
    //!
    //! \param offset The offset.
    //!
    //! Returns the current object offset by the offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-=(uint64_t offset)
        -> IteratorCpu &
    {
        this->mIndex -= offset;
        return *this;
    }
};

//#############################################################################
//! A GPU memory iterator.
//!
//! \tparam TAcc The accelerator type.
//! \tparam T The type.
//! \tparam TBuf The buffer type (standard is T).
template <typename TAcc, typename T, typename TBuf = T>
class IteratorGpu : public Iterator<T, TBuf>
{
private:
    const uint32_t mGridSize;

public:
    //-----------------------------------------------------------------------------
    //! Constructor.
    //!
    //! \param data A pointer to the data.
    //! \param linearizedIndex The linearized index.
    //! \param gridSize The grid size.
    //! \param n The problem size.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE IteratorGpu(const TAcc &,
                                                    const TBuf *data,
                                                    uint32_t linearizedIndex,
                                                    uint32_t gridSize,
                                                    uint64_t n)
        : Iterator<T, TBuf>(data, linearizedIndex, n), mGridSize(gridSize)
    {
    }

    //-----------------------------------------------------------------------------
    //! Returns the iterator for the last item.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto end() const -> IteratorGpu
    {
        IteratorGpu ret(*this);
        ret.mIndex = this->mMaximum;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Increments the internal pointer to the next one and returns this
    //! element.
    //!
    //! Returns a reference to the next index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++() -> IteratorGpu &
    {
        this->mIndex += this->mGridSize;
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element and increments the internal pointer to the
    //! next one.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++(int) -> IteratorGpu
    {
        auto ret(*this);
        this->mIndex += this->mGridSize;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Decrements the internal pointer to the previous one and returns the this
    //! element.
    //!
    //! Returns a reference to the previous index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--() -> IteratorGpu &
    {
        this->mIndex -= this->mGridSize;
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Returns the current element and decrements the internal pointer to the
    //! previous one.
    //!
    //! Returns a reference to the current index.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--(int) -> IteratorGpu
    {
        auto ret(*this);
        this->mIndex -= this->mGridSize;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Returns the index + a supplied offset.
    //!
    //! \param n The offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+(uint64_t n) const
        -> IteratorGpu
    {
        auto ret(*this);
        ret.mIndex += n * mGridSize;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Returns the index - a supplied offset.
    //!
    //! \param n The offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-(uint64_t n) const
        -> IteratorGpu
    {
        auto ret(*this);
        ret.mIndex -= n * mGridSize;
        return ret;
    }

    //-----------------------------------------------------------------------------
    //! Addition assignment.
    //!
    //! \param offset The offset.
    //!
    //! Returns the current object offset by the offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+=(uint64_t offset)
        -> IteratorGpu &
    {
        this->mIndex += offset * this->mGridSize;
        return *this;
    }

    //-----------------------------------------------------------------------------
    //! Substraction assignment.
    //!
    //! \param offset The offset.
    //!
    //! Returns the current object offset by the offset.
    ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-=(uint64_t offset)
        -> IteratorGpu &
    {
        this->mIndex -= offset * this->mGridSize;
        return *this;
    }
};
<|endoftext|>


<commit_before>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5pp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY
// 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
// ===========================================================================
//
// Author: Eugen Wintersberger <eugen.wintersberger@desy.de>
// Created on: Oct 11, 2017
//
#include <iostream>
#include <h5cpp/hdf5.hpp>

using namespace hdf5;

int main()
{
  file::File f = file::create("append_scalar_data.h5",
                              file::AccessFlags::TRUNCATE);
  node::Group root_group = f.root();
  property::LinkCreationList lcpl;
  property::DatasetCreationList dcpl;
  dcpl.layout(property::DatasetLayout::CHUNKED);
  dcpl.chunk(Dimensions{1024});

  dataspace::Simple space({0},{dataspace::Simple::UNLIMITED});
  auto type = datatype::create<int>();

  node::Dataset dset(root_group,"data",type,space,lcpl,dcpl);

  dataspace::Hyperslab slab{{0},{1},{1},{1}};
  int data=0;
  for(size_t index=1;index<=25;++index,++data)
  {
    dset.extent(0,1);      //grow dataset
    dset.write(data,slab); //write data
    slab.offset(0,index);   //update selection
  }
}

<commit_msg>Updated append scalar data example<commit_after>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5pp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY
// 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
// ===========================================================================
//
// Author: Eugen Wintersberger <eugen.wintersberger@desy.de>
// Created on: Oct 11, 2017
//
#include <iostream>
#include <h5cpp/hdf5.hpp>

using namespace hdf5;

node::Dataset create_dataset(const node::Group parent_group)
{
  property::LinkCreationList lcpl;
  property::DatasetCreationList dcpl;

  // in order to append data we have to use a chunked layout of the dataset
  dcpl.layout(property::DatasetLayout::CHUNKED);
  dcpl.chunk(Dimensions{1024});

  // create dataspace (infinitely extensible) and datatype
  dataspace::Simple space({0},{dataspace::Simple::UNLIMITED});
  auto type = datatype::create<int>();

  // finally create the dataset
  return node::Dataset(parent_group,"data",type,space,lcpl,dcpl);
}

int main()
{
  file::File f = file::create("append_scalar_data.h5",
                              file::AccessFlags::TRUNCATE);
  node::Group root_group = f.root();

  //
  // create the dataset to which we want to write data
  //
  node::Dataset dataset = create_dataset(root_group);

  //
  // write individual elements to the dataset using a Hyperslab selection
  //
  std::cout<<"writing: ";
  dataspace::Hyperslab selection{{0},{1},{1},{1}};
  int data=0;
  for(size_t index=1;index<=25;++index,++data)
  {
    dataset.extent(0,1);           //grow dataset
    dataset.write(data,selection); //write data
    selection.offset(0,index);  //update selection
    std::cout<<data<<"  ";
  }
  std::cout<<std::endl;

  //
  // reading individual data elements from the dataset
  //
  std::cout<<"reading: ";
  for(size_t index=0;index<=24;++index)
  {
    selection.offset(0,index);
    int value;
    dataset.read(value,selection);
    std::cout<<value<<"  ";
  }
  std::cout<<std::endl;

  return 0;
}

<|endoftext|>


<commit_before>/**
 * @file hmm_train_main.cpp
 * @author Ryan Curtin
 *
 * Executable which trains an HMM and saves the trained HMM to file.
 */
#include <mlpack/core.hpp>

#include "hmm.hpp"
#include "hmm_util.hpp"

#include <mlpack/methods/gmm/gmm.hpp>

PROGRAM_INFO("Hidden Markov Model (HMM) Training", "This program allows a "
    "Hidden Markov Model to be trained on labeled or unlabeled data.  It "
    "support three types of HMMs: discrete HMMs, Gaussian HMMs, or GMM HMMs."
    "\n\n"
    "Either one input sequence can be specified (with --input_file), or, a "
    "file containing files in which input sequences can be found (when "
    "--input_file and --batch are used together).  In addition, labels can be "
    "provided in the file specified by --labels_file, and if --batch is used, "
    "the file given to --labels_file should contain a list of files of labels "
    "corresponding to the sequences in the file given to --input_file."
    "\n\n"
    "The HMM is trained with the Baum-Welch algorithm if no labels are "
    "provided.  The tolerance of the Baum-Welch algorithm can be set with the "
    "--tolerance option."
    "\n\n"
    "Optionally, a pre-created HMM model can be used as a guess for the "
    "transition matrix and emission probabilities; this is specifiable with "
    "--model_file.");

PARAM_STRING_REQ("input_file", "File containing input observations.", "i");
PARAM_STRING_REQ("type", "Type of HMM: discrete | gaussian | gmm.", "t");

PARAM_FLAG("batch", "If true, input_file (and if passed, labels_file) are "
    "expected to contain a list of files to use as input observation sequences "
    "(and label sequences).", "b");
PARAM_INT("states", "Number of hidden states in HMM (necessary, unless "
    "model_file is specified.", "n", 0);
PARAM_INT("gaussians", "Number of gaussians in each GMM (necessary when type is"
    " 'gmm'.", "g", 0);
PARAM_STRING("model_file", "Pre-existing HMM model (optional).", "m", "");
PARAM_STRING("labels_file", "Optional file of hidden states, used for "
    "labeled training.", "l", "");
PARAM_STRING("output_model_file", "File to save trained HMM to.", "o",
    "output_hmm.xml");
PARAM_INT("seed", "Random seed.  If 0, 'std::time(NULL)' is used.", "s", 0);
PARAM_DOUBLE("tolerance", "Tolerance of the Baum-Welch algorithm.", "T", 1e-5);

using namespace mlpack;
using namespace mlpack::hmm;
using namespace mlpack::distribution;
using namespace mlpack::util;
using namespace mlpack::gmm;
using namespace mlpack::math;
using namespace arma;
using namespace std;

// Because we don't know what the type of our HMM is, we need to write a
// function that can take arbitrary HMM types.
struct Train
{
  template<typename HMMType>
  static void Apply(HMMType& hmm, vector<mat>* trainSeqPtr)
  {
    const bool batch = CLI::HasParam("batch");
    const double tolerance = CLI::GetParam<double>("tolerance");

    // Do we need to replace the tolerance?
    if (CLI::HasParam("tolerance"))
      hmm.Tolerance() = tolerance;

    const string labelsFile = CLI::GetParam<string>("labels_file");

    // Verify that the dimensionality of our observations is the same as the
    // dimensionality of our HMM's emissions.
    vector<mat>& trainSeq = *trainSeqPtr;
    for (size_t i = 0; i < trainSeq.size(); ++i)
      if (trainSeq[i].n_rows != hmm.Emission()[0].Dimensionality())
        Log::Fatal << "Dimensionality of training sequence " << i << " ("
            << trainSeq[i].n_rows << ") is not equal to the dimensionality of "
            << "the HMM (" << hmm.Emission()[0].Dimensionality() << ")!"
            << endl;

    vector<arma::Col<size_t> > labelSeq; // May be empty.
    if (labelsFile != "")
    {
      // Do we have multiple label files to load?
      char lineBuf[1024];
      if (batch)
      {
        fstream f(labelsFile);

        if (!f.is_open())
          Log::Fatal << "Could not open '" << labelsFile << "' for reading."
              << endl;

        // Now read each line in.
        f.getline(lineBuf, 1024, '\n');
        while (!f.eof())
        {
          Log::Info << "Adding training sequence labels from '" << lineBuf
              << "'." << endl;

          // Now read the matrix.
          Mat<size_t> label;
          data::Load(lineBuf, label, true); // Fatal on failure.

          // Ensure that matrix only has one column.
          if (label.n_rows == 1)
            label = trans(label);

          if (label.n_cols > 1)
            Log::Fatal << "Invalid labels; must be one-dimensional." << endl;

          labelSeq.push_back(label.col(0));

          f.getline(lineBuf, 1024, '\n');
        }

        f.close();
      }
      else
      {
        Mat<size_t> label;
        data::Load(labelsFile, label, true);

        // Ensure that matrix only has one column.
        if (label.n_rows == 1)
          label = trans(label);

        if (label.n_cols > 1)
          Log::Fatal << "Invalid labels; must be one-dimensional." << endl;

        // Verify the same number of observations as the data.
        if (label.n_elem != trainSeq[labelSeq.size()].n_cols)
          Log::Fatal << "Label sequence " << labelSeq.size() << " does not have"
              << " the same number of points as observation sequence "
              << labelSeq.size() << "!" << endl;

        labelSeq.push_back(label.col(0));
      }

      // Now perform the training with labels.
      hmm.Train(trainSeq, labelSeq);
    }
    else
    {
      // Perform unsupervised training.
      hmm.Train(trainSeq);
    }

    // Save the model.
    if (CLI::HasParam("output_model_file"))
    {
      const string modelFile = CLI::GetParam<string>("output_model_file");
      SaveHMM(hmm, modelFile);
    }
  }
};

int main(int argc, char** argv)
{
  // Parse command line options.
  CLI::ParseCommandLine(argc, argv);

  // Set random seed.
  if (CLI::GetParam<int>("seed") != 0)
    RandomSeed((size_t) CLI::GetParam<int>("seed"));
  else
    RandomSeed((size_t) time(NULL));

  // Validate parameters.
  const string modelFile = CLI::GetParam<string>("model_file");
  const string inputFile = CLI::GetParam<string>("input_file");
  const string type = CLI::GetParam<string>("type");
  const size_t states = CLI::GetParam<int>("states");
  const double tolerance = CLI::GetParam<double>("tolerance");
  const bool batch = CLI::HasParam("batch");

  // Verify that either a model or a type was given.
  if (modelFile == "" && type == "")
    Log::Fatal << "No model file specified and no HMM type given!  At least "
        << "one is required." << endl;

  // If no model is specified, make sure we are training with valid parameters.
  if (modelFile == "")
  {
    // Validate number of states.
    if (states == 0)
      Log::Fatal << "Must specify number of states if model file is not "
          << "specified!" << endl;
  }

  if (modelFile != "" && CLI::HasParam("tolerance"))
    Log::Info << "Tolerance of existing model in '" << modelFile << "' will be "
        << "replaced with specified tolerance of " << tolerance << "." << endl;

  // Load the input data.
  vector<mat> trainSeq;
  if (batch)
  {
    // The input file contains a list of files to read.
    Log::Info << "Reading list of training sequences from '" << inputFile
        << "'." << endl;

    fstream f(inputFile.c_str(), ios_base::in);

    if (!f.is_open())
      Log::Fatal << "Could not open '" << inputFile << "' for reading."
          << endl;

    // Now read each line in.
    char lineBuf[1024]; // Max 1024 characters... hopefully long enough.
    f.getline(lineBuf, 1024, '\n');
    while (!f.eof())
    {
      Log::Info << "Adding training sequence from '" << lineBuf << "'."
          << endl;

      // Now read the matrix.
      trainSeq.push_back(mat());
      data::Load(lineBuf, trainSeq.back(), true); // Fatal on failure.

      // See if we need to transpose the data.
      if (type == "discrete")
      {
        if (trainSeq.back().n_cols == 1)
          trainSeq.back() = trans(trainSeq.back());
      }

      f.getline(lineBuf, 1024, '\n');
    }

    f.close();
  }
  else
  {
    // Only one input file.
    trainSeq.resize(1);
    data::Load(inputFile, trainSeq[0], true);
  }

  // If we have a model file, we can autodetect the type.
  if (modelFile != "")
  {
    LoadHMMAndPerformAction<Train>(modelFile, &trainSeq);
  }
  else
  {
    // We need to read in the type and build the HMM by hand.
    const string type = CLI::GetParam<string>("type");

    if (type == "discrete")
    {
      // Maximum observation is necessary so we know how to train the discrete
      // distribution.
      size_t maxEmission = 0;
      for (vector<mat>::iterator it = trainSeq.begin(); it != trainSeq.end();
           ++it)
      {
        size_t maxSeq = size_t(as_scalar(max(trainSeq[0], 1))) + 1;
        if (maxSeq > maxEmission)
          maxEmission = maxSeq;
      }

      Log::Info << maxEmission << " discrete observations in the input data."
          << endl;

      // Create HMM object.
      HMM<DiscreteDistribution> hmm(size_t(states),
          DiscreteDistribution(maxEmission), tolerance);

      // Now train it.  Pass the already-loaded training data.
      Train::Apply(hmm, &trainSeq);
    }
    else if (type == "gaussian")
    {
      // Find dimension of the data.
      const size_t dimensionality = trainSeq[0].n_rows;

      // Verify dimensionality of data.
      for (size_t i = 0; i < trainSeq.size(); ++i)
        if (trainSeq[i].n_rows != dimensionality)
          Log::Fatal << "Observation sequence " << i << " dimensionality ("
              << trainSeq[i].n_rows << " is incorrect (should be "
              << dimensionality << ")!" << endl;

      HMM<GaussianDistribution> hmm(size_t(states),
          GaussianDistribution(dimensionality), tolerance);

      // Now train it.
      Train::Apply(hmm, &trainSeq);
    }
    else if (type == "gmm")
    {
      // Find dimension of the data.
      const size_t dimensionality = trainSeq[0].n_rows;

      const int gaussians = CLI::GetParam<int>("gaussians");

      if (gaussians == 0)
        Log::Fatal << "Number of gaussians for each GMM must be specified (-g) "
            << "when type = 'gmm'!" << endl;

      if (gaussians < 0)
        Log::Fatal << "Invalid number of gaussians (" << gaussians << "); must "
            << "be greater than or equal to 1." << endl;

      // Create HMM object.
      HMM<GMM<>> hmm(size_t(states), GMM<>(size_t(gaussians), dimensionality),
          tolerance);

      // Issue a warning if the user didn't give labels.
      if (!CLI::HasParam("labels_file"))
        Log::Warn << "Unlabeled training of GMM HMMs is almost certainly not "
            << "going to produce good results!" << endl;

      Train::Apply(hmm, &trainSeq);
    }
    else
    {
      Log::Fatal << "Unknown HMM type: " << type << "; must be 'discrete', "
          << "'gaussian', or 'gmm'." << endl;
    }
  }
}
<commit_msg>Fail when invalid labels are specified.<commit_after>/**
 * @file hmm_train_main.cpp
 * @author Ryan Curtin
 *
 * Executable which trains an HMM and saves the trained HMM to file.
 */
#include <mlpack/core.hpp>

#include "hmm.hpp"
#include "hmm_util.hpp"

#include <mlpack/methods/gmm/gmm.hpp>

PROGRAM_INFO("Hidden Markov Model (HMM) Training", "This program allows a "
    "Hidden Markov Model to be trained on labeled or unlabeled data.  It "
    "support three types of HMMs: discrete HMMs, Gaussian HMMs, or GMM HMMs."
    "\n\n"
    "Either one input sequence can be specified (with --input_file), or, a "
    "file containing files in which input sequences can be found (when "
    "--input_file and --batch are used together).  In addition, labels can be "
    "provided in the file specified by --labels_file, and if --batch is used, "
    "the file given to --labels_file should contain a list of files of labels "
    "corresponding to the sequences in the file given to --input_file."
    "\n\n"
    "The HMM is trained with the Baum-Welch algorithm if no labels are "
    "provided.  The tolerance of the Baum-Welch algorithm can be set with the "
    "--tolerance option."
    "\n\n"
    "Optionally, a pre-created HMM model can be used as a guess for the "
    "transition matrix and emission probabilities; this is specifiable with "
    "--model_file.");

PARAM_STRING_REQ("input_file", "File containing input observations.", "i");
PARAM_STRING_REQ("type", "Type of HMM: discrete | gaussian | gmm.", "t");

PARAM_FLAG("batch", "If true, input_file (and if passed, labels_file) are "
    "expected to contain a list of files to use as input observation sequences "
    "(and label sequences).", "b");
PARAM_INT("states", "Number of hidden states in HMM (necessary, unless "
    "model_file is specified.", "n", 0);
PARAM_INT("gaussians", "Number of gaussians in each GMM (necessary when type is"
    " 'gmm'.", "g", 0);
PARAM_STRING("model_file", "Pre-existing HMM model (optional).", "m", "");
PARAM_STRING("labels_file", "Optional file of hidden states, used for "
    "labeled training.", "l", "");
PARAM_STRING("output_model_file", "File to save trained HMM to.", "o",
    "output_hmm.xml");
PARAM_INT("seed", "Random seed.  If 0, 'std::time(NULL)' is used.", "s", 0);
PARAM_DOUBLE("tolerance", "Tolerance of the Baum-Welch algorithm.", "T", 1e-5);

using namespace mlpack;
using namespace mlpack::hmm;
using namespace mlpack::distribution;
using namespace mlpack::util;
using namespace mlpack::gmm;
using namespace mlpack::math;
using namespace arma;
using namespace std;

// Because we don't know what the type of our HMM is, we need to write a
// function that can take arbitrary HMM types.
struct Train
{
  template<typename HMMType>
  static void Apply(HMMType& hmm, vector<mat>* trainSeqPtr)
  {
    const bool batch = CLI::HasParam("batch");
    const double tolerance = CLI::GetParam<double>("tolerance");

    // Do we need to replace the tolerance?
    if (CLI::HasParam("tolerance"))
      hmm.Tolerance() = tolerance;

    const string labelsFile = CLI::GetParam<string>("labels_file");

    // Verify that the dimensionality of our observations is the same as the
    // dimensionality of our HMM's emissions.
    vector<mat>& trainSeq = *trainSeqPtr;
    for (size_t i = 0; i < trainSeq.size(); ++i)
      if (trainSeq[i].n_rows != hmm.Emission()[0].Dimensionality())
        Log::Fatal << "Dimensionality of training sequence " << i << " ("
            << trainSeq[i].n_rows << ") is not equal to the dimensionality of "
            << "the HMM (" << hmm.Emission()[0].Dimensionality() << ")!"
            << endl;

    vector<arma::Col<size_t> > labelSeq; // May be empty.
    if (labelsFile != "")
    {
      // Do we have multiple label files to load?
      char lineBuf[1024];
      if (batch)
      {
        fstream f(labelsFile);

        if (!f.is_open())
          Log::Fatal << "Could not open '" << labelsFile << "' for reading."
              << endl;

        // Now read each line in.
        f.getline(lineBuf, 1024, '\n');
        while (!f.eof())
        {
          Log::Info << "Adding training sequence labels from '" << lineBuf
              << "'." << endl;

          // Now read the matrix.
          Mat<size_t> label;
          data::Load(lineBuf, label, true); // Fatal on failure.

          // Ensure that matrix only has one column.
          if (label.n_rows == 1)
            label = trans(label);

          if (label.n_cols > 1)
            Log::Fatal << "Invalid labels; must be one-dimensional." << endl;

          // Check all of the labels.
          for (size_t i = 0; i < label.n_rows; ++i)
          {
            if (label[i] >= hmm.Transition().n_cols)
            {
              Log::Fatal << "HMM has " << hmm.Transition().n_cols << " hidden "
                  << "states, but label on line " << i << " of '" << lineBuf
                  << "' is " << label[i] << " (should be between 0 and "
                  << (hmm.Transition().n_cols - 1) << ")!" << endl;
            }
          }

          labelSeq.push_back(label.col(0));

          f.getline(lineBuf, 1024, '\n');
        }

        f.close();
      }
      else
      {
        Mat<size_t> label;
        data::Load(labelsFile, label, true);

        // Ensure that matrix only has one column.
        if (label.n_rows == 1)
          label = trans(label);

        if (label.n_cols > 1)
          Log::Fatal << "Invalid labels; must be one-dimensional." << endl;

        // Verify the same number of observations as the data.
        if (label.n_elem != trainSeq[labelSeq.size()].n_cols)
          Log::Fatal << "Label sequence " << labelSeq.size() << " does not have"
              << " the same number of points as observation sequence "
              << labelSeq.size() << "!" << endl;

        // Check all of the labels.
        for (size_t i = 0; i < label.n_rows; ++i)
        {
          if (label[i] >= hmm.Transition().n_cols)
          {
            Log::Fatal << "HMM has " << hmm.Transition().n_cols << " hidden "
                << "states, but label on line " << i << " of '" << labelsFile
                << "' is " << label[i] << " (should be between 0 and "
                << (hmm.Transition().n_cols - 1) << ")!" << endl;
          }
        }

        labelSeq.push_back(label.col(0));
      }

      // Now perform the training with labels.
      hmm.Train(trainSeq, labelSeq);
    }
    else
    {
      // Perform unsupervised training.
      hmm.Train(trainSeq);
    }

    // Save the model.
    if (CLI::HasParam("output_model_file"))
    {
      const string modelFile = CLI::GetParam<string>("output_model_file");
      SaveHMM(hmm, modelFile);
    }
  }
};

int main(int argc, char** argv)
{
  // Parse command line options.
  CLI::ParseCommandLine(argc, argv);

  // Set random seed.
  if (CLI::GetParam<int>("seed") != 0)
    RandomSeed((size_t) CLI::GetParam<int>("seed"));
  else
    RandomSeed((size_t) time(NULL));

  // Validate parameters.
  const string modelFile = CLI::GetParam<string>("model_file");
  const string inputFile = CLI::GetParam<string>("input_file");
  const string type = CLI::GetParam<string>("type");
  const size_t states = CLI::GetParam<int>("states");
  const double tolerance = CLI::GetParam<double>("tolerance");
  const bool batch = CLI::HasParam("batch");

  // Verify that either a model or a type was given.
  if (modelFile == "" && type == "")
    Log::Fatal << "No model file specified and no HMM type given!  At least "
        << "one is required." << endl;

  // If no model is specified, make sure we are training with valid parameters.
  if (modelFile == "")
  {
    // Validate number of states.
    if (states == 0)
      Log::Fatal << "Must specify number of states if model file is not "
          << "specified!" << endl;
  }

  if (modelFile != "" && CLI::HasParam("tolerance"))
    Log::Info << "Tolerance of existing model in '" << modelFile << "' will be "
        << "replaced with specified tolerance of " << tolerance << "." << endl;

  // Load the input data.
  vector<mat> trainSeq;
  if (batch)
  {
    // The input file contains a list of files to read.
    Log::Info << "Reading list of training sequences from '" << inputFile
        << "'." << endl;

    fstream f(inputFile.c_str(), ios_base::in);

    if (!f.is_open())
      Log::Fatal << "Could not open '" << inputFile << "' for reading."
          << endl;

    // Now read each line in.
    char lineBuf[1024]; // Max 1024 characters... hopefully long enough.
    f.getline(lineBuf, 1024, '\n');
    while (!f.eof())
    {
      Log::Info << "Adding training sequence from '" << lineBuf << "'."
          << endl;

      // Now read the matrix.
      trainSeq.push_back(mat());
      data::Load(lineBuf, trainSeq.back(), true); // Fatal on failure.

      // See if we need to transpose the data.
      if (type == "discrete")
      {
        if (trainSeq.back().n_cols == 1)
          trainSeq.back() = trans(trainSeq.back());
      }

      f.getline(lineBuf, 1024, '\n');
    }

    f.close();
  }
  else
  {
    // Only one input file.
    trainSeq.resize(1);
    data::Load(inputFile, trainSeq[0], true);
  }

  // If we have a model file, we can autodetect the type.
  if (modelFile != "")
  {
    LoadHMMAndPerformAction<Train>(modelFile, &trainSeq);
  }
  else
  {
    // We need to read in the type and build the HMM by hand.
    const string type = CLI::GetParam<string>("type");

    if (type == "discrete")
    {
      // Maximum observation is necessary so we know how to train the discrete
      // distribution.
      size_t maxEmission = 0;
      for (vector<mat>::iterator it = trainSeq.begin(); it != trainSeq.end();
           ++it)
      {
        size_t maxSeq = size_t(as_scalar(max(trainSeq[0], 1))) + 1;
        if (maxSeq > maxEmission)
          maxEmission = maxSeq;
      }

      Log::Info << maxEmission << " discrete observations in the input data."
          << endl;

      // Create HMM object.
      HMM<DiscreteDistribution> hmm(size_t(states),
          DiscreteDistribution(maxEmission), tolerance);

      // Now train it.  Pass the already-loaded training data.
      Train::Apply(hmm, &trainSeq);
    }
    else if (type == "gaussian")
    {
      // Find dimension of the data.
      const size_t dimensionality = trainSeq[0].n_rows;

      // Verify dimensionality of data.
      for (size_t i = 0; i < trainSeq.size(); ++i)
        if (trainSeq[i].n_rows != dimensionality)
          Log::Fatal << "Observation sequence " << i << " dimensionality ("
              << trainSeq[i].n_rows << " is incorrect (should be "
              << dimensionality << ")!" << endl;

      HMM<GaussianDistribution> hmm(size_t(states),
          GaussianDistribution(dimensionality), tolerance);

      // Now train it.
      Train::Apply(hmm, &trainSeq);
    }
    else if (type == "gmm")
    {
      // Find dimension of the data.
      const size_t dimensionality = trainSeq[0].n_rows;

      const int gaussians = CLI::GetParam<int>("gaussians");

      if (gaussians == 0)
        Log::Fatal << "Number of gaussians for each GMM must be specified (-g) "
            << "when type = 'gmm'!" << endl;

      if (gaussians < 0)
        Log::Fatal << "Invalid number of gaussians (" << gaussians << "); must "
            << "be greater than or equal to 1." << endl;

      // Create HMM object.
      HMM<GMM<>> hmm(size_t(states), GMM<>(size_t(gaussians), dimensionality),
          tolerance);

      // Issue a warning if the user didn't give labels.
      if (!CLI::HasParam("labels_file"))
        Log::Warn << "Unlabeled training of GMM HMMs is almost certainly not "
            << "going to produce good results!" << endl;

      Train::Apply(hmm, &trainSeq);
    }
    else
    {
      Log::Fatal << "Unknown HMM type: " << type << "; must be 'discrete', "
          << "'gaussian', or 'gmm'." << endl;
    }
  }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: officeclient.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 05:21:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include <stdio.h>
#include <osl/mutex.hxx>
#include <cppuhelper/factory.hxx>

#include <cppuhelper/servicefactory.hxx>

#include <com/sun/star/uno/XNamingService.hpp>

#include <com/sun/star/registry/XImplementationRegistration.hpp>

#include <com/sun/star/connection/XConnector.hpp>

#include <com/sun/star/bridge/XUnoUrlResolver.hpp>

#include <com/sun/star/lang/XMain.hpp>
#include <com/sun/star/lang/XComponent.hpp>

#include <com/sun/star/frame/XComponentLoader.hpp>

#include <com/sun/star/text/XTextDocument.hpp>

#include <cppuhelper/implbase1.hxx>

using namespace ::rtl;
using namespace ::cppu;
using namespace ::osl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;
using namespace ::com::sun::star::connection;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::bridge;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::frame;

namespace remotebridges_officeclient {

class OfficeClientMain : public WeakImplHelper1< XMain >
{
public:
    OfficeClientMain( const Reference< XMultiServiceFactory > &r ) :
        m_xSMgr( r )
        {}
public:     // Methods

    virtual sal_Int32 SAL_CALL run( const Sequence< OUString >& aArguments )
        throw(RuntimeException);

private: // helper methods
    void testWriter( const Reference < XComponent > & rComponent );
    void registerServices();
    Reference< XMultiServiceFactory > m_xSMgr;
};

void OfficeClientMain::testWriter( const Reference< XComponent > & rComponent )
{
    printf( "pasting some text into the writer document\n" );

    Reference< XTextDocument > rTextDoc( rComponent , UNO_QUERY );
    Reference< XText > rText = rTextDoc->getText();
    Reference< XTextCursor > rCursor = rText->createTextCursor();
    Reference< XTextRange > rRange ( rCursor , UNO_QUERY );

    rText->insertString( rRange, OUString::createFromAscii( "This text has been posted by the officeclient component" ), sal_False );
}

/********************
 * does necessary service registration ( this could be done also by a setup tool )
 *********************/
void OfficeClientMain::registerServices( )
{
    // register services.
    // Note : this needs to be done only once and is in general done by the setup
    Reference < XImplementationRegistration > rImplementationRegistration(

        m_xSMgr->createInstance(
            OUString::createFromAscii( "com.sun.star.registry.ImplementationRegistration" )),
        UNO_QUERY );

    if( ! rImplementationRegistration.is() )
    {
        printf( "Couldn't create registration component\n" );
        exit(1);
    }

    OUString aSharedLibrary[4];
    aSharedLibrary[0] =
        OUString::createFromAscii( "connector.uno" SAL_DLLEXTENSION );
    aSharedLibrary[1] =
        OUString::createFromAscii( "remotebridge.uno" SAL_DLLEXTENSION );
    aSharedLibrary[2] =
        OUString::createFromAscii( "bridgefac.uno" SAL_DLLEXTENSION );
    aSharedLibrary[3] =
        OUString::createFromAscii( "uuresolver.uno" SAL_DLLEXTENSION );

    sal_Int32 i;
    for( i = 0 ; i < 4 ; i ++ )
    {

        // build the system specific library name
        OUString aDllName = aSharedLibrary[i];

        try
        {
            // register the needed services in the servicemanager
            rImplementationRegistration->registerImplementation(
                OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ),
                aDllName,
                Reference< XSimpleRegistry > () );
        }
        catch( Exception & )
        {
            printf( "couldn't register dll %s\n" ,
                    OUStringToOString( aDllName, RTL_TEXTENCODING_ASCII_US ).getStr() );
        }
    }
}

sal_Int32 OfficeClientMain::run( const Sequence< OUString > & aArguments ) throw ( RuntimeException )
{
    printf( "Connecting ....\n" );

    if( aArguments.getLength() == 1 )
    {
        try {
            registerServices();
            Reference < XInterface > r =
                m_xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.bridge.UnoUrlResolver" ) );
            Reference < XUnoUrlResolver > rResolver( r , UNO_QUERY );
            r = rResolver->resolve( aArguments.getConstArray()[0] );

            Reference< XNamingService > rNamingService( r, UNO_QUERY );
            if( rNamingService.is() )
            {
                printf( "got the remote NamingService\n" );

                r = rNamingService->getRegisteredObject(OUString::createFromAscii("StarOffice.ServiceManager"));

                Reference< XMultiServiceFactory > rRemoteSMgr( r , UNO_QUERY );

                Reference < XComponentLoader > rLoader(
                    rRemoteSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop" ))),
                    UNO_QUERY );

                if( rLoader.is() )
                {

                    sal_Char *urls[] = {
                        "private:factory/swriter",
                        "private:factory/sdraw",
                        "private:factory/simpress",
                        "private:factory/scalc"
                    };

                    sal_Char *docu[]= {
                        "a new writer document ...\n",
                        "a new draw document ...\n",
                        "a new schedule document ...\n" ,
                        "a new calc document ...\n"
                    };
                    sal_Int32 i;
                    for( i = 0 ; i < 4 ; i ++ )
                    {
                        printf( "press any key to open %s\n" , docu[i] );
                        getchar();

                        Reference< XComponent > rComponent =
                            rLoader->loadComponentFromURL(
                                OUString::createFromAscii( urls[i] ) ,
                                OUString( RTL_CONSTASCII_USTRINGPARAM("_blank")),
                                0 ,
                                Sequence < ::com::sun::star::beans::PropertyValue >() );

                        if( 0 == i )
                        {
                            testWriter( rComponent );
                        }
                        printf( "press any key to close the document\n" );
                        getchar();
                        rComponent->dispose();
                    }
                }
            }

        }
        catch( ConnectionSetupException &e )
        {
            OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
            printf( "%s\n", o.pData->buffer );
            printf( "couldn't access local resource ( possible security resons )\n" );
        }
        catch( NoConnectException &e )
        {
            OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
            printf( "%s\n", o.pData->buffer );
            printf( "no server listening on the resource\n" );
        }
        catch( IllegalArgumentException &e )
        {
            OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
            printf( "%s\n", o.pData->buffer );
            printf( "uno url invalid\n" );
        }
        catch( RuntimeException & e )
        {
            OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
            printf( "%s\n", o.pData->buffer );
            printf( "a remote call was aborted\n" );
        }
    }
    else
    {
        printf( "usage: (uno officeclient-component --) uno-url\n"
                "e.g.:  uno:socket,host=localhost,port=2002;urp;StarOffice.NamingService\n" );
        return 1;
    }
    return 0;
}

Reference< XInterface > SAL_CALL CreateInstance( const Reference< XMultiServiceFactory > &r)
{
    return Reference< XInterface > ( ( OWeakObject * ) new OfficeClientMain(r) );
}

Sequence< OUString > getSupportedServiceNames()
{
    static Sequence < OUString > *pNames = 0;
    if( ! pNames )
    {
        MutexGuard guard( Mutex::getGlobalMutex() );
        if( !pNames )
        {
            static Sequence< OUString > seqNames(2);
            seqNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.bridge.example.OfficeClientExample" );
            pNames = &seqNames;
        }
    }
    return *pNames;
}

}

using namespace remotebridges_officeclient;
#define IMPLEMENTATION_NAME "com.sun.star.comp.remotebridges.example.OfficeClientSample"

extern "C"
{
//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================
sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    if (pRegistryKey)
    {
        try
        {
            Reference< XRegistryKey > xNewKey(
                reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
                    OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) );

            const Sequence< OUString > & rSNL = getSupportedServiceNames();
            const OUString * pArray = rSNL.getConstArray();
            for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
                xNewKey->createKey( pArray[nPos] );

            return sal_True;
        }
        catch (InvalidRegistryException &)
        {
            OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
        }
    }
    return sal_False;
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    void * pRet = 0;

    if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0)
    {
        Reference< XSingleServiceFactory > xFactory( createSingleFactory(
            reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
            OUString::createFromAscii( pImplName ),
            CreateInstance, getSupportedServiceNames() ) );

        if (xFactory.is())
        {
            xFactory->acquire();
            pRet = xFactory.get();
        }
    }

    return pRet;
}
}
<commit_msg>INTEGRATION: CWS changefileheader (1.6.42); FILE MERGED 2008/03/31 07:25:25 rt 1.6.42.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: officeclient.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#include <stdio.h>
#include <osl/mutex.hxx>
#include <cppuhelper/factory.hxx>

#include <cppuhelper/servicefactory.hxx>

#include <com/sun/star/uno/XNamingService.hpp>

#include <com/sun/star/registry/XImplementationRegistration.hpp>

#include <com/sun/star/connection/XConnector.hpp>

#include <com/sun/star/bridge/XUnoUrlResolver.hpp>

#include <com/sun/star/lang/XMain.hpp>
#include <com/sun/star/lang/XComponent.hpp>

#include <com/sun/star/frame/XComponentLoader.hpp>

#include <com/sun/star/text/XTextDocument.hpp>

#include <cppuhelper/implbase1.hxx>

using namespace ::rtl;
using namespace ::cppu;
using namespace ::osl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;
using namespace ::com::sun::star::connection;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::bridge;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::frame;

namespace remotebridges_officeclient {

class OfficeClientMain : public WeakImplHelper1< XMain >
{
public:
    OfficeClientMain( const Reference< XMultiServiceFactory > &r ) :
        m_xSMgr( r )
        {}
public:     // Methods

    virtual sal_Int32 SAL_CALL run( const Sequence< OUString >& aArguments )
        throw(RuntimeException);

private: // helper methods
    void testWriter( const Reference < XComponent > & rComponent );
    void registerServices();
    Reference< XMultiServiceFactory > m_xSMgr;
};

void OfficeClientMain::testWriter( const Reference< XComponent > & rComponent )
{
    printf( "pasting some text into the writer document\n" );

    Reference< XTextDocument > rTextDoc( rComponent , UNO_QUERY );
    Reference< XText > rText = rTextDoc->getText();
    Reference< XTextCursor > rCursor = rText->createTextCursor();
    Reference< XTextRange > rRange ( rCursor , UNO_QUERY );

    rText->insertString( rRange, OUString::createFromAscii( "This text has been posted by the officeclient component" ), sal_False );
}

/********************
 * does necessary service registration ( this could be done also by a setup tool )
 *********************/
void OfficeClientMain::registerServices( )
{
    // register services.
    // Note : this needs to be done only once and is in general done by the setup
    Reference < XImplementationRegistration > rImplementationRegistration(

        m_xSMgr->createInstance(
            OUString::createFromAscii( "com.sun.star.registry.ImplementationRegistration" )),
        UNO_QUERY );

    if( ! rImplementationRegistration.is() )
    {
        printf( "Couldn't create registration component\n" );
        exit(1);
    }

    OUString aSharedLibrary[4];
    aSharedLibrary[0] =
        OUString::createFromAscii( "connector.uno" SAL_DLLEXTENSION );
    aSharedLibrary[1] =
        OUString::createFromAscii( "remotebridge.uno" SAL_DLLEXTENSION );
    aSharedLibrary[2] =
        OUString::createFromAscii( "bridgefac.uno" SAL_DLLEXTENSION );
    aSharedLibrary[3] =
        OUString::createFromAscii( "uuresolver.uno" SAL_DLLEXTENSION );

    sal_Int32 i;
    for( i = 0 ; i < 4 ; i ++ )
    {

        // build the system specific library name
        OUString aDllName = aSharedLibrary[i];

        try
        {
            // register the needed services in the servicemanager
            rImplementationRegistration->registerImplementation(
                OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ),
                aDllName,
                Reference< XSimpleRegistry > () );
        }
        catch( Exception & )
        {
            printf( "couldn't register dll %s\n" ,
                    OUStringToOString( aDllName, RTL_TEXTENCODING_ASCII_US ).getStr() );
        }
    }
}

sal_Int32 OfficeClientMain::run( const Sequence< OUString > & aArguments ) throw ( RuntimeException )
{
    printf( "Connecting ....\n" );

    if( aArguments.getLength() == 1 )
    {
        try {
            registerServices();
            Reference < XInterface > r =
                m_xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.bridge.UnoUrlResolver" ) );
            Reference < XUnoUrlResolver > rResolver( r , UNO_QUERY );
            r = rResolver->resolve( aArguments.getConstArray()[0] );

            Reference< XNamingService > rNamingService( r, UNO_QUERY );
            if( rNamingService.is() )
            {
                printf( "got the remote NamingService\n" );

                r = rNamingService->getRegisteredObject(OUString::createFromAscii("StarOffice.ServiceManager"));

                Reference< XMultiServiceFactory > rRemoteSMgr( r , UNO_QUERY );

                Reference < XComponentLoader > rLoader(
                    rRemoteSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop" ))),
                    UNO_QUERY );

                if( rLoader.is() )
                {

                    sal_Char *urls[] = {
                        "private:factory/swriter",
                        "private:factory/sdraw",
                        "private:factory/simpress",
                        "private:factory/scalc"
                    };

                    sal_Char *docu[]= {
                        "a new writer document ...\n",
                        "a new draw document ...\n",
                        "a new schedule document ...\n" ,
                        "a new calc document ...\n"
                    };
                    sal_Int32 i;
                    for( i = 0 ; i < 4 ; i ++ )
                    {
                        printf( "press any key to open %s\n" , docu[i] );
                        getchar();

                        Reference< XComponent > rComponent =
                            rLoader->loadComponentFromURL(
                                OUString::createFromAscii( urls[i] ) ,
                                OUString( RTL_CONSTASCII_USTRINGPARAM("_blank")),
                                0 ,
                                Sequence < ::com::sun::star::beans::PropertyValue >() );

                        if( 0 == i )
                        {
                            testWriter( rComponent );
                        }
                        printf( "press any key to close the document\n" );
                        getchar();
                        rComponent->dispose();
                    }
                }
            }

        }
        catch( ConnectionSetupException &e )
        {
            OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
            printf( "%s\n", o.pData->buffer );
            printf( "couldn't access local resource ( possible security resons )\n" );
        }
        catch( NoConnectException &e )
        {
            OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
            printf( "%s\n", o.pData->buffer );
            printf( "no server listening on the resource\n" );
        }
        catch( IllegalArgumentException &e )
        {
            OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
            printf( "%s\n", o.pData->buffer );
            printf( "uno url invalid\n" );
        }
        catch( RuntimeException & e )
        {
            OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
            printf( "%s\n", o.pData->buffer );
            printf( "a remote call was aborted\n" );
        }
    }
    else
    {
        printf( "usage: (uno officeclient-component --) uno-url\n"
                "e.g.:  uno:socket,host=localhost,port=2002;urp;StarOffice.NamingService\n" );
        return 1;
    }
    return 0;
}

Reference< XInterface > SAL_CALL CreateInstance( const Reference< XMultiServiceFactory > &r)
{
    return Reference< XInterface > ( ( OWeakObject * ) new OfficeClientMain(r) );
}

Sequence< OUString > getSupportedServiceNames()
{
    static Sequence < OUString > *pNames = 0;
    if( ! pNames )
    {
        MutexGuard guard( Mutex::getGlobalMutex() );
        if( !pNames )
        {
            static Sequence< OUString > seqNames(2);
            seqNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.bridge.example.OfficeClientExample" );
            pNames = &seqNames;
        }
    }
    return *pNames;
}

}

using namespace remotebridges_officeclient;
#define IMPLEMENTATION_NAME "com.sun.star.comp.remotebridges.example.OfficeClientSample"

extern "C"
{
//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================
sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    if (pRegistryKey)
    {
        try
        {
            Reference< XRegistryKey > xNewKey(
                reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
                    OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) );

            const Sequence< OUString > & rSNL = getSupportedServiceNames();
            const OUString * pArray = rSNL.getConstArray();
            for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
                xNewKey->createKey( pArray[nPos] );

            return sal_True;
        }
        catch (InvalidRegistryException &)
        {
            OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
        }
    }
    return sal_False;
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    void * pRet = 0;

    if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0)
    {
        Reference< XSingleServiceFactory > xFactory( createSingleFactory(
            reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
            OUString::createFromAscii( pImplName ),
            CreateInstance, getSupportedServiceNames() ) );

        if (xFactory.is())
        {
            xFactory->acquire();
            pRet = xFactory.get();
        }
    }

    return pRet;
}
}
<|endoftext|>


<commit_before>#include "tentacle-pseudopod.h"
#include <stddef.h>

Pseudopod::Pseudopod(Stream &input, Print &output, Tentacle& tentacle) {
  pb_ostream_from_stream(output, pbOutput);
  pb_istream_from_stream(input, pbInput);

  this->tentacle = &tentacle;
  messagePinActions = new Action[tentacle.getNumPins()];
  resetPinActions();
}

bool Pseudopod::shouldBroadcastPins() {
  return broadcastPins;
}

int Pseudopod::getBroadcastInterval() {
  return broadcastInterval;
}

bool Pseudopod::isConfigured() {
  return configured;
}

void Pseudopod::resetPinActions() {
  for(int i = 0; i < tentacle->getNumPins(); i++) {
    messagePinActions[i] = Action_ignore;
  }
}

size_t Pseudopod::sendPins() {
  pbOutput.bytes_written = 0;

  currentMessage = {};
  currentMessage.topic = TentacleMessageTopic_action;
  currentMessage.has_topic = true;
  currentMessage.response = true;
  currentMessage.has_response = true;
  currentMessage.pins.funcs.encode = &Pseudopod::pinEncode;
  currentMessage.pins.arg = (void*)this;

  bool status = pb_encode_delimited(&pbOutput, TentacleMessage_fields, &currentMessage);

  return pbOutput.bytes_written;
}

size_t Pseudopod::sendPins(Action* actions) {
  resetPinActions();

  for(int i = 0; i < tentacle->getNumPins(); i++) {
    messagePinActions[i] = actions[i];
  }

  return sendPins();
}

size_t Pseudopod::sendConfiguredPins() {
  return sendPins(tentacle->getConfiguredPinActions());
}

size_t Pseudopod::authenticate(const char *uuid, const char *token) {
  pbOutput.bytes_written = 0;

  currentMessage = {};

  currentMessage.topic = TentacleMessageTopic_authentication;
  currentMessage.has_topic = true;
  currentMessage.authentication = {};
  currentMessage.has_authentication = true;

  strncpy(currentMessage.authentication.uuid, uuid, 36);
  currentMessage.authentication.has_uuid = true;

  strncpy(currentMessage.authentication.token, token, 40);

  currentMessage.authentication.has_token = true;

  bool status = pb_encode_delimited(&pbOutput, TentacleMessage_fields, &currentMessage);

  return pbOutput.bytes_written;
}

size_t Pseudopod::requestConfiguration() {
  pbOutput.bytes_written = 0;

  currentMessage = {};

  currentMessage.topic = TentacleMessageTopic_config;
  currentMessage.has_topic = true;

  bool status = pb_encode_delimited(&pbOutput, TentacleMessage_fields, &currentMessage);

  return pbOutput.bytes_written;
}

size_t Pseudopod::registerDevice() {
  return 0;
}

bool Pseudopod::isConnected() {
  pbOutput.bytes_written = 0;

  currentMessage = {};

  currentMessage.topic = TentacleMessageTopic_ping;
  currentMessage.has_topic = true;

  bool status = pb_encode_delimited(&pbOutput, TentacleMessage_fields, &currentMessage);

  return pbOutput.bytes_written != 0;
}

TentacleMessageTopic Pseudopod::readMessage() {
  resetPinActions();

  currentMessage = {};
  currentMessage.pins.funcs.decode = &Pseudopod::pinDecode;
  currentMessage.pins.arg = (void*) this;

  bool status = pb_decode_delimited(&pbInput, TentacleMessage_fields, &currentMessage);

  if (currentMessage.topic == TentacleMessageTopic_config) {
    configured = true;
    broadcastPins = currentMessage.broadcastPins;
    broadcastInterval = currentMessage.broadcastInterval;
  }

  return currentMessage.topic;
}

bool Pseudopod::pinEncode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
  Pseudopod *pseudopod = (Pseudopod*) *arg;
  Action action;
  Pin pin;

  for(int i = 0; i < pseudopod->tentacle->getNumPins(); i++) {
    action = pseudopod->messagePinActions[i];
    if(action == Action_ignore) {
      continue;
    }

    pin = {};
    pin.has_action = true;
    pin.action = action;
    pin.has_number = true;
    pin.number = i;
    int value = pseudopod->tentacle->processPin(i);

    if(value != -1) {
      pin.has_value = true;
      pin.value = value;
    }

    if (!pb_encode_tag_for_field(stream, field)) {
      return false;
    }

    if(!pb_encode_submessage(stream, Pin_fields, &pin)) {
      return false;
    }
  }

  return true;
}

bool Pseudopod::pinDecode(pb_istream_t *stream, const pb_field_t *field, void **arg) {
  Pseudopod *pseudopod = (Pseudopod*) *arg;
  Pin pin = {};

  if (!pb_decode(stream, Pin_fields, &pin)) {
    return false;
  }

  TentacleMessage& message = pseudopod->currentMessage;

  switch(message.topic) {
    case TentacleMessageTopic_config:
      pseudopod->tentacle->configurePin(pin.number, pin.action);
    break;

    case TentacleMessageTopic_action:
      pseudopod->messagePinActions[pin.number] = pin.action;
      pseudopod->tentacle->processPin(pin.number, pin.value);
    break;

  }

  return true;
}
<commit_msg>asfasd<commit_after>#include "tentacle-pseudopod.h"
#include <stddef.h>

Pseudopod::Pseudopod(Stream &input, Print &output, Tentacle& tentacle) {
  pb_ostream_from_stream(output, pbOutput);
  pb_istream_from_stream(input, pbInput);

  this->tentacle = &tentacle;
  messagePinActions = new Action[tentacle.getNumPins()];
  resetPinActions();
}

bool Pseudopod::shouldBroadcastPins() {
  return broadcastPins;
}

int Pseudopod::getBroadcastInterval() {
  return broadcastInterval;
}

bool Pseudopod::isConfigured() {
  return configured;
}

void Pseudopod::resetPinActions() {
  for(int i = 0; i < tentacle->getNumPins(); i++) {
    messagePinActions[i] = Action_ignore;
  }
}

size_t Pseudopod::sendPins() {
  pbOutput.bytes_written = 0;

  currentMessage = {};
  currentMessage.topic = TentacleMessageTopic_action;
  currentMessage.has_topic = true;
  currentMessage.response = true;
  currentMessage.has_response = true;
  currentMessage.pins.funcs.encode = &Pseudopod::pinEncode;
  currentMessage.pins.arg = (void*)this;

  bool status = pb_encode_delimited(&pbOutput, TentacleMessage_fields, &currentMessage);

  return pbOutput.bytes_written;
}

size_t Pseudopod::sendPins(Action* actions) {
  resetPinActions();

  for(int i = 0; i < tentacle->getNumPins(); i++) {
    messagePinActions[i] = actions[i];
  }

  return sendPins();
}

size_t Pseudopod::sendConfiguredPins() {
  return sendPins(tentacle->getConfiguredPinActions());
}

size_t Pseudopod::authenticate(const char *uuid, const char *token) {
  pbOutput.bytes_written = 0;

  currentMessage = {};

  currentMessage.topic = TentacleMessageTopic_authentication;
  currentMessage.has_topic = true;
  currentMessage.authentication = {};
  currentMessage.has_authentication = true;

  strncpy(currentMessage.authentication.uuid, uuid, 36);
  currentMessage.authentication.has_uuid = true;

  strncpy(currentMessage.authentication.token, token, 40);

  currentMessage.authentication.has_token = true;

  bool status = pb_encode_delimited(&pbOutput, TentacleMessage_fields, &currentMessage);

  return pbOutput.bytes_written;
}

size_t Pseudopod::requestConfiguration() {
  pbOutput.bytes_written = 0;

  currentMessage = {};

  currentMessage.topic = TentacleMessageTopic_config;
  currentMessage.has_topic = true;

  bool status = pb_encode_delimited(&pbOutput, TentacleMessage_fields, &currentMessage);

  return pbOutput.bytes_written;
}

size_t Pseudopod::registerDevice() {
  return 0;
}

bool Pseudopod::isConnected() {
  pbOutput.bytes_written = 0;

  currentMessage = {};

  currentMessage.topic = TentacleMessageTopic_ping;
  currentMessage.has_topic = true;

  bool status = pb_encode_delimited(&pbOutput, TentacleMessage_fields, &currentMessage);

  return pbOutput.bytes_written != 0;
}

TentacleMessageTopic Pseudopod::readMessage() {
  resetPinActions();

  currentMessage = {};
  currentMessage.pins.funcs.decode = &Pseudopod::pinDecode;
  currentMessage.pins.arg = (void*) this;

  bool status = pb_decode_delimited(&pbInput, TentacleMessage_fields, &currentMessage);

  if (currentMessage.topic == TentacleMessageTopic_config) {
    for(int i = 0; i < tentacle->getNumPins(); i++) {
        pseudopod->tentacle->configurePin(i, messagePinActions[i]);
    }

    configured = true;
    broadcastPins = currentMessage.broadcastPins;
    broadcastInterval = currentMessage.broadcastInterval;
  }

  return currentMessage.topic;
}

bool Pseudopod::pinEncode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
  Pseudopod *pseudopod = (Pseudopod*) *arg;
  Action action;
  Pin pin;

  for(int i = 0; i < pseudopod->tentacle->getNumPins(); i++) {
    action = pseudopod->messagePinActions[i];
    if(action == Action_ignore) {
      continue;
    }

    pin = {};
    pin.has_action = true;
    pin.action = action;
    pin.has_number = true;
    pin.number = i;
    int value = pseudopod->tentacle->processPin(i);

    if(value != -1) {
      pin.has_value = true;
      pin.value = value;
    }

    if (!pb_encode_tag_for_field(stream, field)) {
      return false;
    }

    if(!pb_encode_submessage(stream, Pin_fields, &pin)) {
      return false;
    }
  }

  return true;
}

bool Pseudopod::pinDecode(pb_istream_t *stream, const pb_field_t *field, void **arg) {
  Pseudopod *pseudopod = (Pseudopod*) *arg;
  Pin pin = {};

  if (!pb_decode(stream, Pin_fields, &pin)) {
    return false;
  }

  TentacleMessage& message = pseudopod->currentMessage;
  pseudopod->messagePinActions[pin.number] = pin.action;

  if(message.topic == TentacleMessageTopic_action) {
    pseudopod->tentacle->processPin(pin.number, pin.value);
  }

  return true;
}
<|endoftext|>