<commit_before>#ifndef _FM_INDEX_RANGE_LIST_HPP
#define _FM_INDEX_RANGE_LIST_HPP

#include "wavelet_tree_node.hpp"

#include <boost/tuple/tuple.hpp>

NS_IZENELIB_AM_BEGIN

namespace succinct
{
namespace fm_index
{

namespace detail
{

static double getScore(const std::vector<boost::tuple<size_t, size_t, double> > &patterns)
{
    double score = 0.0;

    for (std::vector<boost::tuple<size_t, size_t, double> >::const_iterator it = patterns.begin();
            it != patterns.end(); ++it)
    {
        score += it->get<2>();
    }

    return score;
}

static struct InvalidRange
{
    bool operator()(const std::pair<size_t, size_t> &range) const
    {
        return range.first >= range.second;
    }

    bool operator()(const boost::tuple<size_t, size_t, double> &range) const
    {
        return range.get<0>() >= range.get<1>();
    }
} InvalidRange;

}

class PatternList
{
public:
    PatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            const std::vector<boost::tuple<size_t, size_t, double> > &patterns)
        : level_(level)
        , sym_(sym)
        , node_(node)
        , patterns_(patterns)
    {
//      patterns_.erase(std::remove_if(patterns_.begin(), patterns_.end(), detail::InvalidRange), patterns_.end());
        score_ = detail::getScore(patterns_);
    }

    PatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            size_t pattern_count)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
    {
        patterns_.reserve(pattern_count);
    }

    ~PatternList() {}

    void addPattern(const boost::tuple<size_t, size_t, double> &pattern)
    {
        if (pattern.get<0>() < pattern.get<1>())
            patterns_.push_back(pattern);
    }

    void calcScore()
    {
        score_ = detail::getScore(patterns_);
    }

    bool operator<(const PatternList &rhs) const
    {
        return score_ < rhs.score_ || (score_ == rhs.score_ && level_ < rhs.level_);
    }

public:
    size_t level_;
    uint64_t sym_;
    double score_;
    const WaveletTreeNode *node_;
    std::vector<boost::tuple<size_t, size_t, double> > patterns_;
};

class FilteredPatternList
{
public:
    FilteredPatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            const std::vector<std::pair<size_t, size_t> > &filters,
            const std::vector<boost::tuple<size_t, size_t, double> > &patterns)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
        , filters_(filters)
        , patterns_(patterns)
    {
//      filters_.erase(std::remove_if(filters_.begin(), filters_.end(), detail::InvalidRange), filters_.end());
        if (!filters_.empty())
        {
//          patterns_.erase(std::remove_if(patterns_.begin(), patterns_.end(), detail::InvalidRange), patterns_.end());
            score_ = detail::getScore(patterns_);
        }
    }

    FilteredPatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            size_t filter_count, size_t pattern_count)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
    {
        filters_.reserve(filter_count);
        patterns_.reserve(pattern_count);
    }

    ~FilteredPatternList() {}

    void addFilter(const std::pair<size_t, size_t> &filter)
    {
        if (filter.first < filter.second)
            filters_.push_back(filter);
    }

    void addPattern(const boost::tuple<size_t, size_t, double> &pattern)
    {
        if (pattern.get<0>() < pattern.get<1>())
            patterns_.push_back(pattern);
    }

    void calcScore()
    {
        score_ = detail::getScore(patterns_);
    }

    bool operator<(const FilteredPatternList &rhs) const
    {
        return score_ < rhs.score_ || (score_ == rhs.score_ && level_ < rhs.level_);
    }

public:
    size_t level_;
    uint64_t sym_;
    double score_;
    const WaveletTreeNode *node_;
    std::vector<std::pair<size_t, size_t> > filters_;
    std::vector<boost::tuple<size_t, size_t, double> > patterns_;
};

template <class WaveletTreeType>
class FilterList
{
public:
    FilterList(
            const WaveletTreeType *tree, const WaveletTreeNode *node,
            const std::vector<std::pair<size_t, size_t> > &filters)
        : tree_(tree) , node_(node)
        , filters_(filters)
    {
//      filters_.erase(std::remove_if(filters_.begin(), filters_.end(), detail::InvalidRange), filters_.end());
    }

    FilterList(
            const WaveletTreeType *tree, const WaveletTreeNode *node,
            size_t filter_count)
        : tree_(tree) , node_(node)
    {
        filters_.reserve(filter_count);
    }

    ~FilterList() {}

    void addFilter(const std::pair<size_t, size_t> &filter)
    {
        if (filter.first < filter.second)
            filters_.push_back(filter);
    }

public:
    const WaveletTreeType *tree_;
    const WaveletTreeNode *node_;
    std::vector<std::pair<size_t, size_t> > filters_;
};

template <class WaveletTreeType>
class AuxFilteredPatternList
{
public:
    AuxFilteredPatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            const std::vector<FilterList<WaveletTreeType> *> &aux_filters,
            const std::vector<std::pair<size_t, size_t> > &filters,
            const std::vector<boost::tuple<size_t, size_t, double> > &patterns)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
        , aux_filters_(aux_filters)
        , filters_(filters)
        , patterns_(patterns)
    {
//      filters_.erase(std::remove_if(filters_.begin(), filters_.end(), detail::InvalidRange), filters_.end());
        if (!aux_filters_.empty() || !filters_.empty())
        {
//          patterns_.erase(std::remove_if(patterns_.begin(), patterns_.end(), detail::InvalidRange), patterns_.end());
            score_ = detail::getScore(patterns_);
        }
    }

    AuxFilteredPatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            size_t aux_filter_count, size_t filter_count, size_t pattern_count)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
    {
        aux_filters_.reserve(aux_filter_count);
        filters_.reserve(filter_count);
        patterns_.reserve(pattern_count);
    }

    ~AuxFilteredPatternList()
    {
        for (size_t i = 0; i < aux_filters_.size(); ++i)
        {
            delete aux_filters_[i];
        }
    }

    void addFilter(const std::pair<size_t, size_t> &filter)
    {
        if (filter.first < filter.second)
            filters_.push_back(filter);
    }

    void addAuxFilter(FilterList<WaveletTreeType> *aux_filter)
    {
    }

    void addPattern(const boost::tuple<size_t, size_t, double> &pattern)
    {
        if (pattern.get<0>() < pattern.get<1>())
            patterns_.push_back(pattern);
    }

    void calcScore()
    {
        score_ = detail::getScore(patterns_);
    }

    bool operator<(const AuxFilteredPatternList &rhs) const
    {
        return score_ < rhs.score_ || (score_ == rhs.score_ && level_ < rhs.level_);
    }

public:
    size_t level_;
    uint64_t sym_;
    double score_;
    const WaveletTreeNode *node_;
    std::vector<FilterList<WaveletTreeType> *> aux_filters_;
    std::vector<std::pair<size_t, size_t> > filters_;
    std::vector<boost::tuple<size_t, size_t, double> > patterns_;
};

}
}

NS_IZENELIB_AM_END

namespace std
{

template <>
struct less<izenelib::am::succinct::fm_index::PatternList *>
{
    bool operator()(izenelib::am::succinct::fm_index::PatternList * const &p1, izenelib::am::succinct::fm_index::PatternList * const &p2)
    {
        return *p1 < *p2;
    }
};

template <class T>
struct less<pair<izenelib::am::succinct::fm_index::PatternList *, T> >
{
    bool operator()(pair<izenelib::am::succinct::fm_index::PatternList *, T> const &p1, pair<izenelib::am::succinct::fm_index::PatternList *, T> const &p2)
    {
        return *p1.first < *p2.first;
    }
};

template <>
struct less<izenelib::am::succinct::fm_index::FilteredPatternList *>
{
    bool operator()(izenelib::am::succinct::fm_index::FilteredPatternList * const &p1, izenelib::am::succinct::fm_index::FilteredPatternList * const &p2)
    {
        return *p1 < *p2;
    }
};

template <class T>
struct less<pair<izenelib::am::succinct::fm_index::FilteredPatternList *, T> >
{
    bool operator()(pair<izenelib::am::succinct::fm_index::FilteredPatternList *, T> const &p1, pair<izenelib::am::succinct::fm_index::FilteredPatternList *, T> const &p2)
    {
        return *p1.first < *p2.first;
    }
};

template <class W>
struct less<izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> *>
{
    bool operator()(izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> * const &p1, izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> * const &p2)
    {
        return *p1 < *p2;
    }
};

template <class W, class T>
struct less<pair<izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> *, T> >
{
    bool operator()(pair<izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> *, T> const &p1, pair<izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> *, T> const &p2)
    {
        return *p1.first < *p2.first;
    }
};

}

#endif
<commit_msg>fix AuxFilteredPatternList::addAuxFilter()<commit_after>#ifndef _FM_INDEX_RANGE_LIST_HPP
#define _FM_INDEX_RANGE_LIST_HPP

#include "wavelet_tree_node.hpp"

#include <boost/tuple/tuple.hpp>

NS_IZENELIB_AM_BEGIN

namespace succinct
{
namespace fm_index
{

namespace detail
{

static double getScore(const std::vector<boost::tuple<size_t, size_t, double> > &patterns)
{
    double score = 0.0;

    for (std::vector<boost::tuple<size_t, size_t, double> >::const_iterator it = patterns.begin();
            it != patterns.end(); ++it)
    {
        score += it->get<2>();
    }

    return score;
}

static struct InvalidRange
{
    bool operator()(const std::pair<size_t, size_t> &range) const
    {
        return range.first >= range.second;
    }

    bool operator()(const boost::tuple<size_t, size_t, double> &range) const
    {
        return range.get<0>() >= range.get<1>();
    }
} InvalidRange;

}

class PatternList
{
public:
    PatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            const std::vector<boost::tuple<size_t, size_t, double> > &patterns)
        : level_(level)
        , sym_(sym)
        , node_(node)
        , patterns_(patterns)
    {
//      patterns_.erase(std::remove_if(patterns_.begin(), patterns_.end(), detail::InvalidRange), patterns_.end());
        score_ = detail::getScore(patterns_);
    }

    PatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            size_t pattern_count)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
    {
        patterns_.reserve(pattern_count);
    }

    ~PatternList() {}

    void addPattern(const boost::tuple<size_t, size_t, double> &pattern)
    {
        if (pattern.get<0>() < pattern.get<1>())
            patterns_.push_back(pattern);
    }

    void calcScore()
    {
        score_ = detail::getScore(patterns_);
    }

    bool operator<(const PatternList &rhs) const
    {
        return score_ < rhs.score_ || (score_ == rhs.score_ && level_ < rhs.level_);
    }

public:
    size_t level_;
    uint64_t sym_;
    double score_;
    const WaveletTreeNode *node_;
    std::vector<boost::tuple<size_t, size_t, double> > patterns_;
};

class FilteredPatternList
{
public:
    FilteredPatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            const std::vector<std::pair<size_t, size_t> > &filters,
            const std::vector<boost::tuple<size_t, size_t, double> > &patterns)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
        , filters_(filters)
        , patterns_(patterns)
    {
//      filters_.erase(std::remove_if(filters_.begin(), filters_.end(), detail::InvalidRange), filters_.end());
        if (!filters_.empty())
        {
//          patterns_.erase(std::remove_if(patterns_.begin(), patterns_.end(), detail::InvalidRange), patterns_.end());
            score_ = detail::getScore(patterns_);
        }
    }

    FilteredPatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            size_t filter_count, size_t pattern_count)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
    {
        filters_.reserve(filter_count);
        patterns_.reserve(pattern_count);
    }

    ~FilteredPatternList() {}

    void addFilter(const std::pair<size_t, size_t> &filter)
    {
        if (filter.first < filter.second)
            filters_.push_back(filter);
    }

    void addPattern(const boost::tuple<size_t, size_t, double> &pattern)
    {
        if (pattern.get<0>() < pattern.get<1>())
            patterns_.push_back(pattern);
    }

    void calcScore()
    {
        score_ = detail::getScore(patterns_);
    }

    bool operator<(const FilteredPatternList &rhs) const
    {
        return score_ < rhs.score_ || (score_ == rhs.score_ && level_ < rhs.level_);
    }

public:
    size_t level_;
    uint64_t sym_;
    double score_;
    const WaveletTreeNode *node_;
    std::vector<std::pair<size_t, size_t> > filters_;
    std::vector<boost::tuple<size_t, size_t, double> > patterns_;
};

