<commit_before>#include <algorithm>
#include <libdariadb/flags.h>
#include <libdariadb/storage/cursors.h>
#include <libdariadb/utils/utils.h>
#include <map>
#include <set>

using namespace dariadb;
using namespace dariadb::storage;

namespace cursors_inner {

Time get_top_time(ICursor *r) {
  if (r->is_end()) {
    return MAX_TIME;
  } else {
    return r->top().time;
  }
}
void fill_top_times(std::vector<Time> &top_times,
                    const std::vector<Cursor_Ptr> &readers) {
  size_t pos = 0;
  for (auto r : readers) {
    top_times[pos++] = get_top_time(r.get());
  }
}

/// return: pair(index,ptr)
std::pair<size_t, ICursor *>
get_cursor_with_min_time(std::vector<Time> &top_times,
                         const std::vector<Cursor_Ptr> &readers) {
  Time min_time = MAX_TIME;
  size_t min_time_index = 0;
  for (size_t i = 0; i < top_times.size(); ++i) {
    if (top_times[i] != MAX_TIME && min_time > top_times[i]) {
      min_time = top_times[i];
      min_time_index = i;
    }
  }
  auto reader_it = readers[min_time_index];
  return std::make_pair(min_time_index, reader_it.get());
}

CursorsList unpack_readers(const CursorsList &readers) {
  CursorsList tmp_readers_list;

  for (auto r : readers) {
    // TODO use type enum.
    auto msr = dynamic_cast<MergeSortCursor *>(r.get());
    if (msr == nullptr) {
      tmp_readers_list.emplace_back(r);
    } else {
      for (auto sub_reader : msr->_readers) {
        tmp_readers_list.emplace_back(sub_reader);
      }
    }
  }
  return tmp_readers_list;
}
}

FullCursor::FullCursor(MeasArray &ma) : _ma(ma) {
  _index = size_t(0);

  _minTime = MAX_TIME;
  _maxTime = MIN_TIME;
  for (auto &v : _ma) {
    _minTime = std::min(_minTime, v.time);
    _maxTime = std::max(_maxTime, v.time);
  }
  ENSURE(!_ma.empty());
  ENSURE(_minTime != MAX_TIME);
  ENSURE(_minTime <= _maxTime);
}

Meas FullCursor::readNext() {
  ENSURE(!is_end());

  auto result = _ma[_index++];
  return result;
}

bool FullCursor::is_end() const { return _index >= _ma.size(); }

Meas FullCursor::top() {
  if (!is_end()) {
    return _ma[_index];
  }
  THROW_EXCEPTION("is_end()");
}

Time FullCursor::minTime() { return _minTime; }

Time FullCursor::maxTime() { return _maxTime; }

MergeSortCursor::MergeSortCursor(const CursorsList &readers) {
  CursorsList tmp_readers_list = cursors_inner::unpack_readers(readers);

  _readers.reserve(tmp_readers_list.size());
  for (auto r : tmp_readers_list) {
    _readers.emplace_back(r);
  }

  _top_times.resize(_readers.size());
  _is_end_status.resize(_top_times.size());
  cursors_inner::fill_top_times(_top_times, _readers);

  _minTime = MAX_TIME;
  _maxTime = MIN_TIME;
  for (auto &r : _readers) {
    _minTime = std::min(_minTime, r->minTime());
    _maxTime = std::max(_maxTime, r->maxTime());
  }
  ENSURE(!_readers.empty());
  ENSURE(_minTime != MAX_TIME);
  ENSURE(_minTime <= _maxTime);
}

Meas MergeSortCursor::readNext() {
  ENSURE(!is_end());
  auto index_and_reader =
      cursors_inner::get_cursor_with_min_time(_top_times, _readers);

  auto cursor = index_and_reader.second;
  ENSURE(!cursor->is_end());

  auto result = cursor->readNext();
  _top_times[index_and_reader.first] = cursors_inner::get_top_time(cursor);
  _is_end_status[index_and_reader.first] = cursor->is_end();

  // skip duplicates.
  for (size_t i = 0; i < _readers.size(); ++i) {
    if (!_is_end_status[i] && _top_times[i] == result.time) {
      auto r = _readers[i].get();
      while (!r->is_end()) {
        if (r->top().time != result.time) {
          break;
        }
        r->readNext();
      }
      _top_times[i] = cursors_inner::get_top_time(r);
      if (r->is_end()) {
        _is_end_status[i] = true;
      }
    }
  }
  return result;
}

bool MergeSortCursor::is_end() const {
  for (size_t i = 0; i < _is_end_status.size(); ++i) {
    if (!_is_end_status[i]) {
      return false;
    }
  }
  return true;
}

Meas MergeSortCursor::top() {
  ENSURE(!is_end());
  auto r = cursors_inner::get_cursor_with_min_time(_top_times, _readers);
  return r.second->top();
}

Time MergeSortCursor::minTime() { return _minTime; }

Time MergeSortCursor::maxTime() { return _maxTime; }

LinearCursor::LinearCursor(const CursorsList &readers) {
  std::vector<Cursor_Ptr> rv(readers.begin(), readers.end());
  std::sort(rv.begin(), rv.end(),
            [](auto l, auto r) { return l->minTime() < r->minTime(); });
  _readers = CursorsList(rv.begin(), rv.end());
  _minTime = MAX_TIME;
  _maxTime = MIN_TIME;
  for (auto &r : _readers) {
    _minTime = std::min(_minTime, r->minTime());
    _maxTime = std::max(_maxTime, r->maxTime());
  }
  ENSURE(!_readers.empty());
  ENSURE(!is_end());
  ENSURE(_minTime != MAX_TIME);
  ENSURE(_minTime <= _maxTime);
}

Meas LinearCursor::readNext() {
  ENSURE(!is_end());

  auto result = _readers.front()->readNext();
  if (_readers.front()->is_end()) {
    _readers.pop_front();
  }
  return result;
}

bool LinearCursor::is_end() const { return _readers.empty(); }

Meas LinearCursor::top() {
  ENSURE(!is_end());
  return _readers.front()->top();
}

Time LinearCursor::minTime() { return _minTime; }

Time LinearCursor::maxTime() { return _maxTime; }

Cursor_Ptr
CursorWrapperFactory::colapseCursors(const CursorsList &readers_list) {
  std::vector<Cursor_Ptr> readers_vector{readers_list.begin(),
                                         readers_list.end()};
  typedef std::set<size_t> positions_set;
  std::map<size_t, positions_set> overlapped;
  positions_set processed_pos;

  CursorsList result_readers;
  for (size_t i = 0; i < readers_vector.size(); ++i) {
    bool have_overlap = false;
    for (size_t j = 0; j < readers_vector.size(); ++j) {
      if (i != j) {
        bool is_not_processed = processed_pos.find(j) == processed_pos.end();
        if (!is_linear_readers(readers_vector[i], readers_vector[j]) &&
            is_not_processed) {
          processed_pos.insert(i);
          processed_pos.insert(j);
          overlapped[i].insert(j);
          have_overlap = true;
        }
      }
    }
    if (processed_pos.find(i) == processed_pos.end() && !have_overlap) {
      result_readers.emplace_back(readers_vector[i]);
    }
  }

  for (auto kv : overlapped) {
    CursorsList rs;
    rs.emplace_back(readers_vector[kv.first]);
    for (size_t pos : kv.second) {
      rs.emplace_back(readers_vector[pos]);
    }
    MergeSortCursor *msr = new MergeSortCursor(rs);
    Cursor_Ptr rptr{msr};
    result_readers.emplace_back(rptr);
  }

  LinearCursor *lsr = new LinearCursor(result_readers);
  Cursor_Ptr rptr{lsr};
  return rptr;
}

Id2Cursor CursorWrapperFactory::colapseCursors(const Id2CursorsList &i2r) {
  Id2Cursor result;
  for (auto kv : i2r) {
    if (kv.second.size() == 1) {
      result[kv.first] = kv.second.front();
    } else {
      result[kv.first] = colapseCursors(kv.second);
    }
  }
  return result;
}

bool CursorWrapperFactory::is_linear_readers(const Cursor_Ptr &r1,
                                             const Cursor_Ptr &r2) {
  bool is_overlap = utils::intervalsIntersection(r1->minTime(), r1->maxTime(),
                                                 r2->minTime(), r2->maxTime());
  return !is_overlap;
}

void Join::join(const CursorsList &l, const IdArray &ids,
                Join::Callback *clbk) {
  std::vector<Cursor_Ptr> cursors{l.begin(), l.end()};
  ENSURE(ids.size() == cursors.size());

  std::vector<bool> end_status(cursors.size());
  std::vector<Time> top_times(cursors.size());
  size_t pos = 0;
  for (auto c : cursors) {
    end_status[pos++] = c->is_end();
  }

  cursors_inner::fill_top_times(top_times, cursors);

  MeasArray row(cursors.size());
  for (size_t i = 0; i < cursors.size(); ++i) {
    row[i].flag = FLAGS::_NO_DATA;
    row[i].id = ids[i];
  }

  while (std::any_of(end_status.begin(), end_status.end(),
                     [](auto v) { return !v; })) {
    auto pos_and_cursor =
        cursors_inner::get_cursor_with_min_time(top_times, cursors);
    auto min_time = top_times[pos_and_cursor.first];

    std::list<size_t> current_row;
    for (size_t i = 0; i < cursors.size(); ++i) {
      if (row[i].flag != FLAGS::_NO_DATA) {
        row[i].addFlag(FLAGS::_REPEAT);
      }
      row[i].time = min_time;
      if (!end_status[i]) {
        auto c = cursors[i].get();

        if (c->top().time == min_time) {
          current_row.push_back(i);
        }
      }
    }

    for (auto i : current_row) {
      auto c = cursors[i].get();
      row[i] = c->readNext();
      end_status[i] = c->is_end();
      top_times[i] = cursors_inner::get_top_time(c);
    }
    clbk->apply(row);
  }
}

Join::Table Join::makeTable(const CursorsList &l, const IdArray &ids) {
  auto tm = std::make_unique<TableMaker>();
  Join::join(l, ids, tm.get());
  return tm->result;
}<commit_msg>one more check.<commit_after>#include <algorithm>
#include <libdariadb/flags.h>
#include <libdariadb/storage/cursors.h>
#include <libdariadb/utils/utils.h>
#include <map>
#include <set>

using namespace dariadb;
using namespace dariadb::storage;