template <class WaveletTreeType>
class FilterList
{
public:
    FilterList(
            const WaveletTreeType *tree, const WaveletTreeNode *node,
            const std::vector<std::pair<size_t, size_t> > &filters)
        : tree_(tree) , node_(node)
        , filters_(filters)
    {
//      filters_.erase(std::remove_if(filters_.begin(), filters_.end(), detail::InvalidRange), filters_.end());
    }

    FilterList(
            const WaveletTreeType *tree, const WaveletTreeNode *node,
            size_t filter_count)
        : tree_(tree) , node_(node)
    {
        filters_.reserve(filter_count);
    }

    ~FilterList() {}

    void addFilter(const std::pair<size_t, size_t> &filter)
    {
        if (filter.first < filter.second)
            filters_.push_back(filter);
    }

public:
    const WaveletTreeType *tree_;
    const WaveletTreeNode *node_;
    std::vector<std::pair<size_t, size_t> > filters_;
};

template <class WaveletTreeType>
class AuxFilteredPatternList
{
public:
    AuxFilteredPatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            const std::vector<FilterList<WaveletTreeType> *> &aux_filters,
            const std::vector<std::pair<size_t, size_t> > &filters,
            const std::vector<boost::tuple<size_t, size_t, double> > &patterns)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
        , aux_filters_(aux_filters)
        , filters_(filters)
        , patterns_(patterns)
    {
//      filters_.erase(std::remove_if(filters_.begin(), filters_.end(), detail::InvalidRange), filters_.end());
        if (!aux_filters_.empty() || !filters_.empty())
        {
//          patterns_.erase(std::remove_if(patterns_.begin(), patterns_.end(), detail::InvalidRange), patterns_.end());
            score_ = detail::getScore(patterns_);
        }
    }

    AuxFilteredPatternList(
            size_t level, uint64_t sym,
            const WaveletTreeNode *node,
            size_t aux_filter_count, size_t filter_count, size_t pattern_count)
        : level_(level)
        , sym_(sym)
        , score_()
        , node_(node)
    {
        aux_filters_.reserve(aux_filter_count);
        filters_.reserve(filter_count);
        patterns_.reserve(pattern_count);
    }

    ~AuxFilteredPatternList()
    {
        for (size_t i = 0; i < aux_filters_.size(); ++i)
        {
            delete aux_filters_[i];
        }
    }

    void addFilter(const std::pair<size_t, size_t> &filter)
    {
        if (filter.first < filter.second)
            filters_.push_back(filter);
    }

    void addAuxFilter(FilterList<WaveletTreeType> *aux_filter)
    {
        if (aux_filter)
        {
            if (!aux_filter->filters_.empty())
                aux_filters_.push_back(aux_filter);
            else
                delete aux_filter;
        }
    }

    void addPattern(const boost::tuple<size_t, size_t, double> &pattern)
    {
        if (pattern.get<0>() < pattern.get<1>())
            patterns_.push_back(pattern);
    }

    void calcScore()
    {
        score_ = detail::getScore(patterns_);
    }

    bool operator<(const AuxFilteredPatternList &rhs) const
    {
        return score_ < rhs.score_ || (score_ == rhs.score_ && level_ < rhs.level_);
    }

public:
    size_t level_;
    uint64_t sym_;
    double score_;
    const WaveletTreeNode *node_;
    std::vector<FilterList<WaveletTreeType> *> aux_filters_;
    std::vector<std::pair<size_t, size_t> > filters_;
    std::vector<boost::tuple<size_t, size_t, double> > patterns_;
};

}
}

NS_IZENELIB_AM_END

namespace std
{

template <>
struct less<izenelib::am::succinct::fm_index::PatternList *>
{
    bool operator()(izenelib::am::succinct::fm_index::PatternList * const &p1, izenelib::am::succinct::fm_index::PatternList * const &p2)
    {
        return *p1 < *p2;
    }
};

template <class T>
struct less<pair<izenelib::am::succinct::fm_index::PatternList *, T> >
{
    bool operator()(pair<izenelib::am::succinct::fm_index::PatternList *, T> const &p1, pair<izenelib::am::succinct::fm_index::PatternList *, T> const &p2)
    {
        return *p1.first < *p2.first;
    }
};

template <>
struct less<izenelib::am::succinct::fm_index::FilteredPatternList *>
{
    bool operator()(izenelib::am::succinct::fm_index::FilteredPatternList * const &p1, izenelib::am::succinct::fm_index::FilteredPatternList * const &p2)
    {
        return *p1 < *p2;
    }
};

template <class T>
struct less<pair<izenelib::am::succinct::fm_index::FilteredPatternList *, T> >
{
    bool operator()(pair<izenelib::am::succinct::fm_index::FilteredPatternList *, T> const &p1, pair<izenelib::am::succinct::fm_index::FilteredPatternList *, T> const &p2)
    {
        return *p1.first < *p2.first;
    }
};

template <class W>
struct less<izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> *>
{
    bool operator()(izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> * const &p1, izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> * const &p2)
    {
        return *p1 < *p2;
    }
};

template <class W, class T>
struct less<pair<izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> *, T> >
{
    bool operator()(pair<izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> *, T> const &p1, pair<izenelib::am::succinct::fm_index::AuxFilteredPatternList<W> *, T> const &p2)
    {
        return *p1.first < *p2.first;
    }
};

}

#endif
<|endoftext|>


<commit_before>#ifdef EXTINT_H
#ifndef EXTINT_HPP
#define EXTINT_HPP

ExtInt::DListNode & ExtInt::DListNode::remove() {
	DListNode *tmp = this -> forward;
	tmp -> forward -> next = this;
	this -> forward = tmp -> forward;
	delete tmp;
	return *this;
}
ExtInt::DListNode & ExtInt::DListNode::append(DListNode *data) {
	data -> next = this -> next;
	data -> forward = this;
	if (this -> next != NULL) {
		this -> next -> forward = data;
	}
	this -> next = data;
	return *this;
}
ExtInt::DListNode & ExtInt::DListNode::append(const int &data) {
	return append(new DListNode(data));
}
ExtInt::DListNode & ExtInt::DListNode::insert(DListNode *data) {
	data -> next = this;
	data -> forward = this -> forward;
	if (this -> forward != NULL) {
		this -> forward -> next = data;
	}
	this -> forward = data;
	return *this;
}
ExtInt::DListNode & ExtInt::DListNode::insert(const int &data) {
	return insert(new DListNode(data));
}

ExtInt::ExtInt(int data) {
	low = new DListNode;
	high = new DListNode;
	low -> append(high);
	length = 0;
	isNegative = false;
	if (data < 0) {
		isNegative = true;
		data = -data;
	}
	while (data >= ExtInt::LIMIT) {
		high -> insert(data % ExtInt::LIMIT);
		data /= ExtInt::LIMIT;
		length++;
	}
	if (length == 0 || data > 0) {
		high -> insert(data);
		length++;
	}
}
ExtInt::ExtInt(const ExtInt &rhs) {
	low = new DListNode;
	high = new DListNode;
	low -> append(high);
	length = 0;
	isNegative = rhs.isNegative;
	for (DListNode *it = rhs.low -> next; it != rhs.high; it = it -> next) {
		high -> insert(it -> data);
		length++;
	}
}
ExtInt::ExtInt(const std::string &rhs) {
	low = new DListNode;
	high = new DListNode;
	low -> append(high);
	length = 0;
	isNegative = false;
	if (rhs[0] == '-') {
		isNegative = true;
	}
	for (int i = rhs.length() - 1; i >= 0; i -= WIDTH) {
		int value = 0;
		for (int j = std::max(0, i - WIDTH + 1); j <= i; j++) {
			if (j == 0 && isNegative) continue;
			assert(isdigit(rhs[j]));
			value = value * 10 + rhs[j] - '0';
		}
		high -> insert(value);
		length++;
	}
	while (length > 1 && high -> forward -> data == 0) {
		high -> remove();
		length--;
	}
}
ExtInt & ExtInt::operator =(const ExtInt &rhs) {
	if (this == &rhs) return *this;
	if (low != NULL || high != NULL) {
		this -> ~ExtInt();
	}
	low = new DListNode;
	high = new DListNode;
	low -> append(high);
	length = 0;
	isNegative = rhs.isNegative;
	for (DListNode *it = rhs.low -> next; it != rhs.high; it = it -> next) {
		high -> insert(it -> data);
		length++;
	}
	return *this;
}
ExtInt::~ExtInt() {
	for (DListNode *it = low; it != NULL;) {
		DListNode *tmp = it -> next;
		delete it;
		it = tmp;
	}
}

std::istream & operator >>(std::istream &inputStream, ExtInt &data) {
	std::string tmp;
	inputStream >> tmp;
	data = ExtInt(tmp);
	return inputStream;
}
std::ostream & operator <<(std::ostream &outputStream, const ExtInt &data) {
	if (data.isNegative) {
		outputStream << "-";
	}
	ExtInt::DListNode *it = data.high -> forward;
	outputStream << it -> data;
	for (it = it -> forward; it != data.low; it = it -> forward) {
		outputStream << std::setfill('0') << std::setw(ExtInt::WIDTH) << it -> data;
	}
	return outputStream;
}

bool operator <(const ExtInt &a, const ExtInt &b) {
	if (a.isNegative && !b.isNegative) return true;
	if (!a.isNegative && b.isNegative) return false;
	bool flag = false;
	if (a.isNegative && b.isNegative) flag = true;
	if (a.length < b.length) return flag ^ true;
	if (a.length > b.length) return flag ^ false;
	ExtInt::DListNode *itA = a.high, *itB = b.high;
	for (; itA != a.low && itB != b.low; itA = itA -> forward, itB = itB -> forward) {
		if (itA -> data < itB -> data) return flag ^ true;
		if (itA -> data > itB -> data) return flag ^ false;
	}
	return false;
}
bool operator >(const ExtInt &a, const ExtInt &b) {
	if (a.isNegative && !b.isNegative) return false;
	if (!a.isNegative && b.isNegative) return true;
	bool flag = false;
	if (a.isNegative && b.isNegative) flag = true;
	if (a.length < b.length) return flag ^ false;
	if (a.length > b.length) return flag ^ true;
	ExtInt::DListNode *itA = a.high, *itB = b.high;
	for (; itA != a.low && itB != b.low; itA = itA -> forward, itB = itB -> forward) {
		if (itA -> data < itB -> data) return flag ^ false;
		if (itA -> data > itB -> data) return flag ^ true;
	}
	return false;
}
bool operator >=(const ExtInt &a, const ExtInt &b) {
	return !(a < b);
}
bool operator <=(const ExtInt &a, const ExtInt &b) {
	return !(a > b);
}
bool operator ==(const ExtInt &a, const ExtInt &b) {
	if (a.isNegative != b.isNegative) return false;
	if (a.length != b.length) return false;
	ExtInt::DListNode *itA = a.low, *itB = b.low;
	for (; itA != a.high && itB != b.high; itA = itA -> next, itB = itB -> next) {
		if (itA -> data != itB -> data) return false;
	}
	return true;
}
bool operator !=(const ExtInt &a, const ExtInt &b) {
	return !(a == b);
}