namespace cursors_inner {

Time get_top_time(ICursor *r) {
  if (r->is_end()) {
    return MAX_TIME;
  } else {
    return r->top().time;
  }
}
void fill_top_times(std::vector<Time> &top_times,
                    const std::vector<Cursor_Ptr> &readers) {
  size_t pos = 0;
  for (auto r : readers) {
    top_times[pos++] = get_top_time(r.get());
  }
}

/// return: pair(index,ptr)
std::pair<size_t, ICursor *>
get_cursor_with_min_time(std::vector<Time> &top_times,
                         const std::vector<Cursor_Ptr> &readers) {
  Time min_time = MAX_TIME;
  size_t min_time_index = 0;
  for (size_t i = 0; i < top_times.size(); ++i) {
    if (top_times[i] != MAX_TIME && min_time > top_times[i]) {
      min_time = top_times[i];
      min_time_index = i;
    }
  }
  auto reader_it = readers[min_time_index];
  return std::make_pair(min_time_index, reader_it.get());
}

CursorsList unpack_readers(const CursorsList &readers) {
  CursorsList tmp_readers_list;

  for (auto r : readers) {
    // TODO use type enum.
    auto msr = dynamic_cast<MergeSortCursor *>(r.get());
    if (msr == nullptr) {
      tmp_readers_list.emplace_back(r);
    } else {
      for (auto sub_reader : msr->_readers) {
        tmp_readers_list.emplace_back(sub_reader);
      }
    }
  }
  return tmp_readers_list;
}
}

FullCursor::FullCursor(MeasArray &ma) : _ma(ma) {
  _index = size_t(0);

  _minTime = MAX_TIME;
  _maxTime = MIN_TIME;
  for (auto &v : _ma) {
    _minTime = std::min(_minTime, v.time);
    _maxTime = std::max(_maxTime, v.time);
  }
  ENSURE(!_ma.empty());
  ENSURE(_minTime != MAX_TIME);
  ENSURE(_minTime <= _maxTime);
}

Meas FullCursor::readNext() {
  ENSURE(!is_end());

  auto result = _ma[_index++];
  return result;
}

bool FullCursor::is_end() const { return _index >= _ma.size(); }

Meas FullCursor::top() {
  if (!is_end()) {
    return _ma[_index];
  }
  THROW_EXCEPTION("is_end()");
}

Time FullCursor::minTime() { return _minTime; }

Time FullCursor::maxTime() { return _maxTime; }

MergeSortCursor::MergeSortCursor(const CursorsList &readers) {
  CursorsList tmp_readers_list = cursors_inner::unpack_readers(readers);

  _readers.reserve(tmp_readers_list.size());
  for (auto r : tmp_readers_list) {
    _readers.emplace_back(r);
  }

  _top_times.resize(_readers.size());
  _is_end_status.resize(_top_times.size());
  cursors_inner::fill_top_times(_top_times, _readers);

  _minTime = MAX_TIME;
  _maxTime = MIN_TIME;
  for (auto &r : _readers) {
    _minTime = std::min(_minTime, r->minTime());
    _maxTime = std::max(_maxTime, r->maxTime());
  }
  ENSURE(!_readers.empty());
  ENSURE(_minTime != MAX_TIME);
  ENSURE(_minTime <= _maxTime);
}

Meas MergeSortCursor::readNext() {
  ENSURE(!is_end());
  auto index_and_reader =
      cursors_inner::get_cursor_with_min_time(_top_times, _readers);

  auto cursor = index_and_reader.second;
  ENSURE(!_is_end_status[index_and_reader.first]);
  ENSURE(!cursor->is_end());

  auto result = cursor->readNext();
  _top_times[index_and_reader.first] = cursors_inner::get_top_time(cursor);
  _is_end_status[index_and_reader.first] = cursor->is_end();

  // skip duplicates.
  for (size_t i = 0; i < _readers.size(); ++i) {
    if (!_is_end_status[i] && _top_times[i] == result.time) {
      auto r = _readers[i].get();
      while (!r->is_end()) {
        if (r->top().time != result.time) {
          break;
        }
        r->readNext();
      }
      _top_times[i] = cursors_inner::get_top_time(r);
	  _is_end_status[i] = r->is_end();
    }
  }
  return result;
}

bool MergeSortCursor::is_end() const {
  for (size_t i = 0; i < _is_end_status.size(); ++i) {
    if (!_is_end_status[i]) {
      return false;
    }
  }
  return true;
}

Meas MergeSortCursor::top() {
  ENSURE(!is_end());
  auto r = cursors_inner::get_cursor_with_min_time(_top_times, _readers);
  return r.second->top();
}

Time MergeSortCursor::minTime() { return _minTime; }

Time MergeSortCursor::maxTime() { return _maxTime; }

LinearCursor::LinearCursor(const CursorsList &readers) {
  std::vector<Cursor_Ptr> rv(readers.begin(), readers.end());
  std::sort(rv.begin(), rv.end(),
            [](auto l, auto r) { return l->minTime() < r->minTime(); });
  _readers = CursorsList(rv.begin(), rv.end());
  _minTime = MAX_TIME;
  _maxTime = MIN_TIME;
  for (auto &r : _readers) {
    _minTime = std::min(_minTime, r->minTime());
    _maxTime = std::max(_maxTime, r->maxTime());
  }
  ENSURE(!_readers.empty());
  ENSURE(!is_end());
  ENSURE(_minTime != MAX_TIME);
  ENSURE(_minTime <= _maxTime);
}

Meas LinearCursor::readNext() {
  ENSURE(!is_end());

  auto result = _readers.front()->readNext();
  if (_readers.front()->is_end()) {
    _readers.pop_front();
  }
  return result;
}

bool LinearCursor::is_end() const { return _readers.empty(); }

Meas LinearCursor::top() {
  ENSURE(!is_end());
  return _readers.front()->top();
}

Time LinearCursor::minTime() { return _minTime; }

Time LinearCursor::maxTime() { return _maxTime; }

Cursor_Ptr
CursorWrapperFactory::colapseCursors(const CursorsList &readers_list) {
  std::vector<Cursor_Ptr> readers_vector{readers_list.begin(),
                                         readers_list.end()};
  typedef std::set<size_t> positions_set;
  std::map<size_t, positions_set> overlapped;
  positions_set processed_pos;

  CursorsList result_readers;
  for (size_t i = 0; i < readers_vector.size(); ++i) {
    bool have_overlap = false;
    for (size_t j = 0; j < readers_vector.size(); ++j) {
      if (i != j) {
        bool is_not_processed = processed_pos.find(j) == processed_pos.end();
        if (!is_linear_readers(readers_vector[i], readers_vector[j]) &&
            is_not_processed) {
          processed_pos.insert(i);
          processed_pos.insert(j);
          overlapped[i].insert(j);
          have_overlap = true;
        }
      }
    }
    if (processed_pos.find(i) == processed_pos.end() && !have_overlap) {
      result_readers.emplace_back(readers_vector[i]);
    }
  }

  for (auto kv : overlapped) {
    CursorsList rs;
    rs.emplace_back(readers_vector[kv.first]);
    for (size_t pos : kv.second) {
      rs.emplace_back(readers_vector[pos]);
    }
    MergeSortCursor *msr = new MergeSortCursor(rs);
    Cursor_Ptr rptr{msr};
    result_readers.emplace_back(rptr);
  }

  LinearCursor *lsr = new LinearCursor(result_readers);
  Cursor_Ptr rptr{lsr};
  return rptr;
}

Id2Cursor CursorWrapperFactory::colapseCursors(const Id2CursorsList &i2r) {
  Id2Cursor result;
  for (auto kv : i2r) {
    if (kv.second.size() == 1) {
      result[kv.first] = kv.second.front();
    } else {
      result[kv.first] = colapseCursors(kv.second);
    }
  }
  return result;
}

bool CursorWrapperFactory::is_linear_readers(const Cursor_Ptr &r1,
                                             const Cursor_Ptr &r2) {
  bool is_overlap = utils::intervalsIntersection(r1->minTime(), r1->maxTime(),
                                                 r2->minTime(), r2->maxTime());
  return !is_overlap;
}

void Join::join(const CursorsList &l, const IdArray &ids,
                Join::Callback *clbk) {
  std::vector<Cursor_Ptr> cursors{l.begin(), l.end()};
  ENSURE(ids.size() == cursors.size());

  std::vector<bool> end_status(cursors.size());
  std::vector<Time> top_times(cursors.size());
  size_t pos = 0;
  for (auto c : cursors) {
    end_status[pos++] = c->is_end();
  }

  cursors_inner::fill_top_times(top_times, cursors);

  MeasArray row(cursors.size());
  for (size_t i = 0; i < cursors.size(); ++i) {
    row[i].flag = FLAGS::_NO_DATA;
    row[i].id = ids[i];
  }

  while (std::any_of(end_status.begin(), end_status.end(),
                     [](auto v) { return !v; })) {
    auto pos_and_cursor =
        cursors_inner::get_cursor_with_min_time(top_times, cursors);
    auto min_time = top_times[pos_and_cursor.first];

    std::list<size_t> current_row;
    for (size_t i = 0; i < cursors.size(); ++i) {
      if (row[i].flag != FLAGS::_NO_DATA) {
        row[i].addFlag(FLAGS::_REPEAT);
      }
      row[i].time = min_time;
      if (!end_status[i]) {
        auto c = cursors[i].get();

        if (c->top().time == min_time) {
          current_row.push_back(i);
        }
      }
    }

    for (auto i : current_row) {
      auto c = cursors[i].get();
      row[i] = c->readNext();
      end_status[i] = c->is_end();
      top_times[i] = cursors_inner::get_top_time(c);
    }
    clbk->apply(row);
  }
}

Join::Table Join::makeTable(const CursorsList &l, const IdArray &ids) {
  auto tm = std::make_unique<TableMaker>();
  Join::join(l, ids, tm.get());
  return tm->result;
}<|endoftext|>


<commit_before>#ifndef __INCLUDED_SYMBOLSET_PREPROCESSOR_HPP__
#define __INCLUDED_SYMBOLSET_PREPROCESSOR_HPP__

#define BOOST_PP_VARIADICS
#include <boost/preprocessor.hpp>

// utils
#define SYMBOLSET_PP_ARG_TUPLE(data_tuple) \
    BOOST_PP_TUPLE_ELEM(0, data_tuple)

#define SYMBOLSET_PP_VAL_TUPLE(data_tuple) \
    BOOST_PP_TUPLE_ELEM(1, data_tuple)

#define SYMBOLSET_PP_ARG(i, data_tuple) \
    BOOST_PP_TUPLE_ELEM(i, \
        SYMBOLSET_PP_ARG_TUPLE(data_tuple) \
    )

#define SYMBOLSET_PP_VAL(i, data_tuple) \
    BOOST_PP_TUPLE_ELEM(i, \
        SYMBOLSET_PP_VAL_TUPLE(data_tuple) \
    )

#define SYMBOLSET_PP_STR(i, data_tuple) \
    BOOST_PP_STRINGIZE( \
        SYMBOLSET_PP_VAL(i,data_tuple) \
    )

#define SYMBOLSET_PP_EACH(callback, data_tuple) \
    BOOST_PP_REPEAT( \
        BOOST_PP_TUPLE_SIZE(SYMBOLSET_PP_VAL_TUPLE(data_tuple)), \
        callback, \
        data_tuple \
    )

// display the symbols
#define SYMBOLSET_PP_SYMBOL_LIST(data_tuple) \
    SYMBOLSET_PP_EACH(SYMBOLSET_PP_SYMBOL, data_tuple)