ExtInt operator +(const ExtInt &a, const ExtInt &b) {
	if (b.isNegative) {
		ExtInt tmp = b;
		tmp.isNegative = false;
		return a - tmp;
	}
	if (a.isNegative) {
		ExtInt tmp = a;
		tmp.isNegative = false;
		return b - tmp;
	}
	ExtInt ret = a;
	ExtInt::DListNode *itA = ret.low -> next, *itB = b.low -> next;
	for (; itB != b.high; itA = itA -> next, itB = itB -> next) {
		if (itA == ret.high) {
			itA -> insert(0);
			ret.length++;
			itA = itA -> forward;
		}
		itA -> data += itB -> data;
		if (itA -> data >= ExtInt::LIMIT) {
			if (itA -> next == ret.high) {
				itA -> append(0);
				ret.length++;
			}
			itA -> next -> data += itA -> data / ExtInt::LIMIT;
			itA -> data %= ExtInt::LIMIT;
		}
	}
	return ret;
}
ExtInt operator -(const ExtInt &a, const ExtInt &b) {
	if (b.isNegative) {
		ExtInt tmp = b;
		tmp.isNegative = false;
		return a + tmp;
	}
	if (a.isNegative) {
		ExtInt tmp = a;
		tmp.isNegative = false;
		tmp = tmp + b;
		tmp.isNegative = true;
		return tmp;
	}
	if (a < b) {
		ExtInt tmp = b - a;
		tmp.isNegative = true;
		return tmp;
	}
	ExtInt ret = a;
	ExtInt::DListNode *itA = ret.low -> next, *itB = b.low -> next;
	for (; itA != ret.high && itB != b.high; itA = itA -> next, itB = itB -> next) {
		itA -> data -= itB -> data;
		if (itA -> data < 0) {
			itA -> data += ExtInt::LIMIT;
			itA -> next -> data--;
		}
	}
	for (; itA != ret.high; itA = itA -> next) {
		if (itA -> data < 0) {
			itA -> data += ExtInt::LIMIT;
			itA -> next -> data--;
		}
	}
	while (ret.length > 1 && ret.high -> forward -> data == 0) {
		ret.high -> remove();
		ret.length--;
	}
	return ret;
}
ExtInt operator *(const ExtInt &a, const ExtInt &b) {
	if (a == ExtInt(0) || b == ExtInt(0)) return ExtInt(0);
	ExtInt ret, tmp;
	ExtInt::DListNode *itB = b.low -> next;
	for (int value = 0; itB != b.high; itB = itB -> next, value++) {
		if (itB -> data == 0) {
			continue;
		}
		tmp = a;
		for (ExtInt::DListNode *itA = tmp.low -> next; itA != tmp.high; itA = itA -> next) {
			itA -> data *= itB -> data;
		}
		for (ExtInt::DListNode *itA = tmp.low -> next; itA != tmp.high; itA = itA -> next) {
			if (itA -> data >= ExtInt::LIMIT) {
				if (itA -> next == tmp.high) {
					itA -> append(0);
					tmp.length++;
				}
				itA -> next -> data += itA -> data / ExtInt::LIMIT;
				itA -> data %= ExtInt::LIMIT;
			}
		}
		for (int i = 1; i <= value; i++) {
			tmp.low -> append(0);
			tmp.length++;
		}
		//std::cerr << ret << std::endl;
		//std::cerr << tmp << std::endl;
		//std::cerr << tmp.length << std::endl;
		ret = ret + tmp;
	}
	ret.isNegative = a.isNegative ^ b.isNegative;
	return ret;
}
ExtInt operator /(const ExtInt &a, const ExtInt &b) {
	assert(b != ExtInt(0));
	if (a == ExtInt(0)) return ExtInt(0);
	ExtInt ret, tmp, div = b;
	ret.high -> remove();
	ret.length = 0;
	tmp.high -> remove();
	tmp.length = 0;
	div.isNegative = false;
	ExtInt::DListNode *itA = a.high -> forward;
	for (; itA != a.low; itA = itA -> forward) {
		tmp.low -> append(itA -> data);
		tmp.length++;
		if (tmp >= div) {
			int left = 0, right = ExtInt::LIMIT - 1;
			while (left < right) {
				int middle = (left + right >> 1) + 1;
				if (tmp >= div * middle) {
					left = middle;
				} else {
					right = middle - 1;
				}
			}
			//std::cerr << tmp << " " << div * left << std::endl;
			ret.low -> append(left);
			ret.length++;
			tmp = tmp - div * left;
			if (tmp == ExtInt(0)) {
				tmp.high -> remove();
				tmp.length = 0;
			}
		} else {
			ret.low -> append(0);
			ret.length++;
		}
	}
	while (ret.length > 1 && ret.high -> forward -> data == 0) {
		ret.high -> remove();
		ret.length--;
	}
	ret.isNegative = a.isNegative ^ b.isNegative;
	if (ret.isNegative && tmp.low -> next != tmp.high) {
		ret = ret - 1;
	}
	return ret;
}
ExtInt operator %(const ExtInt &a, const ExtInt &b) {
	return a - a / b * b;
}

ExtInt & ExtInt::operator +=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}
ExtInt & ExtInt::operator -=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}
ExtInt & ExtInt::operator *=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}
ExtInt & ExtInt::operator /=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}
ExtInt & ExtInt::operator %=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}

#endif
#endif
<commit_msg>Division Module Mistakes Fixed.<commit_after>#ifdef EXTINT_H
#ifndef EXTINT_HPP
#define EXTINT_HPP

ExtInt::DListNode & ExtInt::DListNode::remove() {
	DListNode *tmp = this -> forward;
	tmp -> forward -> next = this;
	this -> forward = tmp -> forward;
	delete tmp;
	return *this;
}
ExtInt::DListNode & ExtInt::DListNode::append(DListNode *data) {
	data -> next = this -> next;
	data -> forward = this;
	if (this -> next != NULL) {
		this -> next -> forward = data;
	}
	this -> next = data;
	return *this;
}
ExtInt::DListNode & ExtInt::DListNode::append(const int &data) {
	return append(new DListNode(data));
}
ExtInt::DListNode & ExtInt::DListNode::insert(DListNode *data) {
	data -> next = this;
	data -> forward = this -> forward;
	if (this -> forward != NULL) {
		this -> forward -> next = data;
	}
	this -> forward = data;
	return *this;
}
ExtInt::DListNode & ExtInt::DListNode::insert(const int &data) {
	return insert(new DListNode(data));
}

ExtInt::ExtInt(int data) {
	low = new DListNode;
	high = new DListNode;
	low -> append(high);
	length = 0;
	isNegative = false;
	if (data < 0) {
		isNegative = true;
		data = -data;
	}
	while (data >= ExtInt::LIMIT) {
		high -> insert(data % ExtInt::LIMIT);
		data /= ExtInt::LIMIT;
		length++;
	}
	if (length == 0 || data > 0) {
		high -> insert(data);
		length++;
	}
}
ExtInt::ExtInt(const ExtInt &rhs) {
	low = new DListNode;
	high = new DListNode;
	low -> append(high);
	length = 0;
	isNegative = rhs.isNegative;
	for (DListNode *it = rhs.low -> next; it != rhs.high; it = it -> next) {
		high -> insert(it -> data);
		length++;
	}
}
ExtInt::ExtInt(const std::string &rhs) {
	low = new DListNode;
	high = new DListNode;
	low -> append(high);
	length = 0;
	isNegative = false;
	if (rhs[0] == '-') {
		isNegative = true;
	}
	for (int i = rhs.length() - 1; i >= 0; i -= WIDTH) {
		int value = 0;
		for (int j = std::max(0, i - WIDTH + 1); j <= i; j++) {
			if (j == 0 && isNegative) continue;
			assert(isdigit(rhs[j]));
			value = value * 10 + rhs[j] - '0';
		}
		high -> insert(value);
		length++;
	}
	while (length > 1 && high -> forward -> data == 0) {
		high -> remove();
		length--;
	}
}
ExtInt & ExtInt::operator =(const ExtInt &rhs) {
	if (this == &rhs) return *this;
	if (low != NULL || high != NULL) {
		this -> ~ExtInt();
	}
	low = new DListNode;
	high = new DListNode;
	low -> append(high);
	length = 0;
	isNegative = rhs.isNegative;
	for (DListNode *it = rhs.low -> next; it != rhs.high; it = it -> next) {
		high -> insert(it -> data);
		length++;
	}
	return *this;
}
ExtInt::~ExtInt() {
	for (DListNode *it = low; it != NULL;) {
		DListNode *tmp = it -> next;
		delete it;
		it = tmp;
	}
}

std::istream & operator >>(std::istream &inputStream, ExtInt &data) {
	std::string tmp;
	inputStream >> tmp;
	data = ExtInt(tmp);
	return inputStream;
}
std::ostream & operator <<(std::ostream &outputStream, const ExtInt &data) {
	if (data.isNegative) {
		outputStream << "-";
	}
	ExtInt::DListNode *it = data.high -> forward;
	outputStream << it -> data;
	for (it = it -> forward; it != data.low; it = it -> forward) {
		outputStream << std::setfill('0') << std::setw(ExtInt::WIDTH) << it -> data;
	}
	return outputStream;
}

bool operator <(const ExtInt &a, const ExtInt &b) {
	if (a.isNegative && !b.isNegative) return true;
	if (!a.isNegative && b.isNegative) return false;
	bool flag = false;
	if (a.isNegative && b.isNegative) flag = true;
	if (a.length < b.length) return flag ^ true;
	if (a.length > b.length) return flag ^ false;
	ExtInt::DListNode *itA = a.high, *itB = b.high;
	for (; itA != a.low && itB != b.low; itA = itA -> forward, itB = itB -> forward) {
		if (itA -> data < itB -> data) return flag ^ true;
		if (itA -> data > itB -> data) return flag ^ false;
	}
	return false;
}
bool operator >(const ExtInt &a, const ExtInt &b) {
	if (a.isNegative && !b.isNegative) return false;
	if (!a.isNegative && b.isNegative) return true;
	bool flag = false;
	if (a.isNegative && b.isNegative) flag = true;
	if (a.length < b.length) return flag ^ false;
	if (a.length > b.length) return flag ^ true;
	ExtInt::DListNode *itA = a.high, *itB = b.high;
	for (; itA != a.low && itB != b.low; itA = itA -> forward, itB = itB -> forward) {
		if (itA -> data < itB -> data) return flag ^ false;
		if (itA -> data > itB -> data) return flag ^ true;
	}
	return false;
}
bool operator >=(const ExtInt &a, const ExtInt &b) {
	return !(a < b);
}
bool operator <=(const ExtInt &a, const ExtInt &b) {
	return !(a > b);
}
bool operator ==(const ExtInt &a, const ExtInt &b) {
	if (a.isNegative != b.isNegative) return false;
	if (a.length != b.length) return false;
	ExtInt::DListNode *itA = a.low, *itB = b.low;
	for (; itA != a.high && itB != b.high; itA = itA -> next, itB = itB -> next) {
		if (itA -> data != itB -> data) return false;
	}
	return true;
}
bool operator !=(const ExtInt &a, const ExtInt &b) {
	return !(a == b);
}