#define SYMBOLSET_PP_SYMBOL(unused, i, data_tuple) \
    static constexpr value_type SYMBOLSET_PP_VAL(i, data_tuple) = static_cast<value_type>(i);

// display the symbol-name mapping list
#define SYMBOLSET_PP_NAME_LIST(data_tuple) \
    BOOST_PP_SEQ_ENUM( \
        SYMBOLSET_PP_EACH(SYMBOLSET_PP_NAME, data_tuple) \
    )

#define SYMBOLSET_PP_NAME(unused, i, data_tuple) \
    ({::symbolset::val(SYMBOLSET_PP_ARG(0, data_tuple)::SYMBOLSET_PP_VAL(i, data_tuple))) \
    (SYMBOLSET_PP_STR(i, data_tuple)})

// display the static_assert() list
#define SYMBOLSET_PP_ASSERT_LIST(data_tuple) \
    SYMBOLSET_PP_EACH(SYMBOLSET_PP_ASSERT, data_tuple)

#define SYMBOLSET_PP_ASSERT(unused, i, data_tuple) \
    static_assert(SYMBOLSET_PP_STR(i, data_tuple)[0] != '\0', "Symbol name is empty! (index: " #i ")");

// display the symbolset
#define SYMBOLSET_DEFINE(type, symbols) \
    SYMBOLSET_PP_DEFINE(type, ((type), symbols))

#define SYMBOLSET_PP_DEFINE(type, data_tuple) \
    SYMBOLSET_PP_ASSERT_LIST(data_tuple) \
    \
    struct type: public ::symbolset::symbolset<type> { \
        using symbolset::symbolset; \
        constexpr type() : symbolset() {} \
        constexpr type(const symbolset & v) : symbolset(v) {} \
        \
        SYMBOLSET_PP_SYMBOL_LIST(data_tuple) \
        \
        static const info_type & info() { \
            static info_type const data{ \
                SYMBOLSET_PP_NAME_LIST(data_tuple) \
            }; \
            return data; \
        } \
    };

#endif // __INCLUDED_SYMBOLSET_PREPROCESSOR_HPP__
<commit_msg>Fix the processor.<commit_after>#ifndef __INCLUDED_SYMBOLSET_PREPROCESSOR_HPP__
#define __INCLUDED_SYMBOLSET_PREPROCESSOR_HPP__

#define BOOST_PP_VARIADICS
#include <boost/preprocessor.hpp>

// utils
#define SYMBOLSET_PP_ARG_TUPLE(data_tuple) \
    BOOST_PP_TUPLE_ELEM(0, data_tuple)

#define SYMBOLSET_PP_VAL_TUPLE(data_tuple) \
    BOOST_PP_TUPLE_ELEM(1, data_tuple)

#define SYMBOLSET_PP_ARG(i, data_tuple) \
    BOOST_PP_TUPLE_ELEM(i, \
        SYMBOLSET_PP_ARG_TUPLE(data_tuple) \
    )

#define SYMBOLSET_PP_VAL(i, data_tuple) \
    BOOST_PP_TUPLE_ELEM(i, \
        SYMBOLSET_PP_VAL_TUPLE(data_tuple) \
    )

#define SYMBOLSET_PP_STR(i, data_tuple) \
    BOOST_PP_STRINGIZE( \
        SYMBOLSET_PP_VAL(i, data_tuple) \
    )

#define SYMBOLSET_PP_EACH(callback, data_tuple) \
    BOOST_PP_REPEAT( \
        BOOST_PP_TUPLE_SIZE(SYMBOLSET_PP_VAL_TUPLE(data_tuple)), \
        callback, \
        data_tuple \
    )

// display the symbols
#define SYMBOLSET_PP_SYMBOL_LIST(data_tuple) \
    SYMBOLSET_PP_EACH(SYMBOLSET_PP_SYMBOL, data_tuple)

#define SYMBOLSET_PP_SYMBOL(unused, i, data_tuple) \
    SYMBOLSET_PP_SYMBOL_IMPL( \
        SYMBOLSET_PP_VAL(i, data_tuple), i \
    )

#define SYMBOLSET_PP_SYMBOL_IMPL(symbol, value) \
    static constexpr value_type symbol = static_cast<value_type>(value);

// display the symbol-name mapping list
#define SYMBOLSET_PP_NAME_LIST(data_tuple) \
    BOOST_PP_SEQ_ENUM( \
        SYMBOLSET_PP_EACH(SYMBOLSET_PP_NAME, data_tuple) \
    )

#define SYMBOLSET_PP_NAME(unused, i, data_tuple) \
    SYMBOLSET_PP_NAME_IMPL( \
        SYMBOLSET_PP_ARG(0, data_tuple), \
        SYMBOLSET_PP_VAL(i, data_tuple), \
        SYMBOLSET_PP_STR(i, data_tuple) \
    )

#define SYMBOLSET_PP_NAME_IMPL(type, symbol, name) \
    ({::symbolset::val(type::symbol)) (name})

// display the static_assert() list
#define SYMBOLSET_PP_ASSERT_LIST(data_tuple) \
    SYMBOLSET_PP_EACH(SYMBOLSET_PP_ASSERT, data_tuple)

#define SYMBOLSET_PP_ASSERT(unused, i, data_tuple) \
    SYMBOLSET_PP_ASSERT_IMPL( \
        SYMBOLSET_PP_STR(i, data_tuple), \
        "Symbol name is empty! (index: " #i ")"  \
    )

#define SYMBOLSET_PP_ASSERT_IMPL(name, message) \
    static_assert(name[0] != '\0', message);

// display the symbolset
#define SYMBOLSET_DEFINE(type, symbols) \
    SYMBOLSET_PP_DEFINE(type, ((type), symbols))

#define SYMBOLSET_PP_DEFINE(type, data_tuple) \
    SYMBOLSET_PP_ASSERT_LIST(data_tuple) \
    \
    struct type: public ::symbolset::symbolset<type> { \
        using symbolset::symbolset; \
        constexpr type() : symbolset() {} \
        constexpr type(const symbolset & v) : symbolset(v) {} \
        \
        SYMBOLSET_PP_SYMBOL_LIST(data_tuple) \
        \
        static const info_type & info() { \
            static info_type const data{ \
                SYMBOLSET_PP_NAME_LIST(data_tuple) \
            }; \
            return data; \
        } \
    };

#endif // __INCLUDED_SYMBOLSET_PREPROCESSOR_HPP__
<|endoftext|>


<commit_before>// Copyright 2006-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================

#include <atlbase.h>
#include <atlcom.h>
#include <iterator>
#include <map>

#include "gtest/gtest.h"
#include "omaha/statsreport/aggregator-win32_unittest.h"
#include "omaha/statsreport/const-win32.h"
#include "omaha/statsreport/persistent_iterator-win32.h"

using namespace stats_report;

namespace {

class PersistentMetricsIteratorWin32Test: public MetricsAggregatorWin32Test {
public:
  bool WriteStats() {
    // put some persistent metrics into the registry
    MetricsAggregatorWin32 agg(coll_, kAppName);
    AddStats();
    bool ret = agg.AggregateMetrics();

    // Reset the stats, we should now have the same stats
    // in our collection as in registry.
    AddStats();

    return ret;
  }

  typedef std::map<std::string, MetricBase*> MetricsMap;
  void IndexMetrics(MetricsMap *metrics) {
    // build a map over the metrics in our collection
    MetricIterator it(coll_), end;

    for (; it != end; ++it) {
      metrics->insert(std::make_pair(std::string(it->name()), *it));
    }
  }
};

// compare two metrics instances for equality
bool equals(MetricBase *a, MetricBase *b) {
  if (!a || !b)
    return false;

  if (a->type() != b->type() || 0 != strcmp(a->name(), b->name()))
    return false;

  switch (a->type()) {
   case kCountType:
    return a->AsCount().value() == b->AsCount().value();
    break;
   case kTimingType: {
      TimingMetric &at = a->AsTiming();
      TimingMetric &bt = b->AsTiming();

      return at.count() == bt.count() &&
             at.sum() == bt.sum() &&
             at.minimum() == bt.minimum() &&
             at.maximum() == bt.maximum();
    }
    break;
   case kIntegerType:
    return a->AsInteger().value() == b->AsInteger().value();
    break;
   case kBoolType:
    return a->AsBool().value() == b->AsBool().value();
    break;

   case kInvalidType:
   default:
    LOG(FATAL) << "Impossible metric type";
  }

  return false;
}

} // namespace

TEST_F(PersistentMetricsIteratorWin32Test, Basic) {
  EXPECT_TRUE(WriteStats());
  PersistentMetricsIteratorWin32 a, b, c(kAppName);

  EXPECT_TRUE(a == b);
  EXPECT_TRUE(b == a);

  EXPECT_FALSE(a == c);
  EXPECT_FALSE(b == c);
  EXPECT_FALSE(c == a);
  EXPECT_FALSE(c == b);

  ++a;
  EXPECT_TRUE(a == b);
  EXPECT_TRUE(b == a);
}

// Test to see whether we can reliably roundtrip metrics through
// the registry without molestation
TEST_F(PersistentMetricsIteratorWin32Test, UnmolestedValues) {
  EXPECT_TRUE(WriteStats());

  MetricsMap metrics;
  IndexMetrics(&metrics);

  PersistentMetricsIteratorWin32 it(kAppName), end;
  int count = 0;
  for (; it != end; ++it) {
    MetricsMap::iterator found = metrics.find(it->name());

    // make sure we found it, and that it's unmolested in value
    EXPECT_TRUE(found != metrics.end() && equals(found->second, *it));
    count++;
  }

  // Did we visit all metrics?
  EXPECT_EQ(count, metrics.size());
}
<commit_msg>Rename code and comments to remove offensive wording.<commit_after>// Copyright 2006-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================

#include <atlbase.h>
#include <atlcom.h>
#include <iterator>
#include <map>

#include "gtest/gtest.h"
#include "omaha/statsreport/aggregator-win32_unittest.h"
#include "omaha/statsreport/const-win32.h"
#include "omaha/statsreport/persistent_iterator-win32.h"

using namespace stats_report;

namespace {

class PersistentMetricsIteratorWin32Test: public MetricsAggregatorWin32Test {
public:
  bool WriteStats() {
    // put some persistent metrics into the registry
    MetricsAggregatorWin32 agg(coll_, kAppName);
    AddStats();
    bool ret = agg.AggregateMetrics();

    // Reset the stats, we should now have the same stats
    // in our collection as in registry.
    AddStats();

    return ret;
  }

  typedef std::map<std::string, MetricBase*> MetricsMap;
  void IndexMetrics(MetricsMap *metrics) {
    // build a map over the metrics in our collection
    MetricIterator it(coll_), end;

    for (; it != end; ++it) {
      metrics->insert(std::make_pair(std::string(it->name()), *it));
    }
  }
};

// compare two metrics instances for equality
bool equals(MetricBase *a, MetricBase *b) {
  if (!a || !b)
    return false;

  if (a->type() != b->type() || 0 != strcmp(a->name(), b->name()))
    return false;

  switch (a->type()) {
   case kCountType:
    return a->AsCount().value() == b->AsCount().value();
    break;
   case kTimingType: {
      TimingMetric &at = a->AsTiming();
      TimingMetric &bt = b->AsTiming();

      return at.count() == bt.count() &&
             at.sum() == bt.sum() &&
             at.minimum() == bt.minimum() &&
             at.maximum() == bt.maximum();
    }
    break;
   case kIntegerType:
    return a->AsInteger().value() == b->AsInteger().value();
    break;
   case kBoolType:
    return a->AsBool().value() == b->AsBool().value();
    break;

   case kInvalidType:
   default:
    LOG(FATAL) << "Impossible metric type";
  }

  return false;
}

} // namespace

TEST_F(PersistentMetricsIteratorWin32Test, Basic) {
  EXPECT_TRUE(WriteStats());
  PersistentMetricsIteratorWin32 a, b, c(kAppName);

  EXPECT_TRUE(a == b);
  EXPECT_TRUE(b == a);

  EXPECT_FALSE(a == c);
  EXPECT_FALSE(b == c);
  EXPECT_FALSE(c == a);
  EXPECT_FALSE(c == b);

  ++a;
  EXPECT_TRUE(a == b);
  EXPECT_TRUE(b == a);
}

// Test to see whether we can reliably roundtrip metrics through
// the registry without corruption.
TEST_F(PersistentMetricsIteratorWin32Test, WriteStats) {
  EXPECT_TRUE(WriteStats());

  MetricsMap metrics;
  IndexMetrics(&metrics);

  PersistentMetricsIteratorWin32 it(kAppName), end;
  int count = 0;
  for (; it != end; ++it) {
    MetricsMap::iterator found = metrics.find(it->name());

    // Make sure we found it, and that it's the correct value.
    EXPECT_TRUE(found != metrics.end() && equals(found->second, *it));
    count++;
  }

  // Did we visit all metrics?
  EXPECT_EQ(count, metrics.size());
}
<|endoftext|>


<commit_before>#include "notifyingscrollarea.h"
#include "notifyablescrollcontentwidget.h"
#include <QScrollBar>

LONGSCROLLQT_NAMESPACE_BEGIN

void NotifyingScrollArea::scrollContentsBy(int dx, int dy)
{
	QScrollArea::scrollContentsBy(dx, dy);
	findVisible();
}

void NotifyingScrollArea::resizeEvent(QResizeEvent * event)
{
	QScrollArea::resizeEvent(event);
	findVisible();
}

void NotifyingScrollArea::showEvent(QShowEvent * event)
{
	QScrollArea::showEvent(event);
	findVisible();
}

void NotifyingScrollArea::hideEvent(QHideEvent * event)
{
	QScrollArea::hideEvent(event);
	findVisible();
}

void NotifyingScrollArea::findVisible()
{
	QWidget * wid = widget();
	if (wid == 0)
		return;
	QRegion const & region = wid->visibleRegion();
	QList<NotifyableScrollContentWidget *> const & widgets = wid->findChildren<NotifyableScrollContentWidget *>(QString(), Qt::FindDirectChildrenOnly); //TODO: Can this be optimized, so that we don't have to call findChildren every time?
	for (NotifyableScrollContentWidget * it : widgets)
	{
		if (region.contains(it->geometry()))
		{
			QRect && r = region.boundingRect().intersected(it->geometry());
			r.moveTopLeft( it->mapFromParent(r.topLeft()) );
			it->showingRect(r);
		}
	}
}

LONGSCROLLQT_NAMESPACE_END
<commit_msg>Minor refactoring<commit_after>#include "notifyingscrollarea.h"
#include "notifyablescrollcontentwidget.h"
#include <QScrollBar>

LONGSCROLLQT_NAMESPACE_BEGIN

void NotifyingScrollArea::scrollContentsBy(int dx, int dy)
{
	QScrollArea::scrollContentsBy(dx, dy);
	findVisible();
}

void NotifyingScrollArea::resizeEvent(QResizeEvent * event)
{
	QScrollArea::resizeEvent(event);
	findVisible();
}

void NotifyingScrollArea::showEvent(QShowEvent * event)
{
	QScrollArea::showEvent(event);
	findVisible();
}

void NotifyingScrollArea::hideEvent(QHideEvent * event)
{
	QScrollArea::hideEvent(event);
	findVisible();
}

void NotifyingScrollArea::findVisible()
{
	QWidget * wid = widget();
	if (wid == 0)
		return;
	QRect const & visible = wid->visibleRegion().boundingRect();
	QList<NotifyableScrollContentWidget *> const & widgets = wid->findChildren<NotifyableScrollContentWidget *>(QString(), Qt::FindDirectChildrenOnly); //TODO: Can this be optimized, so that we don't have to call findChildren every time?
	for (NotifyableScrollContentWidget * w : widgets)
	{
		QRect && r = visible.intersected(w->geometry());
		if (!r.isEmpty())
			r.moveTopLeft( w->mapFromParent(r.topLeft()) );
		// r == w->visibleRegion().boundingRect(), thus w could determine r on its own, but this method is a little less computationally intensive.
		w->showingRect(r);
	}
}

LONGSCROLLQT_NAMESPACE_END
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "FrameBuffer.h"

namespace ospray {
  namespace sg {

    FrameBuffer::FrameBuffer(vec2i size)
    {
      createChild("size", "vec2i", size);
      createChild("displayWall", "string", std::string(""));

      // Tone mapping with default parameters set to ACES
      createChild("toneMapping", "bool", false);

      createChild("exposure", "float", 0.0f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(-8.f, 8.f);

      createChild("contrast", "float", 1.6773f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(1.f, 5.f);

      createChild("shoulder", "float", 0.9714f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(0.9f, 1.f);

      createChild("midIn", "float", 0.18f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(0.f, 1.f);

      createChild("midOut", "float", 0.18f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(0.f, 1.f);

      createChild("hdrMax", "float", 11.0785f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(1.f, 64.f);

      createChild("useVarianceBuffer", "bool", true);

      createFB();
    }

    void FrameBuffer::postCommit(RenderContext &)
    {
      // Avoid clearing the framebuffer when only tonemapping parameters have been changed
      if (lastModified() >= lastCommitted()
          || child("size").lastModified() >= lastCommitted()
          || child("displayWall").lastModified() >= lastCommitted()
          || child("useVarianceBuffer").lastModified() >= lastCommitted()
          || child("toneMapping").lastModified() >= lastCommitted())
      {
        std::string displayWall = child("displayWall").valueAs<std::string>();
        this->displayWallStream = displayWall;

        destroyFB();
        createFB();

        bool toneMapping = child("toneMapping").valueAs<bool>();
        if (toneMapping)
        {
          toneMapper = ospNewPixelOp("tonemapper");
          ospCommit(toneMapper);
          ospSetPixelOp(ospFrameBuffer, toneMapper);
        }
        else
        {
          toneMapper = nullptr;
        }

        if (displayWall != "") {
          ospLoadModule("displayWald");
          OSPPixelOp pixelOp = ospNewPixelOp("display_wald");
          ospSetString(pixelOp,"streamName", displayWall.c_str());
          ospCommit(pixelOp);
          ospSetPixelOp(ospFrameBuffer,pixelOp);
          std::cout << "-------------------------------------------------------"
                    << std::endl;
          std::cout << "this is the display wall framebuffer .. size is "
                    << size() << std::endl;
          std::cout << "added display wall pixel op ..." << std::endl;

          std::cout << "created display wall pixelop, and assigned to frame buffer!"
                  << std::endl;
        }

        ospCommit(ospFrameBuffer);
      }

      if (toneMapper)
      {
        float exposure = child("exposure").valueAs<float>();
        float linearExposure = exp2(exposure);
        ospSet1f(toneMapper, "exposure", linearExposure);

        ospSet1f(toneMapper, "contrast", child("contrast").valueAs<float>());
        ospSet1f(toneMapper, "shoulder", child("shoulder").valueAs<float>());
        ospSet1f(toneMapper, "midIn", child("midIn").valueAs<float>());
        ospSet1f(toneMapper, "midOut", child("midOut").valueAs<float>());
        ospSet1f(toneMapper, "hdrMax", child("hdrMax").valueAs<float>());

        ospCommit(toneMapper);
      }
    }

    const unsigned char *FrameBuffer::map()
    {
      return (const unsigned char *)ospMapFrameBuffer(ospFrameBuffer,
                                                      OSP_FB_COLOR);
    }

    void FrameBuffer::unmap(const void *mem)
    {
      ospUnmapFrameBuffer(mem,ospFrameBuffer);
    }

    void FrameBuffer::clear()
    {
      ospFrameBufferClear(ospFrameBuffer,OSP_FB_ACCUM|OSP_FB_COLOR);
    }

    void FrameBuffer::clearAccum()
    {
      ospFrameBufferClear(ospFrameBuffer,OSP_FB_ACCUM);
    }

    vec2i FrameBuffer::size() const
    {
      return child("size").valueAs<vec2i>();
    }

    /*! \brief returns a std::string with the c++ name of this class */
    std::string FrameBuffer::toString() const
    {
      return "ospray::sg::FrameBuffer";
    }

    OSPFrameBuffer FrameBuffer::handle() const
    {
      return ospFrameBuffer;
    }

    void ospray::sg::FrameBuffer::createFB()
    {
      auto fbsize = size();

      auto useVariance = child("useVarianceBuffer").valueAs<bool>();
      ospFrameBuffer = ospNewFrameBuffer((osp::vec2i&)fbsize,
                                         (displayWallStream=="")
                                         ? OSP_FB_SRGBA
                                         : OSP_FB_NONE,
                                         OSP_FB_COLOR | OSP_FB_ACCUM |
                                         (useVariance ? OSP_FB_VARIANCE : 0));
      clearAccum();
      setValue(ospFrameBuffer);
    }

    void ospray::sg::FrameBuffer::destroyFB()
    {
      ospRelease(ospFrameBuffer);
    }

    OSP_REGISTER_SG_NODE(FrameBuffer);

  } // ::ospray::sg
} // ::ospray
<commit_msg>modifying framebuffer defaults to use toneMapping to tune down overblown defaults with pathtracer<commit_after>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "FrameBuffer.h"

namespace ospray {
  namespace sg {

    FrameBuffer::FrameBuffer(vec2i size)
    {
      createChild("size", "vec2i", size);
      createChild("displayWall", "string", std::string(""));

      // Tone mapping with default parameters set to ACES
      createChild("toneMapping", "bool", true);

      createChild("exposure", "float", 0.0f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(-8.f, 8.f);

      createChild("contrast", "float", 1.4773f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(1.f, 5.f);

      createChild("shoulder", "float", 0.9714f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(0.9f, 1.f);

      createChild("midIn", "float", 0.468f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(0.f, 1.f);

      createChild("midOut", "float", 0.278f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(0.f, 1.f);

      createChild("hdrMax", "float", 1.5785f,
                    NodeFlags::required |
                    NodeFlags::valid_min_max |
                    NodeFlags::gui_slider).setMinMax(1.f, 64.f);

      createChild("useVarianceBuffer", "bool", true);

      createFB();
    }

    void FrameBuffer::postCommit(RenderContext &)
    {
      // Avoid clearing the framebuffer when only tonemapping parameters have been changed
      if (lastModified() >= lastCommitted()
          || child("size").lastModified() >= lastCommitted()
          || child("displayWall").lastModified() >= lastCommitted()
          || child("useVarianceBuffer").lastModified() >= lastCommitted()
          || child("toneMapping").lastModified() >= lastCommitted())
      {
        std::string displayWall = child("displayWall").valueAs<std::string>();
        this->displayWallStream = displayWall;

        destroyFB();
        createFB();

        bool toneMapping = child("toneMapping").valueAs<bool>();
        if (toneMapping)
        {
          toneMapper = ospNewPixelOp("tonemapper");
          ospCommit(toneMapper);
          ospSetPixelOp(ospFrameBuffer, toneMapper);
        }
        else
        {
          toneMapper = nullptr;
        }

        if (displayWall != "") {
          ospLoadModule("displayWald");
          OSPPixelOp pixelOp = ospNewPixelOp("display_wald");
          ospSetString(pixelOp,"streamName", displayWall.c_str());
          ospCommit(pixelOp);
          ospSetPixelOp(ospFrameBuffer,pixelOp);
          std::cout << "-------------------------------------------------------"
                    << std::endl;
          std::cout << "this is the display wall framebuffer .. size is "
                    << size() << std::endl;
          std::cout << "added display wall pixel op ..." << std::endl;

          std::cout << "created display wall pixelop, and assigned to frame buffer!"
                  << std::endl;
        }

        ospCommit(ospFrameBuffer);
      }

      if (toneMapper)
      {
        float exposure = child("exposure").valueAs<float>();
        float linearExposure = exp2(exposure);
        ospSet1f(toneMapper, "exposure", linearExposure);

        ospSet1f(toneMapper, "contrast", child("contrast").valueAs<float>());
        ospSet1f(toneMapper, "shoulder", child("shoulder").valueAs<float>());
        ospSet1f(toneMapper, "midIn", child("midIn").valueAs<float>());
        ospSet1f(toneMapper, "midOut", child("midOut").valueAs<float>());
        ospSet1f(toneMapper, "hdrMax", child("hdrMax").valueAs<float>());

        ospCommit(toneMapper);
      }
    }

    const unsigned char *FrameBuffer::map()
    {
      return (const unsigned char *)ospMapFrameBuffer(ospFrameBuffer,
                                                      OSP_FB_COLOR);
    }

    void FrameBuffer::unmap(const void *mem)
    {
      ospUnmapFrameBuffer(mem,ospFrameBuffer);
    }

    void FrameBuffer::clear()
    {
      ospFrameBufferClear(ospFrameBuffer,OSP_FB_ACCUM|OSP_FB_COLOR);
    }

    void FrameBuffer::clearAccum()
    {
      ospFrameBufferClear(ospFrameBuffer,OSP_FB_ACCUM);
    }

    vec2i FrameBuffer::size() const
    {
      return child("size").valueAs<vec2i>();
    }

    /*! \brief returns a std::string with the c++ name of this class */
    std::string FrameBuffer::toString() const
    {
      return "ospray::sg::FrameBuffer";
    }

    OSPFrameBuffer FrameBuffer::handle() const
    {
      return ospFrameBuffer;
    }

    void ospray::sg::FrameBuffer::createFB()
    {
      auto fbsize = size();

      auto useVariance = child("useVarianceBuffer").valueAs<bool>();
      ospFrameBuffer = ospNewFrameBuffer((osp::vec2i&)fbsize,
                                         (displayWallStream=="")
                                         ? OSP_FB_SRGBA
                                         : OSP_FB_NONE,
                                         OSP_FB_COLOR | OSP_FB_ACCUM |
                                         (useVariance ? OSP_FB_VARIANCE : 0));
      clearAccum();
      setValue(ospFrameBuffer);
    }

    void ospray::sg::FrameBuffer::destroyFB()
    {
      ospRelease(ospFrameBuffer);
    }

    OSP_REGISTER_SG_NODE(FrameBuffer);

  } // ::ospray::sg
} // ::ospray
<|endoftext|>


<commit_before>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty 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

// C++ includes
#include "libmesh_config.h"

#ifdef LIBMESH_HAVE_PETSC

// Local includes
#include "petsc_matrix.h"
#include "dof_map.h"
#include "dense_matrix.h"
#include "petsc_vector.h"

namespace libMesh
{

//-----------------------------------------------------------------------
// PetscMatrix members
template <typename T>
void PetscMatrix<T>::init (const unsigned int m,
			   const unsigned int n,
			   const unsigned int m_l,
			   const unsigned int n_l,
			   const unsigned int nnz,
			   const unsigned int noz)
{
  // We allow 0x0 matrices now
  //if ((m==0) || (n==0))
  //  return;

  // Clear initialized matrices
  if (this->initialized())
    this->clear();

  this->_is_initialized = true;

  int ierr     = 0;
  int m_global = static_cast<int>(m);
  int n_global = static_cast<int>(n);
  int m_local  = static_cast<int>(m_l);
  int n_local  = static_cast<int>(n_l);
  int n_nz     = static_cast<int>(nnz);
  int n_oz     = static_cast<int>(noz);

  // create a sequential matrix on one processor
  if (libMesh::n_processors() == 1)
    {
      libmesh_assert ((m_l == m) && (n_l == n));

      // Create matrix.  Revisit later to do preallocation and make more efficient
      ierr = MatCreateSeqAIJ (libMesh::COMM_WORLD, n_global, n_global,
			      n_nz, PETSC_NULL, &_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatSetFromOptions (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  else
    {
      parallel_only();

      ierr = MatCreateMPIAIJ (libMesh::COMM_WORLD, m_local, n_local, m_global, n_global,
			      n_nz, PETSC_NULL, n_oz, PETSC_NULL, &_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatSetFromOptions (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  this->zero ();
}

template <typename T>
void PetscMatrix<T>::init ()
{
  libmesh_assert (this->_dof_map != NULL);

  // Clear initialized matrices
  if (this->initialized())
    this->clear();

  this->_is_initialized = true;

  const unsigned int m   = this->_dof_map->n_dofs();
  const unsigned int n   = m;
  const unsigned int n_l = this->_dof_map->n_dofs_on_processor(libMesh::processor_id());
  const unsigned int m_l = n_l;

  const std::vector<unsigned int>& n_nz = this->_dof_map->get_n_nz();
  const std::vector<unsigned int>& n_oz = this->_dof_map->get_n_oz();

  // Make sure the sparsity pattern isn't empty unless the matrix is 0x0
  libmesh_assert (n_nz.size() == n_l);
  libmesh_assert (n_oz.size() == n_l);

  // We allow 0x0 matrices now
  //if (m==0)
  //  return;

  int ierr     = 0;
  int m_global = static_cast<int>(m);
  int n_global = static_cast<int>(n);
  int m_local  = static_cast<int>(m_l);
  int n_local  = static_cast<int>(n_l);

  // create a sequential matrix on one processor
  if (libMesh::n_processors() == 1)
    {
      libmesh_assert ((m_l == m) && (n_l == n));
      if (n_nz.empty())
        ierr = MatCreateSeqAIJ (libMesh::COMM_WORLD, n_global, n_global,
			        PETSC_NULL, (int*) PETSC_NULL, &_mat);
      else
        ierr = MatCreateSeqAIJ (libMesh::COMM_WORLD, n_global, n_global,
			        PETSC_NULL, (int*) &n_nz[0], &_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatSetFromOptions (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  else
    {
      parallel_only();

      if (n_nz.empty())
        ierr = MatCreateMPIAIJ (libMesh::COMM_WORLD,
			        m_local, n_local,
			        m_global, n_global,
			        PETSC_NULL, (int*) PETSC_NULL,
			        PETSC_NULL, (int*) PETSC_NULL, &_mat);
      else
        ierr = MatCreateMPIAIJ (libMesh::COMM_WORLD,
			        m_local, n_local,
			        m_global, n_global,
			        PETSC_NULL, (int*) &n_nz[0],
			        PETSC_NULL, (int*) &n_oz[0], &_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatSetFromOptions (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  this->zero();
}

template <typename T>
void PetscMatrix<T>::zero ()
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  int ierr=0;

  ierr = MatZeroEntries(_mat);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::zero_rows (std::vector<int> & rows, T diag_value)
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  int ierr=0;

  if(!rows.empty())
    ierr = MatZeroRows(_mat, rows.size(), &rows[0], diag_value);
  else
    ierr = MatZeroRows(_mat, 0, PETSC_NULL, diag_value);

  CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::clear ()
{
  int ierr=0;

  if ((this->initialized()) && (this->_destroy_mat_on_exit))
    {
      semiparallel_only();

      ierr = MatDestroy (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      this->_is_initialized = false;
    }
}

template <typename T>
Real PetscMatrix<T>::l1_norm () const
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  int ierr=0;
  PetscReal petsc_value;
  Real value;

  libmesh_assert (this->closed());

  ierr = MatNorm(_mat, NORM_1, &petsc_value);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  value = static_cast<Real>(petsc_value);

  return value;
}

template <typename T>
Real PetscMatrix<T>::linfty_norm () const
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  int ierr=0;
  PetscReal petsc_value;
  Real value;

  libmesh_assert (this->closed());

  ierr = MatNorm(_mat, NORM_INFINITY, &petsc_value);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  value = static_cast<Real>(petsc_value);

  return value;
}

template <typename T>
void PetscMatrix<T>::print_matlab (const std::string name) const
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  // libmesh_assert (this->closed());
  this->close();

  int ierr=0;
  PetscViewer petsc_viewer;

  ierr = PetscViewerCreate (libMesh::COMM_WORLD,
			    &petsc_viewer);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  /**
   * Create an ASCII file containing the matrix
   * if a filename was provided.
   */
  if (name != "NULL")
    {
      ierr = PetscViewerASCIIOpen( libMesh::COMM_WORLD,
				   name.c_str(),
				   &petsc_viewer);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = PetscViewerSetFormat (petsc_viewer,
				   PETSC_VIEWER_ASCII_MATLAB);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatView (_mat, petsc_viewer);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  /**
   * Otherwise the matrix will be dumped to the screen.
   */
  else
    {
      ierr = PetscViewerSetFormat (PETSC_VIEWER_STDOUT_WORLD,
				   PETSC_VIEWER_ASCII_MATLAB);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatView (_mat, PETSC_VIEWER_STDOUT_WORLD);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  /**
   * Destroy the viewer.
   */
  ierr = PetscViewerDestroy (petsc_viewer);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::add_matrix(const DenseMatrix<T>& dm,
				const std::vector<unsigned int>& rows,
				const std::vector<unsigned int>& cols)
{
  libmesh_assert (this->initialized());

  const unsigned int m = dm.m();
  const unsigned int n = dm.n();

  libmesh_assert (rows.size() == m);
  libmesh_assert (cols.size() == n);

  int ierr=0;

  // These casts are required for PETSc <= 2.1.5
  ierr = MatSetValues(_mat,
		      m, (int*) &rows[0],
		      n, (int*) &cols[0],
		      (PetscScalar*) &dm.get_values()[0],
		      ADD_VALUES);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::_get_submatrix(SparseMatrix<T>& submatrix,
				    const std::vector<unsigned int> &rows,
				    const std::vector<unsigned int> &cols,
				    const bool reuse_submatrix) const
{
  // Can only extract submatrices from closed matrices
  this->close();

  // Make sure the SparseMatrix passed in is really a PetscMatrix
  PetscMatrix<T>* petsc_submatrix = libmesh_cast_ptr<PetscMatrix<T>*>(&submatrix);

  // If we're not reusing submatrix and submatrix is already initialized
  // then we need to clear it, otherwise we get a memory leak.
  if( !reuse_submatrix && submatrix.initialized() )
    submatrix.clear();

  // Construct row and column index sets.
  int ierr=0;
  IS isrow, iscol;

  ierr = ISCreateGeneral(libMesh::COMM_WORLD,
			 rows.size(),
			 (int*) &rows[0],
			 &isrow); CHKERRABORT(libMesh::COMM_WORLD,ierr);

  ierr = ISCreateGeneral(libMesh::COMM_WORLD,
			 cols.size(),
			 (int*) &cols[0],
			 &iscol); CHKERRABORT(libMesh::COMM_WORLD,ierr);

  // Extract submatrix
#if !PETSC_VERSION_LESS_THAN(3,0,1) || !PETSC_VERSION_RELEASE
  ierr = MatGetSubMatrix(_mat,
			 isrow,
			 iscol,
			 (reuse_submatrix ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX),
			 &(petsc_submatrix->_mat));  CHKERRABORT(libMesh::COMM_WORLD,ierr);
#else
  ierr = MatGetSubMatrix(_mat,
			 isrow,
			 iscol,
			 PETSC_DECIDE,
			 (reuse_submatrix ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX),
			 &(petsc_submatrix->_mat));  CHKERRABORT(libMesh::COMM_WORLD,ierr);
#endif

  // Specify that the new submatrix is initialized and close it.
  petsc_submatrix->_is_initialized = true;
  petsc_submatrix->close();

  // Clean up PETSc data structures
  ierr = ISDestroy(isrow); CHKERRABORT(libMesh::COMM_WORLD,ierr);
  ierr = ISDestroy(iscol); CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::get_diagonal (NumericVector<T>& dest) const
{
  // Make sure the NumericVector passed in is really a PetscVector
  PetscVector<T>& petsc_dest = libmesh_cast_ref<PetscVector<T>&>(dest);

  // Call PETSc function.

#if PETSC_VERSION_LESS_THAN(2,3,1)

  libMesh::out << "This method has been developed with PETSc 2.3.1.  "
	        << "No one has made it backwards compatible with older "
	        << "versions of PETSc so far; however, it might work "
	        << "without any change with some older version." << std::endl;
  libmesh_error();

#else

  // Needs a const_cast since PETSc does not work with const.
  int ierr =
    MatGetDiagonal(const_cast<PetscMatrix<T>*>(this)->mat(),petsc_dest.vec()); CHKERRABORT(libMesh::COMM_WORLD,ierr);

#endif

}

template <typename T>
void PetscMatrix<T>::get_transpose (SparseMatrix<T>& dest) const
{
  // Make sure the SparseMatrix passed in is really a PetscMatrix
  PetscMatrix<T>& petsc_dest = libmesh_cast_ref<PetscMatrix<T>&>(dest);

  // If we aren't reusing the matrix then need to clear dest,
  // otherwise we get a memory leak
  if(&petsc_dest != this)
    dest.clear();

  int ierr;
#if PETSC_VERSION_LESS_THAN(3,0,0)
  if (&petsc_dest == this)
    ierr = MatTranspose(_mat,PETSC_NULL);
  else
    ierr = MatTranspose(_mat,&petsc_dest._mat);
  CHKERRABORT(libMesh::COMM_WORLD,ierr);
#else
  // FIXME - we can probably use MAT_REUSE_MATRIX in more situations
  if (&petsc_dest == this)
    ierr = MatTranspose(_mat,MAT_REUSE_MATRIX,&petsc_dest._mat);
  else
    ierr = MatTranspose(_mat,MAT_INITIAL_MATRIX,&petsc_dest._mat);
  CHKERRABORT(libMesh::COMM_WORLD,ierr);
#endif

  // Specify that the transposed matrix is initialized and close it.
  petsc_dest._is_initialized = true;
  petsc_dest.close();
}

//------------------------------------------------------------------
// Explicit instantiations
template class PetscMatrix<Number>;

} // namespace libMesh

#endif // #ifdef LIBMESH_HAVE_PETSC
<commit_msg>Fixed long-standing bug where rectangular sequential matrices could apparently not be created.<commit_after>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty 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

// C++ includes
#include "libmesh_config.h"

#ifdef LIBMESH_HAVE_PETSC

// Local includes
#include "petsc_matrix.h"
#include "dof_map.h"
#include "dense_matrix.h"
#include "petsc_vector.h"

namespace libMesh
{

//-----------------------------------------------------------------------
// PetscMatrix members
template <typename T>
void PetscMatrix<T>::init (const unsigned int m,
			   const unsigned int n,
			   const unsigned int m_l,
			   const unsigned int n_l,
			   const unsigned int nnz,
			   const unsigned int noz)
{
  // We allow 0x0 matrices now
  //if ((m==0) || (n==0))
  //  return;

  // Clear initialized matrices
  if (this->initialized())
    this->clear();

  this->_is_initialized = true;

  int ierr     = 0;
  int m_global = static_cast<int>(m);
  int n_global = static_cast<int>(n);
  int m_local  = static_cast<int>(m_l);
  int n_local  = static_cast<int>(n_l);
  int n_nz     = static_cast<int>(nnz);
  int n_oz     = static_cast<int>(noz);

  // create a sequential matrix on one processor
  if (libMesh::n_processors() == 1)
    {
      libmesh_assert ((m_l == m) && (n_l == n));

      // Create matrix.  Revisit later to do preallocation and make more efficient
      ierr = MatCreateSeqAIJ (libMesh::COMM_WORLD, m_global, n_global,
			      n_nz, PETSC_NULL, &_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatSetFromOptions (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  else
    {
      parallel_only();

      ierr = MatCreateMPIAIJ (libMesh::COMM_WORLD, m_local, n_local, m_global, n_global,
			      n_nz, PETSC_NULL, n_oz, PETSC_NULL, &_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatSetFromOptions (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  this->zero ();
}

template <typename T>
void PetscMatrix<T>::init ()
{
  libmesh_assert (this->_dof_map != NULL);

  // Clear initialized matrices
  if (this->initialized())
    this->clear();

  this->_is_initialized = true;

  const unsigned int m   = this->_dof_map->n_dofs();
  const unsigned int n   = m;
  const unsigned int n_l = this->_dof_map->n_dofs_on_processor(libMesh::processor_id());
  const unsigned int m_l = n_l;

  const std::vector<unsigned int>& n_nz = this->_dof_map->get_n_nz();
  const std::vector<unsigned int>& n_oz = this->_dof_map->get_n_oz();

  // Make sure the sparsity pattern isn't empty unless the matrix is 0x0
  libmesh_assert (n_nz.size() == n_l);
  libmesh_assert (n_oz.size() == n_l);

  // We allow 0x0 matrices now
  //if (m==0)
  //  return;

  int ierr     = 0;
  int m_global = static_cast<int>(m);
  int n_global = static_cast<int>(n);
  int m_local  = static_cast<int>(m_l);
  int n_local  = static_cast<int>(n_l);

  // create a sequential matrix on one processor
  if (libMesh::n_processors() == 1)
    {
      libmesh_assert ((m_l == m) && (n_l == n));
      if (n_nz.empty())
        ierr = MatCreateSeqAIJ (libMesh::COMM_WORLD, n_global, n_global,
			        PETSC_NULL, (int*) PETSC_NULL, &_mat);
      else
        ierr = MatCreateSeqAIJ (libMesh::COMM_WORLD, n_global, n_global,
			        PETSC_NULL, (int*) &n_nz[0], &_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatSetFromOptions (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  else
    {
      parallel_only();

      if (n_nz.empty())
        ierr = MatCreateMPIAIJ (libMesh::COMM_WORLD,
			        m_local, n_local,
			        m_global, n_global,
			        PETSC_NULL, (int*) PETSC_NULL,
			        PETSC_NULL, (int*) PETSC_NULL, &_mat);
      else
        ierr = MatCreateMPIAIJ (libMesh::COMM_WORLD,
			        m_local, n_local,
			        m_global, n_global,
			        PETSC_NULL, (int*) &n_nz[0],
			        PETSC_NULL, (int*) &n_oz[0], &_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatSetFromOptions (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  this->zero();
}

template <typename T>
void PetscMatrix<T>::zero ()
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  int ierr=0;

  ierr = MatZeroEntries(_mat);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::zero_rows (std::vector<int> & rows, T diag_value)
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  int ierr=0;

  if(!rows.empty())
    ierr = MatZeroRows(_mat, rows.size(), &rows[0], diag_value);
  else
    ierr = MatZeroRows(_mat, 0, PETSC_NULL, diag_value);

  CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::clear ()
{
  int ierr=0;

  if ((this->initialized()) && (this->_destroy_mat_on_exit))
    {
      semiparallel_only();

      ierr = MatDestroy (_mat);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      this->_is_initialized = false;
    }
}

template <typename T>
Real PetscMatrix<T>::l1_norm () const
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  int ierr=0;
  PetscReal petsc_value;
  Real value;

  libmesh_assert (this->closed());

  ierr = MatNorm(_mat, NORM_1, &petsc_value);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  value = static_cast<Real>(petsc_value);

  return value;
}

template <typename T>
Real PetscMatrix<T>::linfty_norm () const
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  int ierr=0;
  PetscReal petsc_value;
  Real value;

  libmesh_assert (this->closed());

  ierr = MatNorm(_mat, NORM_INFINITY, &petsc_value);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  value = static_cast<Real>(petsc_value);

  return value;
}

template <typename T>
void PetscMatrix<T>::print_matlab (const std::string name) const
{
  libmesh_assert (this->initialized());

  semiparallel_only();

  // libmesh_assert (this->closed());
  this->close();

  int ierr=0;
  PetscViewer petsc_viewer;

  ierr = PetscViewerCreate (libMesh::COMM_WORLD,
			    &petsc_viewer);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  /**
   * Create an ASCII file containing the matrix
   * if a filename was provided.
   */
  if (name != "NULL")
    {
      ierr = PetscViewerASCIIOpen( libMesh::COMM_WORLD,
				   name.c_str(),
				   &petsc_viewer);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = PetscViewerSetFormat (petsc_viewer,
				   PETSC_VIEWER_ASCII_MATLAB);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatView (_mat, petsc_viewer);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  /**
   * Otherwise the matrix will be dumped to the screen.
   */
  else
    {
      ierr = PetscViewerSetFormat (PETSC_VIEWER_STDOUT_WORLD,
				   PETSC_VIEWER_ASCII_MATLAB);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);

      ierr = MatView (_mat, PETSC_VIEWER_STDOUT_WORLD);
             CHKERRABORT(libMesh::COMM_WORLD,ierr);
    }

  /**
   * Destroy the viewer.
   */
  ierr = PetscViewerDestroy (petsc_viewer);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::add_matrix(const DenseMatrix<T>& dm,
				const std::vector<unsigned int>& rows,
				const std::vector<unsigned int>& cols)
{
  libmesh_assert (this->initialized());

  const unsigned int m = dm.m();
  const unsigned int n = dm.n();

  libmesh_assert (rows.size() == m);
  libmesh_assert (cols.size() == n);

  int ierr=0;

  // These casts are required for PETSc <= 2.1.5
  ierr = MatSetValues(_mat,
		      m, (int*) &rows[0],
		      n, (int*) &cols[0],
		      (PetscScalar*) &dm.get_values()[0],
		      ADD_VALUES);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::_get_submatrix(SparseMatrix<T>& submatrix,
				    const std::vector<unsigned int> &rows,
				    const std::vector<unsigned int> &cols,
				    const bool reuse_submatrix) const
{
  // Can only extract submatrices from closed matrices
  this->close();

  // Make sure the SparseMatrix passed in is really a PetscMatrix
  PetscMatrix<T>* petsc_submatrix = libmesh_cast_ptr<PetscMatrix<T>*>(&submatrix);

  // If we're not reusing submatrix and submatrix is already initialized
  // then we need to clear it, otherwise we get a memory leak.
  if( !reuse_submatrix && submatrix.initialized() )
    submatrix.clear();

  // Construct row and column index sets.
  int ierr=0;
  IS isrow, iscol;

  ierr = ISCreateGeneral(libMesh::COMM_WORLD,
			 rows.size(),
			 (int*) &rows[0],
			 &isrow); CHKERRABORT(libMesh::COMM_WORLD,ierr);

  ierr = ISCreateGeneral(libMesh::COMM_WORLD,
			 cols.size(),
			 (int*) &cols[0],
			 &iscol); CHKERRABORT(libMesh::COMM_WORLD,ierr);

  // Extract submatrix
#if !PETSC_VERSION_LESS_THAN(3,0,1) || !PETSC_VERSION_RELEASE
  ierr = MatGetSubMatrix(_mat,
			 isrow,
			 iscol,
			 (reuse_submatrix ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX),
			 &(petsc_submatrix->_mat));  CHKERRABORT(libMesh::COMM_WORLD,ierr);
#else
  ierr = MatGetSubMatrix(_mat,
			 isrow,
			 iscol,
			 PETSC_DECIDE,
			 (reuse_submatrix ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX),
			 &(petsc_submatrix->_mat));  CHKERRABORT(libMesh::COMM_WORLD,ierr);
#endif

  // Specify that the new submatrix is initialized and close it.
  petsc_submatrix->_is_initialized = true;
  petsc_submatrix->close();

  // Clean up PETSc data structures
  ierr = ISDestroy(isrow); CHKERRABORT(libMesh::COMM_WORLD,ierr);
  ierr = ISDestroy(iscol); CHKERRABORT(libMesh::COMM_WORLD,ierr);
}

template <typename T>
void PetscMatrix<T>::get_diagonal (NumericVector<T>& dest) const
{
  // Make sure the NumericVector passed in is really a PetscVector
  PetscVector<T>& petsc_dest = libmesh_cast_ref<PetscVector<T>&>(dest);

  // Call PETSc function.

#if PETSC_VERSION_LESS_THAN(2,3,1)

  libMesh::out << "This method has been developed with PETSc 2.3.1.  "
	        << "No one has made it backwards compatible with older "
	        << "versions of PETSc so far; however, it might work "
	        << "without any change with some older version." << std::endl;
  libmesh_error();

#else

  // Needs a const_cast since PETSc does not work with const.
  int ierr =
    MatGetDiagonal(const_cast<PetscMatrix<T>*>(this)->mat(),petsc_dest.vec()); CHKERRABORT(libMesh::COMM_WORLD,ierr);

#endif

}

template <typename T>
void PetscMatrix<T>::get_transpose (SparseMatrix<T>& dest) const
{
  // Make sure the SparseMatrix passed in is really a PetscMatrix
  PetscMatrix<T>& petsc_dest = libmesh_cast_ref<PetscMatrix<T>&>(dest);

  // If we aren't reusing the matrix then need to clear dest,
  // otherwise we get a memory leak
  if(&petsc_dest != this)
    dest.clear();

  int ierr;
#if PETSC_VERSION_LESS_THAN(3,0,0)
  if (&petsc_dest == this)
    ierr = MatTranspose(_mat,PETSC_NULL);
  else
    ierr = MatTranspose(_mat,&petsc_dest._mat);
  CHKERRABORT(libMesh::COMM_WORLD,ierr);
#else
  // FIXME - we can probably use MAT_REUSE_MATRIX in more situations
  if (&petsc_dest == this)
    ierr = MatTranspose(_mat,MAT_REUSE_MATRIX,&petsc_dest._mat);
  else
    ierr = MatTranspose(_mat,MAT_INITIAL_MATRIX,&petsc_dest._mat);
  CHKERRABORT(libMesh::COMM_WORLD,ierr);
#endif

  // Specify that the transposed matrix is initialized and close it.
  petsc_dest._is_initialized = true;
  petsc_dest.close();
}

//------------------------------------------------------------------
// Explicit instantiations
template class PetscMatrix<Number>;

} // namespace libMesh

#endif // #ifdef LIBMESH_HAVE_PETSC
<|endoftext|>


<commit_before>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include "CompressorRGBE.h"
#include "CompressionOptions.h"
#include "OutputOptions.h"

#include <nvimage/Image.h>
#include <nvimage/FloatImage.h>

#include <nvmath/Color.h>

#include <nvcore/Debug.h>

using namespace nv;
using namespace nvtt;

static Color32 toRgbe8(float r, float g, float b)
{
    Color32 c;
    float v = max(max(r, g), b);
    if (v < 1e-32) {
        c.r = c.g = c.b = c.a = 0;
    }
    else {
        int e;
        v = frexp(v, &e) * 256.0f / v;
        c.r = uint8(clamp(r * v, 0.0f, 255.0f));
        c.g = uint8(clamp(g * v, 0.0f, 255.0f));
        c.b = uint8(clamp(b * v, 0.0f, 255.0f));
        c.a = e + 128;
    }

    return c;
}

void CompressorRGBE::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{
    nvDebugCheck (compressionOptions.format == nvtt::Format_RGBE);

    uint srcPitch = w;
    uint srcPlane = w * h;

    // Allocate output scanline.
	Color32 * dst = (Color32 *)mem::malloc(w);

	for (uint y = 0; y < h; y++)
	{
        const uint * src = (const uint *)data + y * srcPitch;
        const float * fsrc = (const float *)data + y * srcPitch;

		for (uint x = 0; x < w; x++)
		{
            float r, g, b;

            if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
                Color32 c = Color32(src[x]);
                r = float(c.r) / 255.0f;
                g = float(c.g) / 255.0f;
                b = float(c.b) / 255.0f;
            }
            else {
                nvDebugCheck (inputFormat == nvtt::InputFormat_RGBA_32F);

#pragma message("Interleave color components")

			    // Color components not interleaved.
			    r = fsrc[x + 0 * srcPlane];
			    g = fsrc[x + 1 * srcPlane];
			    b = fsrc[x + 2 * srcPlane];
            }

            dst[x] = toRgbe8(r, g, b);
        }

		if (outputOptions.outputHandler != NULL)
		{
			outputOptions.outputHandler->writeData(dst, w * 4);
		}
    }

	mem::free(dst);
}
<commit_msg>fix comment.<commit_after>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include "CompressorRGBE.h"
#include "CompressionOptions.h"
#include "OutputOptions.h"

#include <nvimage/Image.h>
#include <nvimage/FloatImage.h>

#include <nvmath/Color.h>

#include <nvcore/Debug.h>

using namespace nv;
using namespace nvtt;

static Color32 toRgbe8(float r, float g, float b)
{
    Color32 c;
    float v = max(max(r, g), b);
    if (v < 1e-32) {
        c.r = c.g = c.b = c.a = 0;
    }
    else {
        int e;
        v = frexp(v, &e) * 256.0f / v;
        c.r = uint8(clamp(r * v, 0.0f, 255.0f));
        c.g = uint8(clamp(g * v, 0.0f, 255.0f));
        c.b = uint8(clamp(b * v, 0.0f, 255.0f));
        c.a = e + 128;
    }

    return c;
}

void CompressorRGBE::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{
    nvDebugCheck (compressionOptions.format == nvtt::Format_RGBE);

    uint srcPitch = w;
    uint srcPlane = w * h;

    // Allocate output scanline.
	Color32 * dst = (Color32 *)mem::malloc(w);

	for (uint y = 0; y < h; y++)
	{
        const uint * src = (const uint *)data + y * srcPitch;
        const float * fsrc = (const float *)data + y * srcPitch;

		for (uint x = 0; x < w; x++)
		{
            float r, g, b;

            if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
                Color32 c = Color32(src[x]);
                r = float(c.r) / 255.0f;
                g = float(c.g) / 255.0f;
                b = float(c.b) / 255.0f;
            }
            else {
                nvDebugCheck (inputFormat == nvtt::InputFormat_RGBA_32F);

#pragma message(NV_FILE_LINE "TODO: Interleave color components")

			    // Color components not interleaved.
			    r = fsrc[x + 0 * srcPlane];
			    g = fsrc[x + 1 * srcPlane];
			    b = fsrc[x + 2 * srcPlane];
            }

            dst[x] = toRgbe8(r, g, b);
        }

		if (outputOptions.outputHandler != NULL)
		{
			outputOptions.outputHandler->writeData(dst, w * 4);
		}
    }

	mem::free(dst);
}
<|endoftext|>


<commit_before>#ifndef st_sorter_threaded_hpp
#define st_sorter_threaded_hpp

#include <string>
#include <vector>

class SorterThreaded {
  public:
    SorterThreaded(int taskFactor=8, int numThreads=-1);
    void sort(std::vector<double>::iterator begin,
              std::vector<double>::iterator end);
    void setTaskFactor(size_t taskFactor);
    void setNumThreads(size_t numThreads);
  private:
    int taskFactor_;
    // If numThreads_ == -1 then omp_max_num_threads will be used
    int numThreads_;
};

  // We need to break the input vector into nearly equal size chunks
  // for partitioning.  One chunk for each thread.
  //
  // We can builid up a Partition from an array of non-repeating
  // values (pivots) from the input vector.
  //
  // Each thread will have and make its own Partition.  These will be
  // OpenMP private.  Each partition has a stack for each thread and
  // each task.  This implies that the total number of stacks over all
  // threads is numThreads^3 * taskFactor_.
  //
  // The threads will be managed by the PartitionGang.  This class
  // will hold all of the Partitions and will be the class to
  // spawn threads.
  //

#endif
<commit_msg>numThreads_ -> maxThreads_<commit_after>#ifndef st_sorter_threaded_hpp
#define st_sorter_threaded_hpp

#include <string>
#include <vector>

class SorterThreaded {
  public:
    SorterThreaded(int taskFactor=8, int numThreads=-1);
    void sort(std::vector<double>::iterator begin,
              std::vector<double>::iterator end);
    void setTaskFactor(size_t taskFactor);
    void setNumThreads(size_t numThreads);
  private:
    int taskFactor_;
    // If numThreads_ == -1 then omp_max_num_threads will be used
    int maxThreads_;
};

  // We need to break the input vector into nearly equal size chunks
  // for partitioning.  One chunk for each thread.
  //
  // We can builid up a Partition from an array of non-repeating
  // values (pivots) from the input vector.
  //
  // Each thread will have and make its own Partition.  These will be
  // OpenMP private.  Each partition has a stack for each thread and
  // each task.  This implies that the total number of stacks over all
  // threads is numThreads^3 * taskFactor_.
  //
  // The threads will be managed by the PartitionGang.  This class
  // will hold all of the Partitions and will be the class to
  // spawn threads.
  //

#endif
<|endoftext|>


<commit_before>//===-- ThreadPlanStepRange.cpp ---------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/ThreadPlanStepRange.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes

#include "lldb/lldb-private-log.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Thread.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// ThreadPlanStepRange: Step through a stack range, either stepping over or into
// based on the value of \a type.
//----------------------------------------------------------------------

ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, const char *name, Thread &thread, const AddressRange &range, const SymbolContext &addr_context, lldb::RunMode stop_others) :
    ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
    m_addr_context (addr_context),
    m_address_range (range),
    m_stop_others (stop_others),
    m_stack_depth (0),
    m_stack_id (),
    m_no_more_plans (false),
    m_first_run_event (true)
{
    m_stack_depth = m_thread.GetStackFrameCount();
    m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
}

ThreadPlanStepRange::~ThreadPlanStepRange ()
{
}

bool
ThreadPlanStepRange::ValidatePlan (Stream *error)
{
    return true;
}

bool
ThreadPlanStepRange::PlanExplainsStop ()
{
    // We don't explain signals or breakpoints (breakpoints that handle stepping in or
    // out will be handled by a child plan.
    StopInfoSP stop_info_sp = GetPrivateStopReason();
    if (stop_info_sp)
    {
        StopReason reason = stop_info_sp->GetStopReason();

        switch (reason)
        {
        case eStopReasonBreakpoint:
        case eStopReasonWatchpoint:
        case eStopReasonSignal:
        case eStopReasonException:
            return false;
        default:
            return true;
        }
    }
    return true;
}

Vote
ThreadPlanStepRange::ShouldReportStop (Event *event_ptr)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
    if (log)
        log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote);
    return vote;
}

bool
ThreadPlanStepRange::InRange ()
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    bool ret_value = false;

    lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();

    ret_value = m_address_range.ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess().GetTarget());

    if (!ret_value)
    {
        // See if we've just stepped to another part of the same line number...
        StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();

        SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything));
        if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid())
        {
           if ((m_addr_context.line_entry.file == new_context.line_entry.file)
               && (m_addr_context.line_entry.line == new_context.line_entry.line))
            {
                m_addr_context = new_context;
                m_address_range = m_addr_context.line_entry.range;
                ret_value = true;
                if (log)
                {
                    StreamString s;
                    m_address_range.Dump (&s, &m_thread.GetProcess().GetTarget(), Address::DumpStyleLoadAddress);

                    log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData());
                }
            }
        }

    }

    if (!ret_value && log)
        log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr);

    return ret_value;
}

bool
ThreadPlanStepRange::InSymbol()
{
    lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
    if (m_addr_context.function != NULL)
    {
        return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget());
    }
    else if (m_addr_context.symbol != NULL)
    {
        return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget());
    }
    return false;
}

// FIXME: This should also handle inlining if we aren't going to do inlining in the
// main stack.
//
// Ideally we should remember the whole stack frame list, and then compare that
// to the current list.

bool
ThreadPlanStepRange::FrameIsYounger ()
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    // FIXME: Might be better to do this by storing the FrameID we started in and seeing if that is still above
    // us on the stack.  Counting the whole stack could be expensive.

    uint32_t current_depth = m_thread.GetStackFrameCount();
    if (current_depth == m_stack_depth)
    {
        if (log)
            log->Printf ("Step range FrameIsYounger still in start function.");
        return false;
    }
    else if (current_depth < m_stack_depth)
    {
        if (log)
            log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
        return false;
    }
    else
    {
        if (log)
            log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
        return true;
    }
}

bool
ThreadPlanStepRange::FrameIsOlder ()
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    uint32_t current_depth = m_thread.GetStackFrameCount();
    if (current_depth == m_stack_depth)
    {
        if (log)
            log->Printf ("Step range FrameIsOlder still in start function.");
        return false;
    }
    else if (current_depth < m_stack_depth)
    {
        if (log)
            log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
        return true;
    }
    else
    {
        if (log)
            log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
        return false;
    }
}

bool
ThreadPlanStepRange::StopOthers ()
{
    if (m_stop_others == lldb::eOnlyThisThread
        || m_stop_others == lldb::eOnlyDuringStepping)
        return true;
    else
        return false;
}

bool
ThreadPlanStepRange::WillStop ()
{
    return true;
}

StateType
ThreadPlanStepRange::GetPlanRunState ()
{
    return eStateStepping;
}

bool
ThreadPlanStepRange::MischiefManaged ()
{
    bool done = true;
    if (!IsPlanComplete())
    {
        if (InRange())
        {
            done = false;
        }
        else if (!FrameIsOlder())
        {
            if (m_no_more_plans)
                done = true;
            else
                done = false;
        }
        else
            done = true;
    }

    if (done)
    {
        LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
        if (log)
            log->Printf("Completed step through range plan.");
        ThreadPlan::MischiefManaged ();
        return true;
    }
    else
    {
        return false;
    }

}
<commit_msg>Formatting.<commit_after>//===-- ThreadPlanStepRange.cpp ---------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/ThreadPlanStepRange.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes

#include "lldb/lldb-private-log.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Thread.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// ThreadPlanStepRange: Step through a stack range, either stepping over or into
// based on the value of \a type.
//----------------------------------------------------------------------

ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind,
                                          const char *name,
                                          Thread &thread,
                                          const AddressRange &range,
                                          const SymbolContext &addr_context,
                                          lldb::RunMode stop_others) :
    ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
    m_addr_context (addr_context),
    m_address_range (range),
    m_stop_others (stop_others),
    m_stack_depth (0),
    m_stack_id (),
    m_no_more_plans (false),
    m_first_run_event (true)
{
    m_stack_depth = m_thread.GetStackFrameCount();
    m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
}

ThreadPlanStepRange::~ThreadPlanStepRange ()
{
}

bool
ThreadPlanStepRange::ValidatePlan (Stream *error)
{
    return true;
}

bool
ThreadPlanStepRange::PlanExplainsStop ()
{
    // We don't explain signals or breakpoints (breakpoints that handle stepping in or
    // out will be handled by a child plan.
    StopInfoSP stop_info_sp = GetPrivateStopReason();
    if (stop_info_sp)
    {
        StopReason reason = stop_info_sp->GetStopReason();

        switch (reason)
        {
        case eStopReasonBreakpoint:
        case eStopReasonWatchpoint:
        case eStopReasonSignal:
        case eStopReasonException:
            return false;
        default:
            return true;
        }
    }
    return true;
}

Vote
ThreadPlanStepRange::ShouldReportStop (Event *event_ptr)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
    if (log)
        log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote);
    return vote;
}

bool
ThreadPlanStepRange::InRange ()
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    bool ret_value = false;

    lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();

    ret_value = m_address_range.ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess().GetTarget());

    if (!ret_value)
    {
        // See if we've just stepped to another part of the same line number...
        StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();

        SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything));
        if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid())
        {
           if ((m_addr_context.line_entry.file == new_context.line_entry.file)
               && (m_addr_context.line_entry.line == new_context.line_entry.line))
            {
                m_addr_context = new_context;
                m_address_range = m_addr_context.line_entry.range;
                ret_value = true;
                if (log)
                {
                    StreamString s;
                    m_address_range.Dump (&s, &m_thread.GetProcess().GetTarget(), Address::DumpStyleLoadAddress);

                    log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData());
                }
            }
        }

    }

    if (!ret_value && log)
        log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr);

    return ret_value;
}

bool
ThreadPlanStepRange::InSymbol()
{
    lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
    if (m_addr_context.function != NULL)
    {
        return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget());
    }
    else if (m_addr_context.symbol != NULL)
    {
        return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget());
    }
    return false;
}

// FIXME: This should also handle inlining if we aren't going to do inlining in the
// main stack.
//
// Ideally we should remember the whole stack frame list, and then compare that
// to the current list.

bool
ThreadPlanStepRange::FrameIsYounger ()
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    // FIXME: Might be better to do this by storing the FrameID we started in and seeing if that is still above
    // us on the stack.  Counting the whole stack could be expensive.

    uint32_t current_depth = m_thread.GetStackFrameCount();
    if (current_depth == m_stack_depth)
    {
        if (log)
            log->Printf ("Step range FrameIsYounger still in start function.");
        return false;
    }
    else if (current_depth < m_stack_depth)
    {
        if (log)
            log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
        return false;
    }
    else
    {
        if (log)
            log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
        return true;
    }
}

bool
ThreadPlanStepRange::FrameIsOlder ()
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    uint32_t current_depth = m_thread.GetStackFrameCount();
    if (current_depth == m_stack_depth)
    {
        if (log)
            log->Printf ("Step range FrameIsOlder still in start function.");
        return false;
    }
    else if (current_depth < m_stack_depth)
    {
        if (log)
            log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth);
        return true;
    }
    else
    {
        if (log)
            log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth);
        return false;
    }
}

bool
ThreadPlanStepRange::StopOthers ()
{
    if (m_stop_others == lldb::eOnlyThisThread
        || m_stop_others == lldb::eOnlyDuringStepping)
        return true;
    else
        return false;
}

bool
ThreadPlanStepRange::WillStop ()
{
    return true;
}

StateType
ThreadPlanStepRange::GetPlanRunState ()
{
    return eStateStepping;
}

bool
ThreadPlanStepRange::MischiefManaged ()
{
    bool done = true;
    if (!IsPlanComplete())
    {
        if (InRange())
        {
            done = false;
        }
        else if (!FrameIsOlder())
        {
            if (m_no_more_plans)
                done = true;
            else
                done = false;
        }
        else
            done = true;
    }

    if (done)
    {
        LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
        if (log)
            log->Printf("Completed step through range plan.");
        ThreadPlan::MischiefManaged ();
        return true;
    }
    else
    {
        return false;
    }

}
<|endoftext|>