ExtInt operator +(const ExtInt &a, const ExtInt &b) {
	if (b.isNegative) {
		ExtInt tmp = b;
		tmp.isNegative = false;
		return a - tmp;
	}
	if (a.isNegative) {
		ExtInt tmp = a;
		tmp.isNegative = false;
		return b - tmp;
	}
	ExtInt ret = a;
	ExtInt::DListNode *itA = ret.low -> next, *itB = b.low -> next;
	for (; itB != b.high; itA = itA -> next, itB = itB -> next) {
		if (itA == ret.high) {
			itA -> insert(0);
			ret.length++;
			itA = itA -> forward;
		}
		itA -> data += itB -> data;
		if (itA -> data >= ExtInt::LIMIT) {
			if (itA -> next == ret.high) {
				itA -> append(0);
				ret.length++;
			}
			itA -> next -> data += itA -> data / ExtInt::LIMIT;
			itA -> data %= ExtInt::LIMIT;
		}
	}
	return ret;
}
ExtInt operator -(const ExtInt &a, const ExtInt &b) {
	if (b.isNegative) {
		ExtInt tmp = b;
		tmp.isNegative = false;
		return a + tmp;
	}
	if (a.isNegative) {
		ExtInt tmp = a;
		tmp.isNegative = false;
		tmp = tmp + b;
		tmp.isNegative = true;
		return tmp;
	}
	if (a < b) {
		ExtInt tmp = b - a;
		tmp.isNegative = true;
		return tmp;
	}
	ExtInt ret = a;
	ExtInt::DListNode *itA = ret.low -> next, *itB = b.low -> next;
	for (; itA != ret.high && itB != b.high; itA = itA -> next, itB = itB -> next) {
		itA -> data -= itB -> data;
		if (itA -> data < 0) {
			itA -> data += ExtInt::LIMIT;
			itA -> next -> data--;
		}
	}
	for (; itA != ret.high; itA = itA -> next) {
		if (itA -> data < 0) {
			itA -> data += ExtInt::LIMIT;
			itA -> next -> data--;
		}
	}
	while (ret.length > 1 && ret.high -> forward -> data == 0) {
		ret.high -> remove();
		ret.length--;
	}
	return ret;
}
ExtInt operator *(const ExtInt &a, const ExtInt &b) {
	if (a == ExtInt(0) || b == ExtInt(0)) return ExtInt(0);
	ExtInt ret, tmp;
	ExtInt::DListNode *itB = b.low -> next;
	for (int value = 0; itB != b.high; itB = itB -> next, value++) {
		if (itB -> data == 0) {
			continue;
		}
		tmp = a;
		for (ExtInt::DListNode *itA = tmp.low -> next; itA != tmp.high; itA = itA -> next) {
			itA -> data *= itB -> data;
		}
		for (ExtInt::DListNode *itA = tmp.low -> next; itA != tmp.high; itA = itA -> next) {
			if (itA -> data >= ExtInt::LIMIT) {
				if (itA -> next == tmp.high) {
					itA -> append(0);
					tmp.length++;
				}
				itA -> next -> data += itA -> data / ExtInt::LIMIT;
				itA -> data %= ExtInt::LIMIT;
			}
		}
		for (int i = 1; i <= value; i++) {
			tmp.low -> append(0);
			tmp.length++;
		}
		//std::cerr << ret << std::endl;
		//std::cerr << tmp << std::endl;
		//std::cerr << tmp.length << std::endl;
		ret = ret + tmp;
	}
	ret.isNegative = a.isNegative ^ b.isNegative;
	return ret;
}
ExtInt operator /(const ExtInt &a, const ExtInt &b) {
	assert(b != ExtInt(0));
	if (a == ExtInt(0)) return ExtInt(0);
	ExtInt ret, tmp, div = b;
	ret.high -> remove();
	ret.length = 0;
	tmp.high -> remove();
	tmp.length = 0;
	div.isNegative = false;
	ExtInt::DListNode *itA = a.high -> forward;
	for (; itA != a.low; itA = itA -> forward) {
		tmp.low -> append(itA -> data);
		tmp.length++;
		if (tmp >= div) {
			int left = 0, right = ExtInt::LIMIT - 1;
			while (left < right) {
				int middle = (left + right >> 1) + 1;
				if (tmp >= div * middle) {
					left = middle;
				} else {
					right = middle - 1;
				}
			}
			//std::cerr << tmp << " " << div * left << std::endl;
			ret.low -> append(left);
			ret.length++;
			tmp = tmp - div * left;
		} else {
			ret.low -> append(0);
			ret.length++;
		}
		if (tmp == ExtInt(0)) {
			tmp.high -> remove();
			tmp.length = 0;
		}
	}
	while (ret.length > 1 && ret.high -> forward -> data == 0) {
		ret.high -> remove();
		ret.length--;
	}
	ret.isNegative = a.isNegative ^ b.isNegative;
	if (ret.isNegative && tmp.low -> next != tmp.high) {
		ret = ret - 1;
	}
	return ret;
}
ExtInt operator %(const ExtInt &a, const ExtInt &b) {
	return a - a / b * b;
}

ExtInt & ExtInt::operator +=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}
ExtInt & ExtInt::operator -=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}
ExtInt & ExtInt::operator *=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}
ExtInt & ExtInt::operator /=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}
ExtInt & ExtInt::operator %=(const ExtInt &rhs) {
	*this = *this + rhs;
	return *this;
}

#endif
#endif

#endif
<|endoftext|>


<commit_before>
#include "app/gibbs/gibbs_sampling.h"
#include "app/gibbs/single_node_sampler.h"
#include "io/pb_parser.h"
#include "common.h"
#include <unistd.h>
#include <fstream>
#include "timer.h"

/*!
 * \brief In this function, the factor graph is located to each NUMA node.
 *
 * TODO: in the near future, this allocation should be abstracted
 * into a higher-level class to avoid writing similar things
 * for Gibbs, NN, SGD etc. However, this is the task of next pass
 * of refactoring.
 */
void dd::GibbsSampling::prepare(){

  n_numa_nodes = numa_max_node();
  //n_numa_nodes = 0;
  n_thread_per_numa = (sysconf(_SC_NPROCESSORS_CONF))/(n_numa_nodes+1);
  //n_thread_per_numa /= 2;
  //if(n_thread_per_numa == 0){
  //  n_thread_per_numa = 1;
  //}
  //n_thread_per_numa = 1;

  this->factorgraphs.push_back(*p_fg);
  for(int i=1;i<=n_numa_nodes;i++){

    numa_run_on_node(i);
    numa_set_localalloc();

    std::cout << "CREATE FG ON NODE ..." <<  i << std::endl;
    dd::FactorGraph fg(p_fg->n_var, p_fg->n_factor, p_fg->n_weight, p_fg->n_edge);

    fg.copy_from(p_fg);
    //fg.load(*p_cmd_parser);

    this->factorgraphs.push_back(fg);
  }

}

void dd::GibbsSampling::inference(const int & n_epoch){

  Timer t_total;

  Timer t;
  int nvar = this->factorgraphs[0].n_var;
  int nnode = n_numa_nodes + 1;

  std::vector<SingleNodeSampler> single_node_samplers;
  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers.push_back(SingleNodeSampler(&this->factorgraphs[i],
      n_thread_per_numa, i));
  }

  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers[i].clear_variabletally();
  }

  for(int i_epoch=0;i_epoch<n_epoch;i_epoch++){

    std::cout << std::setprecision(2) << "INFERENCE EPOCH " << i_epoch * nnode <<  "~"
      << ((i_epoch+1) * nnode) << "...." << std::flush;

    t.restart();

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].sample();
    }

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].wait();
    }
    double elapsed = t.elapsed();
    std::cout << ""  << elapsed << " sec." ;
    std::cout << ","  << (nvar*nnode)/elapsed << " vars/sec" << std::endl;
  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL INFERENCE TIME: " << elapsed << " sec." << std::endl;

}

void dd::GibbsSampling::learn(const int & n_epoch, const int & n_sample_per_epoch,
                              const double & stepsize, const double & decay){

  Timer t_total;

  double current_stepsize = stepsize;

  Timer t;
  int nvar = this->factorgraphs[0].n_var;
  int nnode = n_numa_nodes + 1;
  int nweight = this->factorgraphs[0].n_weight;

  std::vector<SingleNodeSampler> single_node_samplers;
  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers.push_back(SingleNodeSampler(&this->factorgraphs[i], n_thread_per_numa, i));
  }

  double * ori_weights = new double[nweight];
  memcpy(ori_weights, this->factorgraphs[0].infrs->weight_values, sizeof(double)*nweight);

  for(int i_epoch=0;i_epoch<n_epoch;i_epoch++){

    std::cout << std::setprecision(2) << "LEARNING EPOCH " << i_epoch * nnode <<  "~"
      << ((i_epoch+1) * nnode) << "...." << std::flush;

    t.restart();

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].p_fg->stepsize = current_stepsize;
    }

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].sample_sgd();
    }

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].wait_sgd();
    }

    FactorGraph & cfg = this->factorgraphs[0];
    for(int i=1;i<=n_numa_nodes;i++){
      FactorGraph & cfg_other = this->factorgraphs[i];
      for(int j=0;j<nweight;j++){
        cfg.infrs->weight_values[j] += cfg_other.infrs->weight_values[j];
      }
    }

    for(int j=0;j<nweight;j++){
      cfg.infrs->weight_values[j] /= nnode;
      if(cfg.infrs->weights_isfixed[j] == false){
        cfg.infrs->weight_values[j] *= (1.0/(1.0+0.01*current_stepsize));
      }
    }

    for(int i=1;i<=n_numa_nodes;i++){
      FactorGraph &cfg_other = this->factorgraphs[i];
      for(int j=0;j<nweight;j++){
        if(cfg.infrs->weights_isfixed[j] == false){
          cfg_other.infrs->weight_values[j] = cfg.infrs->weight_values[j];
        }
      }
    }

    double lmax = -1000000;
    double l2=0.0;
    for(int i=0;i<nweight;i++){
      double diff = fabs(ori_weights[i] - cfg.infrs->weight_values[i]);
      ori_weights[i] = cfg.infrs->weight_values[i];
      l2 += diff*diff;
      if(lmax < diff){
        lmax = diff;
      }
    }
    lmax = lmax/current_stepsize;

    double elapsed = t.elapsed();
    std::cout << "" << elapsed << " sec.";
    std::cout << ","  << (nvar*nnode)/elapsed << " vars/sec." << ",stepsize=" << current_stepsize << ",lmax=" << lmax << ",l2=" << sqrt(l2)/current_stepsize << std::endl;
    //std::cout << "     " << this->compact_factors[0].fg_mutable->weights[0] << std::endl;

    current_stepsize = current_stepsize * decay;

  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL LEARNING TIME: " << elapsed << " sec." << std::endl;

}

void dd::GibbsSampling::dump_weights(){

  std::cout << "LEARNING SNIPPETS (QUERY WEIGHTS):" << std::endl;
  FactorGraph const & cfg = this->factorgraphs[0];
  int ct = 0;
  for(size_t i=0;i<cfg.infrs->nweights;i++){
    ct ++;
    std::cout << "   " << i << " " << cfg.infrs->weight_values[i] << std::endl;
    if(ct % 10 == 0){
      break;
    }
  }
  std::cout << "   ..." << std::endl;

  std::string filename_protocol = p_cmd_parser->output_folder->getValue()
    + "/inference_result.out.weights";
  std::string filename_text = p_cmd_parser->output_folder->getValue()
    + "/inference_result.out.weights.text";

  std::cout << "DUMPING... PROTOCOL: " << filename_protocol << std::endl;
  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;

  std::ofstream fout_text(filename_text.c_str());
  std::ofstream mFs(filename_protocol.c_str(),std::ios::out | std::ios::binary);
  google::protobuf::io::OstreamOutputStream *_OstreamOutputStream =
    new google::protobuf::io::OstreamOutputStream(&mFs);
  google::protobuf::io::CodedOutputStream *_CodedOutputStream =
    new google::protobuf::io::CodedOutputStream(_OstreamOutputStream);
  deepdive::WeightInferenceResult msg;
  for(size_t i=0;i<cfg.infrs->nweights;i++){
    fout_text << i << " " << cfg.infrs->weight_values[i] << std::endl;
    msg.set_id(i);
    msg.set_value(cfg.infrs->weight_values[i]);
    _CodedOutputStream->WriteVarint32(msg.ByteSize());
    if ( !msg.SerializeToCodedStream(_CodedOutputStream) ){
      std::cout << "SerializeToCodedStream error " << std::endl;
      assert(false);
    }
  }
  delete _CodedOutputStream;
  delete _OstreamOutputStream;
  mFs.close();
  fout_text.close();

}

void dd::GibbsSampling::dump(){

  double * agg_means = new double[factorgraphs[0].n_var];
  double * agg_nsamples = new double[factorgraphs[0].n_var];
  int * multinomial_tallies = new int[factorgraphs[0].infrs->ntallies];

  for(long i=0;i<factorgraphs[0].n_var;i++){
    agg_means[i] = 0;
    agg_nsamples[i] = 0;
  }

  for(long i=0;i<factorgraphs[0].infrs->ntallies;i++){
    multinomial_tallies[i] = 0;
  }

  for(int i=0;i<=n_numa_nodes;i++){
    const FactorGraph & cfg = factorgraphs[i];
    for(long i=0;i<factorgraphs[0].n_var;i++){
      const Variable & variable = factorgraphs[0].variables[i];
      agg_means[variable.id] += cfg.infrs->agg_means[variable.id];
      agg_nsamples[variable.id] += cfg.infrs->agg_nsamples[variable.id];
    }
    for(long i=0;i<factorgraphs[0].infrs->ntallies;i++){
      multinomial_tallies[i] += cfg.infrs->multinomial_tallies[i];
    }
  }

  std::cout << "INFERENCE SNIPPETS (QUERY VARIABLES):" << std::endl;
  int ct = 0;
  for(long i=0;i<factorgraphs[0].n_var;i++){
    const Variable & variable = factorgraphs[0].variables[i];
    if(variable.is_evid == false){
      ct ++;
      std::cout << "   " << variable.id << " EXP="
                << agg_means[variable.id]/agg_nsamples[variable.id] << "  NSAMPLE="
                << agg_nsamples[variable.id] << std::endl;

      if(variable.domain_type != DTYPE_BOOLEAN){
        if(variable.domain_type == DTYPE_MULTINOMIAL){
          for(int j=0;j<=variable.upper_bound;j++){
            std::cout << "        @ " << j << " -> " << 1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id] << std::endl;
          }
        }else{
          std::cout << "ERROR: Only support boolean variables for now!" << std::endl;
          assert(false);
        }
      }

      if(ct % 10 == 0){
        break;
      }
    }
  }
  std::cout << "   ..." << std::endl;

  std::string filename_protocol = p_cmd_parser->output_folder->getValue() +
    "/inference_result.out";
  std::string filename_text = p_cmd_parser->output_folder->getValue() +
    "/inference_result.out.text";
  std::cout << "DUMPING... PROTOCOL: " << filename_protocol << std::endl;
  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;
  std::ofstream fout_text(filename_text.c_str());
  std::ofstream mFs(filename_protocol.c_str(),std::ios::out | std::ios::binary);
  google::protobuf::io::OstreamOutputStream *_OstreamOutputStream =
    new google::protobuf::io::OstreamOutputStream(&mFs);
  google::protobuf::io::CodedOutputStream *_CodedOutputStream =
    new google::protobuf::io::CodedOutputStream(_OstreamOutputStream);
  deepdive::VariableInferenceResult msg;
  for(long i=0;i<factorgraphs[0].n_var;i++){
    const Variable & variable = factorgraphs[0].variables[i];
    if(variable.is_evid == true){
      continue;
    }

    msg.set_id(variable.id);
    msg.set_category(1.0);
    msg.set_expectation(agg_means[variable.id]/agg_nsamples[variable.id]);

    if(variable.domain_type != DTYPE_BOOLEAN){
      if(variable.domain_type == DTYPE_MULTINOMIAL){
        for(int j=0;j<=variable.upper_bound;j++){
          msg.set_category(j);
          msg.set_expectation(1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id]);

          fout_text << variable.id << " " << j << " " << (1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id]) << std::endl;

          _CodedOutputStream->WriteVarint32(msg.ByteSize());
          if ( !msg.SerializeToCodedStream(_CodedOutputStream) ){
            std::cout << "SerializeToCodedStream error " << std::endl;
            assert(false);
          }
        }
      }else{
        std::cout << "ERROR: Only support boolean variables for now!" << std::endl;
        assert(false);
      }
    }else{
      fout_text << variable.id << " " << 1 << " " << (agg_means[variable.id]/agg_nsamples[variable.id]) << std::endl;

      _CodedOutputStream->WriteVarint32(msg.ByteSize());
      if ( !msg.SerializeToCodedStream(_CodedOutputStream) ){
        std::cout << "SerializeToCodedStream error " << std::endl;
        assert(false);
      }
    }
  }
  delete _CodedOutputStream;
  delete _OstreamOutputStream;
  mFs.close();
  fout_text.close();

  std::cout << "INFERENCE CALIBRATION (QUERY BINS):" << std::endl;
  std::vector<int> abc;
  for(int i=0;i<=10;i++){
    abc.push_back(0);
  }
  int bad = 0;
  for(long i=0;i<factorgraphs[0].n_var;i++){
    const Variable & variable = factorgraphs[0].variables[i];
    if(variable.is_evid == true){
      continue;
    }
    int bin = (int)(agg_means[variable.id]/agg_nsamples[variable.id]*10);
    if(bin >= 0 && bin <=10){
      abc[bin] ++;
    }else{
      //std::cout << variable.id << "   " << variable.agg_mean << "   " << variable.n_sample << std::endl;
      bad ++;
    }
  }
  abc[9] += abc[10];
  for(int i=0;i<10;i++){
    std::cout << "PROB BIN 0." << i << "~0." << (i+1) << "  -->  # " << abc[i] << std::endl;
  }

}

<commit_msg>single numa, multiple thread<commit_after>
#include "app/gibbs/gibbs_sampling.h"
#include "app/gibbs/single_node_sampler.h"
#include "io/pb_parser.h"
#include "common.h"
#include <unistd.h>
#include <fstream>
#include "timer.h"

/*!
 * \brief In this function, the factor graph is located to each NUMA node.
 *
 * TODO: in the near future, this allocation should be abstracted
 * into a higher-level class to avoid writing similar things
 * for Gibbs, NN, SGD etc. However, this is the task of next pass
 * of refactoring.
 */
void dd::GibbsSampling::prepare(){

  //n_numa_nodes = numa_max_node();
  n_numa_nodes = 0;
  n_thread_per_numa = (sysconf(_SC_NPROCESSORS_CONF))/(n_numa_nodes+1);
  //n_thread_per_numa /= 2;
  //if(n_thread_per_numa == 0){
  //  n_thread_per_numa = 1;
  //}
  //n_thread_per_numa = 1;

  this->factorgraphs.push_back(*p_fg);
  for(int i=1;i<=n_numa_nodes;i++){

    numa_run_on_node(i);
    numa_set_localalloc();

    std::cout << "CREATE FG ON NODE ..." <<  i << std::endl;
    dd::FactorGraph fg(p_fg->n_var, p_fg->n_factor, p_fg->n_weight, p_fg->n_edge);

    fg.copy_from(p_fg);
    //fg.load(*p_cmd_parser);

    this->factorgraphs.push_back(fg);
  }

}

void dd::GibbsSampling::inference(const int & n_epoch){

  Timer t_total;

  Timer t;
  int nvar = this->factorgraphs[0].n_var;
  int nnode = n_numa_nodes + 1;

  std::vector<SingleNodeSampler> single_node_samplers;
  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers.push_back(SingleNodeSampler(&this->factorgraphs[i],
      n_thread_per_numa, i));
  }

  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers[i].clear_variabletally();
  }

  for(int i_epoch=0;i_epoch<n_epoch;i_epoch++){

    std::cout << std::setprecision(2) << "INFERENCE EPOCH " << i_epoch * nnode <<  "~"
      << ((i_epoch+1) * nnode) << "...." << std::flush;

    t.restart();

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].sample();
    }

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].wait();
    }
    double elapsed = t.elapsed();
    std::cout << ""  << elapsed << " sec." ;
    std::cout << ","  << (nvar*nnode)/elapsed << " vars/sec" << std::endl;
  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL INFERENCE TIME: " << elapsed << " sec." << std::endl;

}

void dd::GibbsSampling::learn(const int & n_epoch, const int & n_sample_per_epoch,
                              const double & stepsize, const double & decay){

  Timer t_total;

  double current_stepsize = stepsize;

  Timer t;
  int nvar = this->factorgraphs[0].n_var;
  int nnode = n_numa_nodes + 1;
  int nweight = this->factorgraphs[0].n_weight;

  std::vector<SingleNodeSampler> single_node_samplers;
  for(int i=0;i<=n_numa_nodes;i++){
    single_node_samplers.push_back(SingleNodeSampler(&this->factorgraphs[i], n_thread_per_numa, i));
  }

  double * ori_weights = new double[nweight];
  memcpy(ori_weights, this->factorgraphs[0].infrs->weight_values, sizeof(double)*nweight);

  for(int i_epoch=0;i_epoch<n_epoch;i_epoch++){

    std::cout << std::setprecision(2) << "LEARNING EPOCH " << i_epoch * nnode <<  "~"
      << ((i_epoch+1) * nnode) << "...." << std::flush;

    t.restart();

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].p_fg->stepsize = current_stepsize;
    }

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].sample_sgd();
    }

    for(int i=0;i<nnode;i++){
      single_node_samplers[i].wait_sgd();
    }

    FactorGraph & cfg = this->factorgraphs[0];
    for(int i=1;i<=n_numa_nodes;i++){
      FactorGraph & cfg_other = this->factorgraphs[i];
      for(int j=0;j<nweight;j++){
        cfg.infrs->weight_values[j] += cfg_other.infrs->weight_values[j];
      }
    }

    for(int j=0;j<nweight;j++){
      cfg.infrs->weight_values[j] /= nnode;
      if(cfg.infrs->weights_isfixed[j] == false){
        cfg.infrs->weight_values[j] *= (1.0/(1.0+0.01*current_stepsize));
      }
    }

    for(int i=1;i<=n_numa_nodes;i++){
      FactorGraph &cfg_other = this->factorgraphs[i];
      for(int j=0;j<nweight;j++){
        if(cfg.infrs->weights_isfixed[j] == false){
          cfg_other.infrs->weight_values[j] = cfg.infrs->weight_values[j];
        }
      }
    }

    double lmax = -1000000;
    double l2=0.0;
    for(int i=0;i<nweight;i++){
      double diff = fabs(ori_weights[i] - cfg.infrs->weight_values[i]);
      ori_weights[i] = cfg.infrs->weight_values[i];
      l2 += diff*diff;
      if(lmax < diff){
        lmax = diff;
      }
    }
    lmax = lmax/current_stepsize;

    double elapsed = t.elapsed();
    std::cout << "" << elapsed << " sec.";
    std::cout << ","  << (nvar*nnode)/elapsed << " vars/sec." << ",stepsize=" << current_stepsize << ",lmax=" << lmax << ",l2=" << sqrt(l2)/current_stepsize << std::endl;
    //std::cout << "     " << this->compact_factors[0].fg_mutable->weights[0] << std::endl;

    current_stepsize = current_stepsize * decay;

  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL LEARNING TIME: " << elapsed << " sec." << std::endl;

}

void dd::GibbsSampling::dump_weights(){

  std::cout << "LEARNING SNIPPETS (QUERY WEIGHTS):" << std::endl;
  FactorGraph const & cfg = this->factorgraphs[0];
  int ct = 0;
  for(size_t i=0;i<cfg.infrs->nweights;i++){
    ct ++;
    std::cout << "   " << i << " " << cfg.infrs->weight_values[i] << std::endl;
    if(ct % 10 == 0){
      break;
    }
  }
  std::cout << "   ..." << std::endl;

  std::string filename_protocol = p_cmd_parser->output_folder->getValue()
    + "/inference_result.out.weights";
  std::string filename_text = p_cmd_parser->output_folder->getValue()
    + "/inference_result.out.weights.text";

  std::cout << "DUMPING... PROTOCOL: " << filename_protocol << std::endl;
  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;

  std::ofstream fout_text(filename_text.c_str());
  std::ofstream mFs(filename_protocol.c_str(),std::ios::out | std::ios::binary);
  google::protobuf::io::OstreamOutputStream *_OstreamOutputStream =
    new google::protobuf::io::OstreamOutputStream(&mFs);
  google::protobuf::io::CodedOutputStream *_CodedOutputStream =
    new google::protobuf::io::CodedOutputStream(_OstreamOutputStream);
  deepdive::WeightInferenceResult msg;
  for(size_t i=0;i<cfg.infrs->nweights;i++){
    fout_text << i << " " << cfg.infrs->weight_values[i] << std::endl;
    msg.set_id(i);
    msg.set_value(cfg.infrs->weight_values[i]);
    _CodedOutputStream->WriteVarint32(msg.ByteSize());
    if ( !msg.SerializeToCodedStream(_CodedOutputStream) ){
      std::cout << "SerializeToCodedStream error " << std::endl;
      assert(false);
    }
  }
  delete _CodedOutputStream;
  delete _OstreamOutputStream;
  mFs.close();
  fout_text.close();

}

void dd::GibbsSampling::dump(){

  double * agg_means = new double[factorgraphs[0].n_var];
  double * agg_nsamples = new double[factorgraphs[0].n_var];
  int * multinomial_tallies = new int[factorgraphs[0].infrs->ntallies];

  for(long i=0;i<factorgraphs[0].n_var;i++){
    agg_means[i] = 0;
    agg_nsamples[i] = 0;
  }

  for(long i=0;i<factorgraphs[0].infrs->ntallies;i++){
    multinomial_tallies[i] = 0;
  }

  for(int i=0;i<=n_numa_nodes;i++){
    const FactorGraph & cfg = factorgraphs[i];
    for(long i=0;i<factorgraphs[0].n_var;i++){
      const Variable & variable = factorgraphs[0].variables[i];
      agg_means[variable.id] += cfg.infrs->agg_means[variable.id];
      agg_nsamples[variable.id] += cfg.infrs->agg_nsamples[variable.id];
    }
    for(long i=0;i<factorgraphs[0].infrs->ntallies;i++){
      multinomial_tallies[i] += cfg.infrs->multinomial_tallies[i];
    }
  }

  std::cout << "INFERENCE SNIPPETS (QUERY VARIABLES):" << std::endl;
  int ct = 0;
  for(long i=0;i<factorgraphs[0].n_var;i++){
    const Variable & variable = factorgraphs[0].variables[i];
    if(variable.is_evid == false){
      ct ++;
      std::cout << "   " << variable.id << " EXP="
                << agg_means[variable.id]/agg_nsamples[variable.id] << "  NSAMPLE="
                << agg_nsamples[variable.id] << std::endl;

      if(variable.domain_type != DTYPE_BOOLEAN){
        if(variable.domain_type == DTYPE_MULTINOMIAL){
          for(int j=0;j<=variable.upper_bound;j++){
            std::cout << "        @ " << j << " -> " << 1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id] << std::endl;
          }
        }else{
          std::cout << "ERROR: Only support boolean variables for now!" << std::endl;
          assert(false);
        }
      }

      if(ct % 10 == 0){
        break;
      }
    }
  }
  std::cout << "   ..." << std::endl;

  std::string filename_protocol = p_cmd_parser->output_folder->getValue() +
    "/inference_result.out";
  std::string filename_text = p_cmd_parser->output_folder->getValue() +
    "/inference_result.out.text";
  std::cout << "DUMPING... PROTOCOL: " << filename_protocol << std::endl;
  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;
  std::ofstream fout_text(filename_text.c_str());
  std::ofstream mFs(filename_protocol.c_str(),std::ios::out | std::ios::binary);
  google::protobuf::io::OstreamOutputStream *_OstreamOutputStream =
    new google::protobuf::io::OstreamOutputStream(&mFs);
  google::protobuf::io::CodedOutputStream *_CodedOutputStream =
    new google::protobuf::io::CodedOutputStream(_OstreamOutputStream);
  deepdive::VariableInferenceResult msg;
  for(long i=0;i<factorgraphs[0].n_var;i++){
    const Variable & variable = factorgraphs[0].variables[i];
    if(variable.is_evid == true){
      continue;
    }

    msg.set_id(variable.id);
    msg.set_category(1.0);
    msg.set_expectation(agg_means[variable.id]/agg_nsamples[variable.id]);

    if(variable.domain_type != DTYPE_BOOLEAN){
      if(variable.domain_type == DTYPE_MULTINOMIAL){
        for(int j=0;j<=variable.upper_bound;j++){
          msg.set_category(j);
          msg.set_expectation(1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id]);

          fout_text << variable.id << " " << j << " " << (1.0*multinomial_tallies[variable.n_start_i_tally + j]/agg_nsamples[variable.id]) << std::endl;

          _CodedOutputStream->WriteVarint32(msg.ByteSize());
          if ( !msg.SerializeToCodedStream(_CodedOutputStream) ){
            std::cout << "SerializeToCodedStream error " << std::endl;
            assert(false);
          }
        }
      }else{
        std::cout << "ERROR: Only support boolean variables for now!" << std::endl;
        assert(false);
      }
    }else{
      fout_text << variable.id << " " << 1 << " " << (agg_means[variable.id]/agg_nsamples[variable.id]) << std::endl;

      _CodedOutputStream->WriteVarint32(msg.ByteSize());
      if ( !msg.SerializeToCodedStream(_CodedOutputStream) ){
        std::cout << "SerializeToCodedStream error " << std::endl;
        assert(false);
      }
    }
  }
  delete _CodedOutputStream;
  delete _OstreamOutputStream;
  mFs.close();
  fout_text.close();

  std::cout << "INFERENCE CALIBRATION (QUERY BINS):" << std::endl;
  std::vector<int> abc;
  for(int i=0;i<=10;i++){
    abc.push_back(0);
  }
  int bad = 0;
  for(long i=0;i<factorgraphs[0].n_var;i++){
    const Variable & variable = factorgraphs[0].variables[i];
    if(variable.is_evid == true){
      continue;
    }
    int bin = (int)(agg_means[variable.id]/agg_nsamples[variable.id]*10);
    if(bin >= 0 && bin <=10){
      abc[bin] ++;
    }else{
      //std::cout << variable.id << "   " << variable.agg_mean << "   " << variable.n_sample << std::endl;
      bad ++;
    }
  }
  abc[9] += abc[10];
  for(int i=0;i<10;i++){
    std::cout << "PROB BIN 0." << i << "~0." << (i+1) << "  -->  # " << abc[i] << std::endl;
  }

}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: templwin.hxx,v $
 *
 *  $Revision: 1.28 $
 *
 *  last change: $Author: hr $ $Date: 2004-08-02 14:36:36 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVTOOLS_TEMPLWIN_HXX
#define _SVTOOLS_TEMPLWIN_HXX

#ifndef _TOOLS_RESARY_HXX
#include <tools/resary.hxx>
#endif
#ifndef _SV_SPLITWIN_HXX
#include <vcl/splitwin.hxx>
#endif
#ifndef _SV_TOOLBOX_HXX
#include <vcl/toolbox.hxx>
#endif
#ifndef _SV_WINDOW_HXX
#include <vcl/window.hxx>
#endif

#ifndef _HEADBAR_HXX
#include "headbar.hxx"
#endif
#ifndef _SVT_FILEVIEW_HXX
#include "fileview.hxx"
#endif
#ifndef _ICNVW_HXX
#include "ivctrl.hxx"
#endif
#ifndef _SVTOOLS_SVMEDIT2_HXX
#include "svmedit2.hxx"
#endif

#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_
#include <com/sun/star/lang/Locale.hpp>
#endif

namespace com{ namespace sun { namespace star { namespace awt   { class XWindow; } } } };
namespace com{ namespace sun { namespace star { namespace frame { class XFrame; } } } };
namespace com{ namespace sun { namespace star { namespace io    { class XPersist; } } } };
namespace svtools
{
    class ODocumentInfoPreview;
}

// class SvtDummyHeaderBar_Impl ------------------------------------------

class SvtDummyHeaderBar_Impl : public Window
{
private:
    void                UpdateBackgroundColor();

public:
                        SvtDummyHeaderBar_Impl( Window* pParent );
                        ~SvtDummyHeaderBar_Impl();

    virtual void        DataChanged( const DataChangedEvent& rDCEvt );
};

// class SvtIconWindow_Impl ----------------------------------------------

class SvtIconWindow_Impl : public Window
{
private:
    SvtDummyHeaderBar_Impl  aDummyHeaderBar;    // spaceholder instead of HeaderBar
    SvtIconChoiceCtrl   aIconCtrl;

    String              aNewDocumentRootURL;
    String              aTemplateRootURL;
    String              aMyDocumentsRootURL;
    String              aSamplesFolderRootURL;

    long                nMaxTextLength;

    SvxIconChoiceCtrlEntry* GetEntry( const String& rURL ) const;

public:
    SvtIconWindow_Impl( Window* pParent );
    ~SvtIconWindow_Impl();

    virtual void        Resize();

    inline long         GetMaxTextLength() const { return nMaxTextLength; }
    inline void         SetClickHdl( const Link& rLink ) { aIconCtrl.SetClickHdl( rLink ); }
    inline String       GetTemplateRootURL() const { return aTemplateRootURL; }

    String              GetSelectedIconURL() const;
    String              GetSelectedIconText() const;
    String              GetCursorPosIconURL() const;
    String              GetIconText( const String& rURL ) const;
    void                InvalidateIconControl();
    void                SetCursorPos( ULONG nPos );
    ULONG               GetCursorPos() const;
    ULONG               GetSelectEntryPos() const;
    void                SetFocus();
    long                CalcHeight() const;
    sal_Bool            IsRootURL( const String& rURL ) const;
    ULONG               GetRootPos( const String& rURL ) const;
    void                UpdateIcons( sal_Bool _bHiContrast );

    inline sal_Bool         ProcessKeyEvent( const KeyEvent& rKEvt );
    inline const String&    GetSamplesFolderURL() const;

    void                SelectFolder(sal_Int32 nFolderPos);
};

inline sal_Bool SvtIconWindow_Impl::ProcessKeyEvent( const KeyEvent& rKEvt )
{
    return ( rKEvt.GetKeyCode().IsMod2() ? aIconCtrl.DoKeyInput( rKEvt ) : sal_False );
}

inline const String& SvtIconWindow_Impl::GetSamplesFolderURL() const
{
    return aSamplesFolderRootURL;
}

// class SvtFileViewWindow_Impl ------------------------------------------

class SvtTemplateWindow;

class SvtFileViewWindow_Impl : public Window
{
private:
    SvtTemplateWindow&  rParent;
    SvtFileView         aFileView;
    Link                aNewFolderLink;
    String              aCurrentRootURL;
    String              aFolderURL;
    String              aSamplesFolderURL;

    sal_Bool            bIsTemplateFolder;

    ::com::sun::star::uno::Sequence< ::rtl::OUString >
                        GetNewDocContents() const;

public:
    SvtFileViewWindow_Impl( SvtTemplateWindow* pParent, const String& rSamplesFolderURL );
    ~SvtFileViewWindow_Impl();

    virtual void        Resize();

    inline void         SetSelectHdl( const Link& rLink ) { aFileView.SetSelectHdl( rLink ); }
    inline void         SetDoubleClickHdl( const Link& rLink ) { aFileView.SetDoubleClickHdl( rLink ); }
    inline void         SetNewFolderHdl( const Link& rLink ) { aNewFolderLink = rLink; }
    inline void         ResetCursor() { aFileView.ResetCursor(); }
    inline sal_Bool     IsTemplateFolder() const { return bIsTemplateFolder; }
    inline String       GetFolderURL() const { return aFolderURL; }
    inline String       GetRootURL() const { return aCurrentRootURL; }
    inline void         OpenRoot( const String& rRootURL )
                            { aCurrentRootURL = rRootURL; OpenFolder( rRootURL ); }

    String              GetSelectedFile() const;
    void                OpenFolder( const String& rURL );
    sal_Bool            HasPreviousLevel( String& rURL ) const;
    String              GetFolderTitle() const;
    void                SetFocus();
};

// class SvtFrameWindow_Impl ---------------------------------------------

class SvtDocInfoTable_Impl : public ResStringArray
{
private:
    String          aEmptyString;

public:
    SvtDocInfoTable_Impl();

    const String&   GetString( long nId ) const;
};

class SvtExtendedMultiLineEdit_Impl : public ExtMultiLineEdit
{
public:
    SvtExtendedMultiLineEdit_Impl( Window* pParent,WinBits _nBits );
    inline ~SvtExtendedMultiLineEdit_Impl() {}

    inline void         Clear() { SetText( String() ); }
    void                InsertEntry( const String& rTitle, const String& rValue );
};

class SvtFrameWindow_Impl : public Window
{
private:
    ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame >
                                xFrame;
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XPersist >
                                xDocInfo;
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >
                                xWindow;

    ::svtools::ODocumentInfoPreview*
                                    pEditWin;
    Window*                         pTextWin;
    Window*                         pEmptyWin;
    ::com::sun::star::lang::Locale  aLocale;
    SvtDocInfoTable_Impl            aInfoTable;
    String                          aCurrentURL;
    ::rtl::OUString                 m_aOpenURL;
    sal_Bool                        bDocInfo;

    void                    ShowDocInfo( const String& rURL );
    void                    ViewEditWin();
    void                    ViewTextWin();
    void                    ViewEmptyWin();
    void                    ViewNonEmptyWin();  // views depending on bDocInfo

public:
    SvtFrameWindow_Impl( Window* pParent );
    ~SvtFrameWindow_Impl();

    virtual void            Resize();

    void                    OpenFile( const String& rURL, sal_Bool bPreview, sal_Bool bIsTemplate, sal_Bool bAsTemplate );
    void                    ToggleView( sal_Bool bDocInfo );
};

// class SvtTemplateWindow -----------------------------------------------

class HistoryList_Impl;

class SvtTemplateWindow : public Window
{
private:
    ToolBox                     aFileViewTB;
    ToolBox                     aFrameWinTB;
    SplitWindow                 aSplitWin;

    SvtIconWindow_Impl*         pIconWin;
    SvtFileViewWindow_Impl*     pFileWin;
    SvtFrameWindow_Impl*        pFrameWin;
    HistoryList_Impl*           pHistoryList;

    Link                        aSelectHdl;
    Link                        aDoubleClickHdl;
    Link                        aNewFolderHdl;
    Link                        aSendFocusHdl;

    Timer                       aSelectTimer;

    String                      aFolderTitle;

    virtual void        Resize();

    DECL_LINK(          IconClickHdl_Impl, SvtIconChoiceCtrl* );
    DECL_LINK(          FileSelectHdl_Impl, SvtFileView* );
    DECL_LINK(          FileDblClickHdl_Impl, SvtFileView* );
    DECL_LINK(          NewFolderHdl_Impl, SvtFileView* );
    DECL_LINK(          TimeoutHdl_Impl, Timer* );
    DECL_LINK(          ClickHdl_Impl, ToolBox* );
    DECL_LINK(          ResizeHdl_Impl, SplitWindow* );     // used for split and initial setting of toolbar pos

    void                PrintFile( const String& rURL );
    void                AppendHistoryURL( const String& rURL, ULONG nGroup );
    void                OpenHistory();
    void                DoAction( USHORT nAction );
    void                InitToolBoxes();
    void                InitToolBoxImages();
    void                UpdateIcons();

protected:
    virtual long        PreNotify( NotifyEvent& rNEvt );
    virtual void        DataChanged( const DataChangedEvent& rDCEvt );

public:
    SvtTemplateWindow( Window* pParent );
    ~SvtTemplateWindow();

    inline void         SetSelectHdl( const Link& rLink ) { aSelectHdl = rLink; }
    inline void         SetDoubleClickHdl( const Link& rLink ) { aDoubleClickHdl = rLink; }
    inline void         SetNewFolderHdl( const Link& rLink ) { aNewFolderHdl = rLink; }
    inline void         SetSendFocusHdl( const Link& rLink ) { aSendFocusHdl = rLink; }
    inline sal_Bool     IsTemplateFolderOpen() const { return pFileWin->IsTemplateFolder(); }
    inline sal_Bool     HasIconWinFocus() const { return pIconWin->HasChildPathFocus(); }

    void                ReadViewSettings( );
    void                WriteViewSettings( );
    sal_Bool            IsFileSelected() const;
    String              GetSelectedFile() const;
    void                OpenFile( sal_Bool bNotAsTemplate );
    String              GetFolderTitle() const;
    void                SetFocus( sal_Bool bIconWin );
    void                OpenTemplateRoot();
    void                SetPrevLevelButtonState( const String& rURL );  // sets state (enable/disable) for previous level button
    void                ClearHistory();
    long                CalcHeight() const;

    void                SelectFolder(sal_Int32 nFolderPosition);
};

#endif // _SVTOOLS_TEMPLWIN_HXX

<commit_msg>INTEGRATION: CWS os43 (1.28.136); FILE MERGED 2004/11/15 14:08:35 pb 1.28.136.1: fix: #i37154# enable DirectoryUp of MyDocuments<commit_after>/*************************************************************************
 *
 *  $RCSfile: templwin.hxx,v $
 *
 *  $Revision: 1.29 $
 *
 *  last change: $Author: hr $ $Date: 2004-11-26 23:01:46 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVTOOLS_TEMPLWIN_HXX
#define _SVTOOLS_TEMPLWIN_HXX

#ifndef _TOOLS_RESARY_HXX
#include <tools/resary.hxx>
#endif
#ifndef _SV_SPLITWIN_HXX
#include <vcl/splitwin.hxx>
#endif
#ifndef _SV_TOOLBOX_HXX
#include <vcl/toolbox.hxx>
#endif
#ifndef _SV_WINDOW_HXX
#include <vcl/window.hxx>
#endif

#ifndef _HEADBAR_HXX
#include "headbar.hxx"
#endif
#ifndef _SVT_FILEVIEW_HXX
#include "fileview.hxx"
#endif
#ifndef _ICNVW_HXX
#include "ivctrl.hxx"
#endif
#ifndef _SVTOOLS_SVMEDIT2_HXX
#include "svmedit2.hxx"
#endif

#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_
#include <com/sun/star/lang/Locale.hpp>
#endif

namespace com{ namespace sun { namespace star { namespace awt   { class XWindow; } } } };
namespace com{ namespace sun { namespace star { namespace frame { class XFrame; } } } };
namespace com{ namespace sun { namespace star { namespace io    { class XPersist; } } } };
namespace svtools
{
    class ODocumentInfoPreview;
}

// class SvtDummyHeaderBar_Impl ------------------------------------------

class SvtDummyHeaderBar_Impl : public Window
{
private:
    void                UpdateBackgroundColor();

public:
                        SvtDummyHeaderBar_Impl( Window* pParent );
                        ~SvtDummyHeaderBar_Impl();

    virtual void        DataChanged( const DataChangedEvent& rDCEvt );
};

// class SvtIconWindow_Impl ----------------------------------------------

class SvtIconWindow_Impl : public Window
{
private:
    SvtDummyHeaderBar_Impl  aDummyHeaderBar;    // spaceholder instead of HeaderBar
    SvtIconChoiceCtrl   aIconCtrl;

    String              aNewDocumentRootURL;
    String              aTemplateRootURL;
    String              aMyDocumentsRootURL;
    String              aSamplesFolderRootURL;

    long                nMaxTextLength;

    SvxIconChoiceCtrlEntry* GetEntry( const String& rURL ) const;

public:
    SvtIconWindow_Impl( Window* pParent );
    ~SvtIconWindow_Impl();

    virtual void        Resize();

    inline long         GetMaxTextLength() const { return nMaxTextLength; }
    inline void         SetClickHdl( const Link& rLink ) { aIconCtrl.SetClickHdl( rLink ); }

    String              GetSelectedIconURL() const;
    String              GetSelectedIconText() const;
    String              GetCursorPosIconURL() const;
    String              GetIconText( const String& rURL ) const;
    void                InvalidateIconControl();
    void                SetCursorPos( ULONG nPos );
    ULONG               GetCursorPos() const;
    ULONG               GetSelectEntryPos() const;
    void                SetFocus();
    long                CalcHeight() const;
    sal_Bool            IsRootURL( const String& rURL ) const;
    ULONG               GetRootPos( const String& rURL ) const;
    void                UpdateIcons( sal_Bool _bHiContrast );

    inline sal_Bool         ProcessKeyEvent( const KeyEvent& rKEvt );

    inline const String&    GetTemplateRootURL() const      { return aTemplateRootURL; }
    inline const String&    GetMyDocumentsRootURL() const   { return aMyDocumentsRootURL; }
    inline const String&    GetSamplesFolderURL() const     { return aSamplesFolderRootURL; }

    void                SelectFolder(sal_Int32 nFolderPos);
};

inline sal_Bool SvtIconWindow_Impl::ProcessKeyEvent( const KeyEvent& rKEvt )
{
    return ( rKEvt.GetKeyCode().IsMod2() ? aIconCtrl.DoKeyInput( rKEvt ) : sal_False );
}

// class SvtFileViewWindow_Impl ------------------------------------------

class SvtTemplateWindow;

class SvtFileViewWindow_Impl : public Window
{
private:
    SvtTemplateWindow&  rParent;
    SvtFileView         aFileView;
    Link                aNewFolderLink;
    String              aCurrentRootURL;
    String              aFolderURL;
    String              aMyDocumentsURL;
    String              aSamplesFolderURL;

    sal_Bool            bIsTemplateFolder;

    ::com::sun::star::uno::Sequence< ::rtl::OUString >
                        GetNewDocContents() const;

public:
    SvtFileViewWindow_Impl( SvtTemplateWindow* pParent );
    ~SvtFileViewWindow_Impl();

    virtual void        Resize();

    inline void         SetSelectHdl( const Link& rLink ) { aFileView.SetSelectHdl( rLink ); }
    inline void         SetDoubleClickHdl( const Link& rLink ) { aFileView.SetDoubleClickHdl( rLink ); }
    inline void         SetNewFolderHdl( const Link& rLink ) { aNewFolderLink = rLink; }
    inline void         ResetCursor() { aFileView.ResetCursor(); }
    inline sal_Bool     IsTemplateFolder() const { return bIsTemplateFolder; }
    inline String       GetFolderURL() const { return aFolderURL; }
    inline String       GetRootURL() const { return aCurrentRootURL; }
    inline void         OpenRoot( const String& rRootURL )
                            { aCurrentRootURL = rRootURL; OpenFolder( rRootURL ); }
    inline void         SetMyDocumentsURL( const String& _rNewURL ) { aMyDocumentsURL = _rNewURL; }
    inline void         SetSamplesFolderURL( const String& _rNewURL ) { aSamplesFolderURL = _rNewURL; }

    String              GetSelectedFile() const;
    void                OpenFolder( const String& rURL );
    sal_Bool            HasPreviousLevel( String& rURL ) const;
    String              GetFolderTitle() const;
    void                SetFocus();
};

// class SvtFrameWindow_Impl ---------------------------------------------

class SvtDocInfoTable_Impl : public ResStringArray
{
private:
    String          aEmptyString;

public:
    SvtDocInfoTable_Impl();

    const String&   GetString( long nId ) const;
};

class SvtExtendedMultiLineEdit_Impl : public ExtMultiLineEdit
{
public:
    SvtExtendedMultiLineEdit_Impl( Window* pParent,WinBits _nBits );
    inline ~SvtExtendedMultiLineEdit_Impl() {}

    inline void         Clear() { SetText( String() ); }
    void                InsertEntry( const String& rTitle, const String& rValue );
};

class SvtFrameWindow_Impl : public Window
{
private:
    ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame >
                                xFrame;
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XPersist >
                                xDocInfo;
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >
                                xWindow;

    ::svtools::ODocumentInfoPreview*
                                    pEditWin;
    Window*                         pTextWin;
    Window*                         pEmptyWin;
    ::com::sun::star::lang::Locale  aLocale;
    SvtDocInfoTable_Impl            aInfoTable;
    String                          aCurrentURL;
    ::rtl::OUString                 m_aOpenURL;
    sal_Bool                        bDocInfo;

    void                    ShowDocInfo( const String& rURL );
    void                    ViewEditWin();
    void                    ViewTextWin();
    void                    ViewEmptyWin();
    void                    ViewNonEmptyWin();  // views depending on bDocInfo

public:
    SvtFrameWindow_Impl( Window* pParent );
    ~SvtFrameWindow_Impl();

    virtual void            Resize();

    void                    OpenFile( const String& rURL, sal_Bool bPreview, sal_Bool bIsTemplate, sal_Bool bAsTemplate );
    void                    ToggleView( sal_Bool bDocInfo );
};

// class SvtTemplateWindow -----------------------------------------------

class HistoryList_Impl;

class SvtTemplateWindow : public Window
{
private:
    ToolBox                     aFileViewTB;
    ToolBox                     aFrameWinTB;
    SplitWindow                 aSplitWin;

    SvtIconWindow_Impl*         pIconWin;
    SvtFileViewWindow_Impl*     pFileWin;
    SvtFrameWindow_Impl*        pFrameWin;
    HistoryList_Impl*           pHistoryList;

    Link                        aSelectHdl;
    Link                        aDoubleClickHdl;
    Link                        aNewFolderHdl;
    Link                        aSendFocusHdl;

    Timer                       aSelectTimer;

    String                      aFolderTitle;

    virtual void        Resize();

    DECL_LINK(          IconClickHdl_Impl, SvtIconChoiceCtrl* );
    DECL_LINK(          FileSelectHdl_Impl, SvtFileView* );
    DECL_LINK(          FileDblClickHdl_Impl, SvtFileView* );
    DECL_LINK(          NewFolderHdl_Impl, SvtFileView* );
    DECL_LINK(          TimeoutHdl_Impl, Timer* );
    DECL_LINK(          ClickHdl_Impl, ToolBox* );
    DECL_LINK(          ResizeHdl_Impl, SplitWindow* );     // used for split and initial setting of toolbar pos

    void                PrintFile( const String& rURL );
    void                AppendHistoryURL( const String& rURL, ULONG nGroup );
    void                OpenHistory();
    void                DoAction( USHORT nAction );
    void                InitToolBoxes();
    void                InitToolBoxImages();
    void                UpdateIcons();

protected:
    virtual long        PreNotify( NotifyEvent& rNEvt );
    virtual void        DataChanged( const DataChangedEvent& rDCEvt );

public:
    SvtTemplateWindow( Window* pParent );
    ~SvtTemplateWindow();

    inline void         SetSelectHdl( const Link& rLink ) { aSelectHdl = rLink; }
    inline void         SetDoubleClickHdl( const Link& rLink ) { aDoubleClickHdl = rLink; }
    inline void         SetNewFolderHdl( const Link& rLink ) { aNewFolderHdl = rLink; }
    inline void         SetSendFocusHdl( const Link& rLink ) { aSendFocusHdl = rLink; }
    inline sal_Bool     IsTemplateFolderOpen() const { return pFileWin->IsTemplateFolder(); }
    inline sal_Bool     HasIconWinFocus() const { return pIconWin->HasChildPathFocus(); }

    void                ReadViewSettings( );
    void                WriteViewSettings( );
    sal_Bool            IsFileSelected() const;
    String              GetSelectedFile() const;
    void                OpenFile( sal_Bool bNotAsTemplate );
    String              GetFolderTitle() const;
    void                SetFocus( sal_Bool bIconWin );
    void                OpenTemplateRoot();
    void                SetPrevLevelButtonState( const String& rURL );  // sets state (enable/disable) for previous level button
    void                ClearHistory();
    long                CalcHeight() const;

    void                SelectFolder(sal_Int32 nFolderPosition);
};

#endif // _SVTOOLS_TEMPLWIN_HXX

<|endoftext|>


<commit_before>#include "viewport.h"

#include <cassert>
#include <iostream>
#include <cmath>

#include <QtGui/QMouseEvent>

#include <ImathMatrix.h>

#include <GL/glu.h>

namespace {
std::vector<Viewport*> s_instances;
}

Viewport::Viewport(QWidget* parent)
    : QGLWidget(parent, (s_instances.size() > 0 ? s_instances[0] : NULL)),
      m_sceneDistance(10), m_sceneRotationX(30), m_sceneRotationY(30), m_origin(0, 0, 0),
      m_mouseX(0), m_mouseY(0) {
	s_instances.push_back(this);

	setMouseTracking(true);
}

Viewport::~Viewport() {
	int index = -1;
	for(unsigned a = 0; a < s_instances.size(); a++)
		if(s_instances[a] == this)
			index = a;
	assert(index >= 0);
	s_instances.erase(s_instances.begin() + index);
}

void Viewport::initializeGL() {
	glClearColor(0, 0, 0, 0);
	resizeGL(width(), height());

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	float white[3] = {1, 1, 1};
	float position[4] = {1, 1, 1, 0};

	glEnable(GL_LIGHT0);
	glLightfv(GL_LIGHT0, GL_AMBIENT, white);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
	glLightfv(GL_LIGHT0, GL_POSITION, position);

	// glEnable(GL_COLOR_MATERIAL);

	m_timer = boost::posix_time::microsec_clock::universal_time();
}

namespace {

Imath::V3f eyePosition(float sceneRotX, float sceneRotY, float sceneDist) {
	Imath::V3f eye;

	eye.x = sin(-sceneRotX / 180.0f * M_PI) * sceneDist;
	eye.z = cos(-sceneRotX / 180.0f * M_PI) * sceneDist;

	eye.y = sin(sceneRotY / 180.0f * M_PI) * sceneDist;
	eye.x *= cos(sceneRotY / 180.0f * M_PI);
	eye.z *= cos(sceneRotY / 180.0f * M_PI);

	return eye;
}

Imath::M44f lookAt(const Imath::V3f& eyePosition, const Imath::V3f& lookAt,
                   const Imath::V3f& upVector) {
	Imath::V3f forward = lookAt - eyePosition;
	forward.normalize();

	Imath::V3f side = forward.cross(upVector);
	side.normalize();

	Imath::V3f up = side.cross(forward);
	up.normalize();

	Imath::M44f rotmat;
	rotmat.makeIdentity();

	rotmat[0][0] = side.x;
	rotmat[1][0] = side.y;
	rotmat[2][0] = side.z;

	rotmat[0][1] = up.x;
	rotmat[1][1] = up.y;
	rotmat[2][1] = up.z;

	rotmat[0][2] = -forward.x;
	rotmat[1][2] = -forward.y;
	rotmat[2][2] = -forward.z;

	Imath::M44f transmat;
	transmat.setTranslation(Imath::V3f(-eyePosition.x, -eyePosition.y, -eyePosition.z));

	return transmat * rotmat;
}
}

void Viewport::paintGL() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45, (float)width() / (float)height(), m_sceneDistance * 0.1f,
	               std::max(m_sceneDistance * 2.0f, 1000.0f));

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	const Imath::V3f eye =
	    eyePosition(m_sceneRotationX, m_sceneRotationY, m_sceneDistance);

	const Imath::M44f m = lookAt(eye + m_origin, m_origin, Imath::V3f(0, 1, 0));
	glMultMatrixf(m.getValue());

	const boost::posix_time::ptime t(boost::posix_time::microsec_clock::universal_time());
	const float dt = (float)(t - m_timer).total_microseconds() / 1e6f;
	m_timer = t;

	glPushAttrib(GL_ALL_ATTRIB_BITS);
	emit render(dt);
	glPopAttrib();
}

void Viewport::resizeGL(int w, int h) {
	QGLWidget::resizeGL(w, h);

	glViewport(0, 0, w, h);
}

void Viewport::mouseMoveEvent(QMouseEvent* event) {
	if(event->buttons() & Qt::LeftButton) {
		m_sceneRotationX += (float)(event->x() - m_mouseX) / (float)width() * 360.0;
		m_sceneRotationY += (float)(event->y() - m_mouseY) / (float)height() * 360.0;

		update();
	}
	m_sceneRotationY = std::max(-89.0f, m_sceneRotationY);
	m_sceneRotationY = std::min(89.0f, m_sceneRotationY);

	if(event->buttons() & Qt::RightButton) {
		m_sceneDistance /= pow(10, (float)(event->y() - m_mouseY) / (float)height());

		update();
	}

	if(event->buttons() & Qt::MiddleButton) {
		const Imath::V3f eye =
		    eyePosition(m_sceneRotationX, m_sceneRotationY, m_sceneDistance);

		const float dx = -(float)(event->x() - m_mouseX) / (float)(width());
		const float dy = (float)(event->y() - m_mouseY) / (float)(height());

		Imath::V3f right = Imath::V3f(0, 1, 0).cross(eye).normalized();
		Imath::V3f up = eye.cross(right).normalized();

		right = right * m_sceneDistance * dx;
		up = up * m_sceneDistance * dy;

		m_origin += right + up;

		update();
	}

	m_mouseX = event->x();
	m_mouseY = event->y();
}
<commit_msg>Perspective matrix computation reimplemented<commit_after>#include "viewport.h"

#include <cassert>
#include <iostream>
#include <cmath>

#include <QtGui/QMouseEvent>

#include <ImathMatrix.h>

#include <GL/glu.h>

namespace {
std::vector<Viewport*> s_instances;
}

Viewport::Viewport(QWidget* parent)
    : QGLWidget(parent, (s_instances.size() > 0 ? s_instances[0] : NULL)),
      m_sceneDistance(10), m_sceneRotationX(30), m_sceneRotationY(30), m_origin(0, 0, 0),
      m_mouseX(0), m_mouseY(0) {
	s_instances.push_back(this);

	setMouseTracking(true);
}

Viewport::~Viewport() {
	int index = -1;
	for(unsigned a = 0; a < s_instances.size(); a++)
		if(s_instances[a] == this)
			index = a;
	assert(index >= 0);
	s_instances.erase(s_instances.begin() + index);
}

void Viewport::initializeGL() {
	glClearColor(0, 0, 0, 0);
	resizeGL(width(), height());

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	float white[3] = {1, 1, 1};
	float position[4] = {1, 1, 1, 0};

	glEnable(GL_LIGHT0);
	glLightfv(GL_LIGHT0, GL_AMBIENT, white);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
	glLightfv(GL_LIGHT0, GL_POSITION, position);

	// glEnable(GL_COLOR_MATERIAL);

	m_timer = boost::posix_time::microsec_clock::universal_time();
}

namespace {

Imath::V3f eyePosition(float sceneRotX, float sceneRotY, float sceneDist) {
	Imath::V3f eye;

	eye.x = sin(-sceneRotX / 180.0f * M_PI) * sceneDist;
	eye.z = cos(-sceneRotX / 180.0f * M_PI) * sceneDist;

	eye.y = sin(sceneRotY / 180.0f * M_PI) * sceneDist;
	eye.x *= cos(sceneRotY / 180.0f * M_PI);
	eye.z *= cos(sceneRotY / 180.0f * M_PI);

	return eye;
}

Imath::M44f lookAt(const Imath::V3f& eyePosition, const Imath::V3f& lookAt,
                   const Imath::V3f& upVector) {
	Imath::V3f forward = lookAt - eyePosition;
	forward.normalize();

	Imath::V3f side = forward.cross(upVector);
	side.normalize();

	Imath::V3f up = side.cross(forward);
	up.normalize();

	Imath::M44f rotmat;
	rotmat.makeIdentity();

	rotmat[0][0] = side.x;
	rotmat[1][0] = side.y;
	rotmat[2][0] = side.z;

	rotmat[0][1] = up.x;
	rotmat[1][1] = up.y;
	rotmat[2][1] = up.z;

	rotmat[0][2] = -forward.x;
	rotmat[1][2] = -forward.y;
	rotmat[2][2] = -forward.z;

	Imath::M44f transmat;
	transmat.setTranslation(Imath::V3f(-eyePosition.x, -eyePosition.y, -eyePosition.z));

	return transmat * rotmat;
}

Imath::M44f perspective(float fovyInDegrees, float aspectRatio, float znear, float zfar) {
	const float f = 1.0 / tanf(fovyInDegrees * M_PI / 360.0);
	const float A = (zfar + znear) / (znear - zfar);
	const float B = 2.0 * zfar * znear / (znear - zfar);

	return Imath::M44f(
		f / aspectRatio, 0, 0, 0,
		0, f, 0, 0,
		0, 0, A, -1,
		0, 0, B, 0);
}
}

void Viewport::paintGL() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	{
		const Imath::M44f persp =
		    perspective(45, (float)width() / (float)height(), m_sceneDistance * 0.1f,
		                std::max(m_sceneDistance * 2.0f, 1000.0f));
		glMatrixMode(GL_PROJECTION);
		glLoadMatrixf(persp.getValue());
	}

	{
		const Imath::M44f m = lookAt(
		    eyePosition(m_sceneRotationX, m_sceneRotationY, m_sceneDistance) + m_origin,
		    m_origin, Imath::V3f(0, 1, 0));
		glMatrixMode(GL_MODELVIEW);
		glLoadMatrixf(m.getValue());
	}

	const boost::posix_time::ptime t(boost::posix_time::microsec_clock::universal_time());
	const float dt = (float)(t - m_timer).total_microseconds() / 1e6f;
	m_timer = t;

	glPushAttrib(GL_ALL_ATTRIB_BITS);
	emit render(dt);
	glPopAttrib();
}

void Viewport::resizeGL(int w, int h) {
	QGLWidget::resizeGL(w, h);

	glViewport(0, 0, w, h);
}

void Viewport::mouseMoveEvent(QMouseEvent* event) {
	if(event->buttons() & Qt::LeftButton) {
		m_sceneRotationX += (float)(event->x() - m_mouseX) / (float)width() * 360.0;
		m_sceneRotationY += (float)(event->y() - m_mouseY) / (float)height() * 360.0;

		update();
	}
	m_sceneRotationY = std::max(-89.0f, m_sceneRotationY);
	m_sceneRotationY = std::min(89.0f, m_sceneRotationY);

	if(event->buttons() & Qt::RightButton) {
		m_sceneDistance /= pow(10, (float)(event->y() - m_mouseY) / (float)height());

		update();
	}

	if(event->buttons() & Qt::MiddleButton) {
		const Imath::V3f eye =
		    eyePosition(m_sceneRotationX, m_sceneRotationY, m_sceneDistance);

		const float dx = -(float)(event->x() - m_mouseX) / (float)(width());
		const float dy = (float)(event->y() - m_mouseY) / (float)(height());

		Imath::V3f right = Imath::V3f(0, 1, 0).cross(eye).normalized();
		Imath::V3f up = eye.cross(right).normalized();

		right = right * m_sceneDistance * dx;
		up = up * m_sceneDistance * dy;

		m_origin += right + up;

		update();
	}

	m_mouseX = event->x();
	m_mouseY = event->y();
}
<|endoftext|>