<commit_before>/*
 * LogConsole.cpp
 *
 * Copyright (C) 2019 by Universitaet Stuttgart (VIS).
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "LogConsole.h"

using namespace megamol;
using namespace megamol::gui;

int megamol::gui::LogBuffer::sync(void) {
    try {
        auto message_str = this->str();
        if (!message_str.empty()) {
            // Split message string
            auto split_index = message_str.find("\n");
            while (split_index != std::string::npos) {
                // Assuming new line of log message of format "<level>|<message>\r\n"
                auto new_message = message_str.substr(0, split_index + 1);
                unsigned int log_level = megamol::core::utility::log::Log::LEVEL_NONE;
                bool extracted_new_message = false;
                auto seperator_index = new_message.find("|");
                if (seperator_index != std::string::npos) {
                    unsigned int log_level = megamol::core::utility::log::Log::LEVEL_NONE;
                    auto level_str = new_message.substr(0, seperator_index);
                    try {
                        log_level = std::stoi(level_str);
                    } catch (...) {}
                    if (log_level != megamol::core::utility::log::Log::LEVEL_NONE) {
                        this->messages.push_back({log_level, new_message});
                        extracted_new_message = true;
                    }
                }
                if (!extracted_new_message) {
                    // Append to previous message
                    this->messages.back().message.append(new_message);
                }
                message_str = message_str.substr(split_index + 1);
                split_index = message_str.find("\n");
            }
            this->str("");
        }
    } catch (...) {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Log Console Buffer Error. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        return 1;
    };
    return 0;
}

megamol::gui::LogConsole::LogConsole()
        : echo_log_buffer()
        , echo_log_stream(&this->echo_log_buffer)
        , echo_log_target(nullptr)
        , log_msg_count(0)
        , scroll_down(2)
        , scroll_up(0)
        , last_window_height(0.0f)
        , tooltip() {

    this->echo_log_target = std::make_shared<megamol::core::utility::log::StreamTarget>(
        this->echo_log_stream, megamol::core::utility::log::Log::LEVEL_ALL);

    this->connect_log();
}

LogConsole::~LogConsole() {

    // Reset echo target only if log target of this class instance is used
    if (megamol::core::utility::log::Log::DefaultLog.AccessEchoTarget() == this->echo_log_target) {
        megamol::core::utility::log::Log::DefaultLog.SetEchoTarget(nullptr);
    }
    this->echo_log_target.reset();
}

bool megamol::gui::LogConsole::Draw(WindowCollection::WindowConfiguration& wc) {

    // Scroll down if window height changes
    if (this->last_window_height != ImGui::GetWindowHeight()) {
        this->last_window_height = ImGui::GetWindowHeight();
        this->scroll_down = 2;
    }

    // Menu
    if (ImGui::BeginMenuBar()) {

        // Force Open on Warnings and Errors
        ImGui::Checkbox("Force Open", &wc.log_force_open);
        this->tooltip.Marker("Force open log console window on warnings and errors.");
        ImGui::Separator();

        // Log Level
        ImGui::TextUnformatted("Show");
        ImGui::SameLine();
        if (ImGui::RadioButton("Errors", (wc.log_level >= megamol::core::utility::log::Log::LEVEL_ERROR))) {
            if (wc.log_level >= megamol::core::utility::log::Log::LEVEL_ERROR) {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_NONE;
            } else {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_ERROR;
            }
            this->scroll_down = 2;
        }
        ImGui::SameLine();
        if (ImGui::RadioButton("Warnings", (wc.log_level >= megamol::core::utility::log::Log::LEVEL_WARN))) {
            if (wc.log_level >= megamol::core::utility::log::Log::LEVEL_WARN) {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_ERROR;
            } else {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_WARN;
            }
            this->scroll_down = 2;
        }
        ImGui::SameLine();
        if (ImGui::RadioButton("Infos", (wc.log_level == megamol::core::utility::log::Log::LEVEL_ALL))) {
            if (wc.log_level == megamol::core::utility::log::Log::LEVEL_ALL) {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_WARN;
            } else {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_ALL;
            }
            this->scroll_down = 2;
        }

        // Scrolling
        std::string scroll_label = "Scroll";
        ImGui::SameLine(0.0f, ImGui::GetContentRegionAvail().x - (2.25f * ImGui::GetFrameHeightWithSpacing()) -
                                  ImGui::CalcTextSize(scroll_label.c_str()).x);
        ImGui::TextUnformatted(scroll_label.c_str());
        ImGui::SameLine();
        if (ImGui::ArrowButton("scroll_up", ImGuiDir_Up)) {
            this->scroll_up = 2;
        }
        this->tooltip.ToolTip("Scroll to first log entry.");
        ImGui::SameLine();
        if (ImGui::ArrowButton("scroll_down", ImGuiDir_Down)) {
            this->scroll_down = 2;
        }
        this->tooltip.ToolTip("Scroll to last log entry.");

        ImGui::EndMenuBar();
    }

    // Scroll (requires 2 frames for being applyed)
    if (this->scroll_down > 0) {
        ImGui::SetScrollY(ImGui::GetScrollMaxY());
        this->scroll_down--;
    }
    if (this->scroll_up > 0) {
        ImGui::SetScrollY(0);
        this->scroll_up--;
    }

    // Print messages
    for (auto& entry : this->echo_log_buffer.log()) {
        if (entry.level <= wc.log_level) {
            if (entry.level >= megamol::core::utility::log::Log::LEVEL_INFO) {
                ImGui::TextUnformatted(entry.message.c_str());
            } else if (entry.level >= megamol::core::utility::log::Log::LEVEL_WARN) {
                ImGui::TextColored(GUI_COLOR_TEXT_WARN, entry.message.c_str());
            } else if (entry.level >= megamol::core::utility::log::Log::LEVEL_ERROR) {
                ImGui::TextColored(GUI_COLOR_TEXT_ERROR, entry.message.c_str());
            }
        }
    }

    return true;
}

void megamol::gui::LogConsole::Update(WindowCollection::WindowConfiguration& wc) {

    auto new_log_msg_count = this->echo_log_buffer.log().size();
    if (new_log_msg_count > this->log_msg_count) {
        // Scroll down if new message came in
        this->scroll_down = 2;
        // Bring log console to front on new warnings and errors
        if (wc.log_force_open) {
            for (size_t i = this->log_msg_count; i < new_log_msg_count; i++) {
                auto entry = this->echo_log_buffer.log()[i];
                if (wc.log_level < megamol::core::utility::log::Log::LEVEL_INFO) {
                    wc.log_level = megamol::core::utility::log::Log::LEVEL_WARN;
                    wc.win_show = true;
                }
            }
        }
    }
    this->log_msg_count = new_log_msg_count;
}

bool megamol::gui::LogConsole::connect_log(void) {

    auto current_echo_target = megamol::core::utility::log::Log::DefaultLog.AccessEchoTarget();
    std::shared_ptr<megamol::core::utility::log::OfflineTarget> offline_echo_target =
        std::dynamic_pointer_cast<megamol::core::utility::log::OfflineTarget>(current_echo_target);

    // Only connect if echo target is still default OfflineTarget
    /// Note: A second log console is temporarily created when "GUIView" module is loaded in configurator for complete
    /// module list. For this "GUIView" module NO log is connected, because the main LogConsole instance is already
    /// connected and the taget is not the default OfflineTarget.
    if ((offline_echo_target != nullptr) && (this->echo_log_target != nullptr)) {
        megamol::core::utility::log::Log::DefaultLog.SetEchoTarget(this->echo_log_target);
    }

    return true;
}
<commit_msg>comment<commit_after>/*
 * LogConsole.cpp
 *
 * Copyright (C) 2019 by Universitaet Stuttgart (VIS).
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "LogConsole.h"

using namespace megamol;
using namespace megamol::gui;

int megamol::gui::LogBuffer::sync(void) {
    try {
        auto message_str = this->str();
        if (!message_str.empty()) {
            // Split message string
            auto split_index = message_str.find("\n");
            while (split_index != std::string::npos) {
                // Assuming new line of log message of format "<level>|<message>\r\n"
                auto new_message = message_str.substr(0, split_index + 1);
                unsigned int log_level = megamol::core::utility::log::Log::LEVEL_NONE;
                bool extracted_new_message = false;
                auto seperator_index = new_message.find("|");
                if (seperator_index != std::string::npos) {
                    unsigned int log_level = megamol::core::utility::log::Log::LEVEL_NONE;
                    auto level_str = new_message.substr(0, seperator_index);
                    try {
                        log_level = std::stoi(level_str);
                    } catch (...) {}
                    if (log_level != megamol::core::utility::log::Log::LEVEL_NONE) {
                        this->messages.push_back({log_level, new_message});
                        extracted_new_message = true;
                    }
                }
                if (!extracted_new_message) {
                    // Append to previous message
                    this->messages.back().message.append(new_message);
                }
                message_str = message_str.substr(split_index + 1);
                split_index = message_str.find("\n");
            }
            this->str("");
        }
    } catch (...) {
        megamol::core::utility::log::Log::DefaultLog.WriteError(
            "[GUI] Log Console Buffer Error. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__);
        return 1;
    };
    return 0;
}

megamol::gui::LogConsole::LogConsole()
        : echo_log_buffer()
        , echo_log_stream(&this->echo_log_buffer)
        , echo_log_target(nullptr)
        , log_msg_count(0)
        , scroll_down(2)
        , scroll_up(0)
        , last_window_height(0.0f)
        , tooltip() {

    this->echo_log_target = std::make_shared<megamol::core::utility::log::StreamTarget>(
        this->echo_log_stream, megamol::core::utility::log::Log::LEVEL_ALL);

    this->connect_log();
}

LogConsole::~LogConsole() {

    // Reset echo target only if log target of this class instance is used
    if (megamol::core::utility::log::Log::DefaultLog.AccessEchoTarget() == this->echo_log_target) {
        megamol::core::utility::log::Log::DefaultLog.SetEchoTarget(nullptr);
    }
    this->echo_log_target.reset();
}

bool megamol::gui::LogConsole::Draw(WindowCollection::WindowConfiguration& wc) {

    // Scroll down if window height changes
    if (this->last_window_height != ImGui::GetWindowHeight()) {
        this->last_window_height = ImGui::GetWindowHeight();
        this->scroll_down = 2;
    }

    // Menu
    if (ImGui::BeginMenuBar()) {

        // Force Open on Warnings and Errors
        ImGui::Checkbox("Force Open", &wc.log_force_open);
        this->tooltip.Marker("Force open log console window on warnings and errors.");
        ImGui::Separator();

        // Log Level
        ImGui::TextUnformatted("Show");
        ImGui::SameLine();
        if (ImGui::RadioButton("Errors", (wc.log_level >= megamol::core::utility::log::Log::LEVEL_ERROR))) {
            if (wc.log_level >= megamol::core::utility::log::Log::LEVEL_ERROR) {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_NONE;
            } else {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_ERROR;
            }
            this->scroll_down = 2;
        }
        ImGui::SameLine();
        if (ImGui::RadioButton("Warnings", (wc.log_level >= megamol::core::utility::log::Log::LEVEL_WARN))) {
            if (wc.log_level >= megamol::core::utility::log::Log::LEVEL_WARN) {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_ERROR;
            } else {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_WARN;
            }
            this->scroll_down = 2;
        }
        ImGui::SameLine();
        if (ImGui::RadioButton("Infos", (wc.log_level == megamol::core::utility::log::Log::LEVEL_ALL))) {
            if (wc.log_level == megamol::core::utility::log::Log::LEVEL_ALL) {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_WARN;
            } else {
                wc.log_level = megamol::core::utility::log::Log::LEVEL_ALL;
            }
            this->scroll_down = 2;
        }

        // Scrolling
        std::string scroll_label = "Scroll";
        ImGui::SameLine(0.0f, ImGui::GetContentRegionAvail().x - (2.25f * ImGui::GetFrameHeightWithSpacing()) -
                                  ImGui::CalcTextSize(scroll_label.c_str()).x);
        ImGui::TextUnformatted(scroll_label.c_str());
        ImGui::SameLine();
        if (ImGui::ArrowButton("scroll_up", ImGuiDir_Up)) {
            this->scroll_up = 2;
        }
        this->tooltip.ToolTip("Scroll to first log entry.");
        ImGui::SameLine();
        if (ImGui::ArrowButton("scroll_down", ImGuiDir_Down)) {
            this->scroll_down = 2;
        }
        this->tooltip.ToolTip("Scroll to last log entry.");

        ImGui::EndMenuBar();
    }

    // Scroll - Requires 2 frames for being applied!
    if (this->scroll_down > 0) {
        ImGui::SetScrollY(ImGui::GetScrollMaxY());
        this->scroll_down--;
    }
    if (this->scroll_up > 0) {
        ImGui::SetScrollY(0);
        this->scroll_up--;
    }

    // Print messages
    for (auto& entry : this->echo_log_buffer.log()) {
        if (entry.level <= wc.log_level) {
            if (entry.level >= megamol::core::utility::log::Log::LEVEL_INFO) {
                ImGui::TextUnformatted(entry.message.c_str());
            } else if (entry.level >= megamol::core::utility::log::Log::LEVEL_WARN) {
                ImGui::TextColored(GUI_COLOR_TEXT_WARN, entry.message.c_str());
            } else if (entry.level >= megamol::core::utility::log::Log::LEVEL_ERROR) {
                ImGui::TextColored(GUI_COLOR_TEXT_ERROR, entry.message.c_str());
            }
        }
    }

    return true;
}

void megamol::gui::LogConsole::Update(WindowCollection::WindowConfiguration& wc) {

    auto new_log_msg_count = this->echo_log_buffer.log().size();
    if (new_log_msg_count > this->log_msg_count) {
        // Scroll down if new message came in
        this->scroll_down = 2;
        // Bring log console to front on new warnings and errors
        if (wc.log_force_open) {
            for (size_t i = this->log_msg_count; i < new_log_msg_count; i++) {
                auto entry = this->echo_log_buffer.log()[i];
                if (wc.log_level < megamol::core::utility::log::Log::LEVEL_INFO) {
                    wc.log_level = megamol::core::utility::log::Log::LEVEL_WARN;
                    wc.win_show = true;
                }
            }
        }
    }
    this->log_msg_count = new_log_msg_count;
}

bool megamol::gui::LogConsole::connect_log(void) {

    auto current_echo_target = megamol::core::utility::log::Log::DefaultLog.AccessEchoTarget();
    std::shared_ptr<megamol::core::utility::log::OfflineTarget> offline_echo_target =
        std::dynamic_pointer_cast<megamol::core::utility::log::OfflineTarget>(current_echo_target);

    // Only connect if echo target is still default OfflineTarget
    /// Note: A second log console is temporarily created when "GUIView" module is loaded in configurator for complete
    /// module list. For this "GUIView" module NO log is connected, because the main LogConsole instance is already
    /// connected and the taget is not the default OfflineTarget.
    if ((offline_echo_target != nullptr) && (this->echo_log_target != nullptr)) {
        megamol::core::utility::log::Log::DefaultLog.SetEchoTarget(this->echo_log_target);
    }

    return true;
}
<|endoftext|>


<commit_before>#include "proctor/basic_proposer.h"

namespace pcl
{

  namespace proctor
  {

    void
    BasicProposer::getProposed(int max_num, Entry &query, std::vector<std::string> &input, std::vector<std::string> &output)
    {
      std::vector<std::string>::iterator database_it;

      vector<Candidate> ballot;
      for ( database_it = input.begin() ; database_it != input.end(); database_it++ ) {
        std::string target_id = (*database_it);
        Entry target = (*database_)[target_id];

        Candidate* candidate = new Candidate;
        candidate->id = target_id;
        candidate->votes = getVotes(query, target);
        ballot.push_back(*candidate);
      }

      selectBestCandidates(max_num, ballot, output);
    }

    double
    BasicProposer::getVotes(Entry &query, Entry &match)
    {
      int max_votes = 1; // TODO Set this to what?

      double votes = 0;
      for (unsigned int pi = 0; pi < query.indices->size(); pi++) {
        vector<int> indices;
        vector<float> distances;

        clock_t start = clock();
        StopWatch s;
        int num_found = match.tree->nearestKSearch(*query.features, pi, max_votes, indices, distances);

        for (int ri = 0; ri < num_found; ri++) {
          votes += 1. / (distances[ri] + numeric_limits<float>::epsilon());
          //votes -= distances[ri];
        }
      }

      return votes;
    }

  }

}
<commit_msg>removed unused variable<commit_after>#include "proctor/basic_proposer.h"

namespace pcl
{

  namespace proctor
  {

    void
    BasicProposer::getProposed(int max_num, Entry &query, std::vector<std::string> &input, std::vector<std::string> &output)
    {
      std::vector<std::string>::iterator database_it;

      vector<Candidate> ballot;
      for ( database_it = input.begin() ; database_it != input.end(); database_it++ ) {
        std::string target_id = (*database_it);
        Entry target = (*database_)[target_id];

        Candidate* candidate = new Candidate;
        candidate->id = target_id;
        candidate->votes = getVotes(query, target);
        ballot.push_back(*candidate);
      }

      selectBestCandidates(max_num, ballot, output);
    }

    double
    BasicProposer::getVotes(Entry &query, Entry &match)
    {
      int max_votes = 1; // TODO Set this to what?

      double votes = 0;
      for (unsigned int pi = 0; pi < query.indices->size(); pi++) {
        vector<int> indices;
        vector<float> distances;

        StopWatch s;
        int num_found = match.tree->nearestKSearch(*query.features, pi, max_votes, indices, distances);

        for (int ri = 0; ri < num_found; ri++) {
          votes += 1. / (distances[ri] + numeric_limits<float>::epsilon());
          //votes -= distances[ri];
        }
      }

      return votes;
    }

  }

}
<|endoftext|>


<commit_before>#include "HeatFlowGrid.hpp"

using namespace std;

HeatFlowGrid::HeatFlowGrid(int sizex, int sizey, double lenghtx) {
  if ((sizex * sizey == 0) || (lenghtx == 0)) {
    //TODO: EXIT HERE AND ERROR
  }
  _sizex = abs(sizex);
  _sizey = abs(sizey);
  _step = lenghtx / (double) _sizex;
  _time = 0.;
  _cell = (Cell*) calloc(_sizex * _sizey, sizeof(Cell));
  if(_cell != NULL) {
    _allocated = true;
  } else {
    _allocated = false;
    //TODO: EXIT HERE AND ERROR
  }
}

HeatFlowGrid::~HeatFlowGrid() {
  if(_allocated) {
    free(_cell);
  }
}

void HeatFlowGrid::nextStep(double dt) {
  dt = fabs(dt);
  _time += dt;
  this->evaluateLaplacian();
  double tTemp;
  for(int i = 0; i < _sizex; i++) {
    for(int j = 0; j < _sizey; j++) {
      if(!this->getCell(i,j)->fixed){
        tTemp  = this->getCell(i,j)->temperature;
        tTemp += dt*this->getCell(i,j)->alfa*this->getCell(i,j)->laplacian;
        this->getCell(i,j)->temperature = tTemp;
      } else if (this->getCell(i,j)->func) {
        double value = this->getCell(i,j)->tFunction->Oscillator(_time);
        this->getCell(i,j)->temperature = value;
      }
    }
  }
}

void HeatFlowGrid::printGrid(){
  for(int j = 0; j < _sizey; j++) {
    for(int i = 0; i < _sizex; i++) {
      std::cout << this->getTemperature(i, _sizey-1-j) << " ";
    }
    std::cout << std::endl;
  }
  std::cout << std::endl;
}

void HeatFlowGrid::setTemperature(int i, int j, double t) {
  this->getCell(i,j)->temperature = fabs(t);
}

void HeatFlowGrid::setTemperature(double x, double y, double t) {
  this->setTemperature(cellFromPos(x), cellFromPos(y), t);
}

void HeatFlowGrid::setAllTemperatures(double t) {
  t = fabs(t);
  for(int i = 0; i < _sizex; i++) {
    for(int j = 0; j < _sizey; j++) {
      this->getCell(i,j)->temperature = t;
    }
  }
}

void HeatFlowGrid::setFixed(int i, int j, bool f) {
  this->getCell(i,j)->fixed = f;
}

void HeatFlowGrid::setFixed(double x, double y, bool f) {
  this->setFixed(cellFromPos(x), cellFromPos(y), f);
}

void HeatFlowGrid::setAllFixed(bool f) {
  for(int i = 0; i < _sizex; i++) {
    for(int j = 0; j < _sizey; j++) {
      this->getCell(i,j)->fixed = f;
    }
  }
}

void HeatFlowGrid::setAllAlfas(double a) {
  for(int i = 0; i < _sizex; i++) {
    for(int j = 0; j < _sizey; j++) {
      this->getCell(i,j)->alfa = a;
    }
  }
}

void HeatFlowGrid::setTemperatureFunc(int i, int j, HeatFlowFunction *tf) {
  this->getCell(i,j)->tFunction = tf;
  this->getCell(i,j)->func = (tf==NULL)?false:true;
  this->getCell(i,j)->fixed = (tf==NULL)?false:true;
  if (tf==NULL) {
    std::fprintf(stderr, "No func setted\n");
  }
}

double HeatFlowGrid::getTemperature(int i, int j) {
  return this->getCell(i,j)->temperature;
}

double HeatFlowGrid::getTemperature(double x, double y) {
  return this->getTemperature(cellFromPos(x), cellFromPos(y));
}

double HeatFlowGrid::getLaplacian(int i, int j) {
  return this->getCell(i,j)->laplacian;
}

double HeatFlowGrid::getLaplacian(double x, double y) {
  return this->getLaplacian(cellFromPos(x), cellFromPos(y));
}

bool HeatFlowGrid::getFixed(int i, int j) {
  return this->getCell(i,j)->fixed;
}

bool HeatFlowGrid::getFixed(double x, double y) {
  return this->getFixed(cellFromPos(x), cellFromPos(y));
}

int HeatFlowGrid::cellFromPos(double pos) {
  return floor(pos/_step);
}

double HeatFlowGrid::posFromCell (int cell) {
  return cell*_step + _step/2.;
}

void HeatFlowGrid::evaluateLaplacian() { //https://en.wikipedia.org/wiki/Finite_difference#Higher-order_differences
  double tempLagr;
  for(int j = 0; j < _sizey; j++) {//d2x + d2y
    for(int i = 0; i < _sizex; i++) {
      tempLagr = -5.*this->getCell(i, j)->temperature;
      tempLagr += 4./3. * (this->getCell(i-1,j)->temperature + this->getCell(i+1,j)->temperature);
      tempLagr += -1./12. * (this->getCell(i-2,j)->temperature + this->getCell(i+2,j)->temperature);
      tempLagr += 4./3. * (this->getCell(i,j-1)->temperature + this->getCell(i,j+1)->temperature);
      tempLagr += -1./12. * (this->getCell(i,j-2)->temperature + this->getCell(i,j+2)->temperature);
      this->getCell(i,j)->laplacian = tempLagr / pow(_step, 2.);
    }
  }
}

Cell* HeatFlowGrid::getCell(int i, int j) {
  if (i < 0) {
    if (j>=0 && j<_sizey) {
      return (_cell + _sizex * j);
    } else if (j<0) {
      return (_cell);
    } else {
      return (_cell + _sizex * (_sizey-1));
    }
  } else if (i>=0 && i<_sizex) {
    if (j>=0 && j<_sizey) {
      return (_cell + _sizex * j + i);
    } else if (j<0) {
      return (_cell + i);
    } else {
      return (_cell + _sizex * (_sizey-1) + i);
    }
  } else if (i>=_sizex) {
    if (j>=0 && j<_sizey) {
      return (_cell + _sizex * j + _sizex-1);
    } else if (j<0) {
      return (_cell + _sizex-1);
    } else {
      return (_cell + _sizex * (_sizey-1) + _sizex-1);
    }
  } else {
    return NULL;
    //TODO: EXIT HERE AND ERROR: WHAT THE HELL?
  }
}
<commit_msg>Easier getCell implementation<commit_after>#include "HeatFlowGrid.hpp"

using namespace std;

HeatFlowGrid::HeatFlowGrid(int sizex, int sizey, double lenghtx) {
  if ((sizex * sizey == 0) || (lenghtx == 0)) {
    //TODO: EXIT HERE AND ERROR
  }
  _sizex = abs(sizex);
  _sizey = abs(sizey);
  _step = lenghtx / (double) _sizex;
  _time = 0.;
  _cell = (Cell*) calloc(_sizex * _sizey, sizeof(Cell));
  if(_cell != NULL) {
    _allocated = true;
  } else {
    _allocated = false;
    //TODO: EXIT HERE AND ERROR
  }
}

HeatFlowGrid::~HeatFlowGrid() {
  if(_allocated) {
    free(_cell);
  }
}

void HeatFlowGrid::nextStep(double dt) {
  dt = fabs(dt);
  _time += dt;
  this->evaluateLaplacian();
  double tTemp;
  for(int i = 0; i < _sizex; i++) {
    for(int j = 0; j < _sizey; j++) {
      if(!this->getCell(i,j)->fixed){
        tTemp  = this->getCell(i,j)->temperature;
        tTemp += dt*this->getCell(i,j)->alfa*this->getCell(i,j)->laplacian;
        this->getCell(i,j)->temperature = tTemp;
      } else if (this->getCell(i,j)->func) {
        double value = this->getCell(i,j)->tFunction->Oscillator(_time);
        this->getCell(i,j)->temperature = value;
      }
    }
  }
}

void HeatFlowGrid::printGrid(){
  for(int j = 0; j < _sizey; j++) {
    for(int i = 0; i < _sizex; i++) {
      std::cout << this->getTemperature(i, _sizey-1-j) << " ";
    }
    std::cout << std::endl;
  }
  std::cout << std::endl;
}

void HeatFlowGrid::setTemperature(int i, int j, double t) {
  this->getCell(i,j)->temperature = fabs(t);
}

void HeatFlowGrid::setTemperature(double x, double y, double t) {
  this->setTemperature(cellFromPos(x), cellFromPos(y), t);
}

void HeatFlowGrid::setAllTemperatures(double t) {
  t = fabs(t);
  for(int i = 0; i < _sizex; i++) {
    for(int j = 0; j < _sizey; j++) {
      this->getCell(i,j)->temperature = t;
    }
  }
}

void HeatFlowGrid::setFixed(int i, int j, bool f) {
  this->getCell(i,j)->fixed = f;
}

void HeatFlowGrid::setFixed(double x, double y, bool f) {
  this->setFixed(cellFromPos(x), cellFromPos(y), f);
}

void HeatFlowGrid::setAllFixed(bool f) {
  for(int i = 0; i < _sizex; i++) {
    for(int j = 0; j < _sizey; j++) {
      this->getCell(i,j)->fixed = f;
    }
  }
}

void HeatFlowGrid::setAllAlfas(double a) {
  for(int i = 0; i < _sizex; i++) {
    for(int j = 0; j < _sizey; j++) {
      this->getCell(i,j)->alfa = a;
    }
  }
}

void HeatFlowGrid::setTemperatureFunc(int i, int j, HeatFlowFunction *tf) {
  this->getCell(i,j)->tFunction = tf;
  this->getCell(i,j)->func = (tf==NULL)?false:true;
  this->getCell(i,j)->fixed = (tf==NULL)?false:true;
  if (tf==NULL) {
    std::fprintf(stderr, "No func setted\n");
  }
}

double HeatFlowGrid::getTemperature(int i, int j) {
  return this->getCell(i,j)->temperature;
}

double HeatFlowGrid::getTemperature(double x, double y) {
  return this->getTemperature(cellFromPos(x), cellFromPos(y));
}

double HeatFlowGrid::getLaplacian(int i, int j) {
  return this->getCell(i,j)->laplacian;
}

double HeatFlowGrid::getLaplacian(double x, double y) {
  return this->getLaplacian(cellFromPos(x), cellFromPos(y));
}

bool HeatFlowGrid::getFixed(int i, int j) {
  return this->getCell(i,j)->fixed;
}

bool HeatFlowGrid::getFixed(double x, double y) {
  return this->getFixed(cellFromPos(x), cellFromPos(y));
}

int HeatFlowGrid::cellFromPos(double pos) {
  return floor(pos/_step);
}

double HeatFlowGrid::posFromCell (int cell) {
  return cell*_step + _step/2.;
}

void HeatFlowGrid::evaluateLaplacian() { //https://en.wikipedia.org/wiki/Finite_difference#Higher-order_differences
  double tempLagr;
  for(int j = 0; j < _sizey; j++) {//d2x + d2y
    for(int i = 0; i < _sizex; i++) {
      tempLagr = -5.*this->getCell(i, j)->temperature;
      tempLagr += 4./3. * (this->getCell(i-1,j)->temperature + this->getCell(i+1,j)->temperature);
      tempLagr += -1./12. * (this->getCell(i-2,j)->temperature + this->getCell(i+2,j)->temperature);
      tempLagr += 4./3. * (this->getCell(i,j-1)->temperature + this->getCell(i,j+1)->temperature);
      tempLagr += -1./12. * (this->getCell(i,j-2)->temperature + this->getCell(i,j+2)->temperature);
      this->getCell(i,j)->laplacian = tempLagr / pow(_step, 2.);
    }
  }
}

Cell* HeatFlowGrid::getCell(int i, int j) {
  if ((i>=0 && i<_sizex)&&(j>=0 && j<_sizey)) {
    return (_cell + _sizex * j + i);
  } else if (i<0) {
    return this->getCell(0,j);
  } else if (i>=_sizex) {
    return this->getCell(_sizex-1,j);
  } else if (j<0) {
    return this->getCell(i,0);
  } else (j>=_sizey) {
    return this->getCell(i,_sizey-1);
  }
  //
  // if (i < 0) {
  //   if (j>=0 && j<_sizey) {
  //     return (_cell + _sizex * j);
  //   } else if (j<0) {
  //     return (_cell);
  //   } else {
  //     return (_cell + _sizex * (_sizey-1));
  //   }
  // } else if (i>=0 && i<_sizex) {
  //   if (j>=0 && j<_sizey) {
  //     return (_cell + _sizex * j + i);
  //   } else if (j<0) {
  //     return (_cell + i);
  //   } else {
  //     return (_cell + _sizex * (_sizey-1) + i);
  //   }
  // } else if (i>=_sizex) {
  //   if (j>=0 && j<_sizey) {
  //     return (_cell + _sizex * j + _sizex-1);
  //   } else if (j<0) {
  //     return (_cell + _sizex-1);
  //   } else {
  //     return (_cell + _sizex * (_sizey-1) + _sizex-1);
  //   }
  // } else {
  //   return NULL;
  //   //TODO: EXIT HERE AND ERROR: WHAT THE HELL?
  // }
}
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */

#include "stdafx.h"

// Test the function methods

#include "Connector/Functions.h"

LOGGING (com.opengamma.language.connector.FunctionsTest);

#define TEST_LANGUAGE		TEXT ("test")
#define TIMEOUT_STARTUP		30000
#define TIMEOUT_CALL		3000

static CConnector *g_poConnector;

static void StartConnector () {
	g_poConnector = CConnector::Start (TEST_LANGUAGE);
	ASSERT (g_poConnector);
	ASSERT (g_poConnector->WaitForStartup (TIMEOUT_STARTUP));
}

static void StopConnector () {
	ASSERT (g_poConnector->Stop ());
	CConnector::Release (g_poConnector);
	g_poConnector = NULL;
}

static void QueryAvailable () {
	CFunctionQueryAvailable query (g_poConnector);
	ASSERT (query.Send ());
	com_opengamma_language_function_Available *pAvailable = query.Recv (CRequestBuilder::GetDefaultTimeout ());
	ASSERT (pAvailable);
	LOGINFO (TEXT ("Received ") << pAvailable->fudgeCountFunction << TEXT (" definitions"));
	ASSERT (pAvailable->fudgeCountFunction > 0);
	int i;
	for (i = 0; i < pAvailable->fudgeCountFunction; i++) {
		LOGDEBUG (TEXT ("Function ") << i << TEXT (": ") << pAvailable->_function[i]->_definition->fudgeParent._name << TEXT (" (") << pAvailable->_function[i]->_identifier << TEXT (")"));
	}
}

static void InvokeInvalid () {
	CFunctionInvoke invoke (g_poConnector);
	invoke.SetInvocationId (99);
	ASSERT (invoke.Send ());
	com_opengamma_language_function_Result *pResult = invoke.Recv (CRequestBuilder::GetDefaultTimeout ());
	ASSERT (pResult);
	ASSERT (!pResult->fudgeCountResult);
}

BEGIN_TESTS(FunctionsTest)
	TEST (QueryAvailable)
	TEST (InvokeInvalid)
	BEFORE_TEST (StartConnector)
	AFTER_TEST (StopConnector)
END_TESTS
<commit_msg>Correct unit test. Need a much bigger ID to be sure it's invalid.<commit_after>/**
 * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */

#include "stdafx.h"

// Test the function methods

#include "Connector/Functions.h"

LOGGING (com.opengamma.language.connector.FunctionsTest);

#define TEST_LANGUAGE		TEXT ("test")
#define TIMEOUT_STARTUP		30000
#define TIMEOUT_CALL		3000

static CConnector *g_poConnector;

static void StartConnector () {
	g_poConnector = CConnector::Start (TEST_LANGUAGE);
	ASSERT (g_poConnector);
	ASSERT (g_poConnector->WaitForStartup (TIMEOUT_STARTUP));
}

static void StopConnector () {
	ASSERT (g_poConnector->Stop ());
	CConnector::Release (g_poConnector);
	g_poConnector = NULL;
}

static void QueryAvailable () {
	CFunctionQueryAvailable query (g_poConnector);
	ASSERT (query.Send ());
	com_opengamma_language_function_Available *pAvailable = query.Recv (CRequestBuilder::GetDefaultTimeout ());
	ASSERT (pAvailable);
	LOGINFO (TEXT ("Received ") << pAvailable->fudgeCountFunction << TEXT (" definitions"));
	ASSERT (pAvailable->fudgeCountFunction > 0);
	int i;
	for (i = 0; i < pAvailable->fudgeCountFunction; i++) {
		LOGDEBUG (TEXT ("Function ") << i << TEXT (": ") << pAvailable->_function[i]->_definition->fudgeParent._name << TEXT (" (") << pAvailable->_function[i]->_identifier << TEXT (")"));
	}
}

static void InvokeInvalid () {
	CFunctionInvoke invoke (g_poConnector);
	invoke.SetInvocationId (MAX_INT);
	ASSERT (invoke.Send ());
	com_opengamma_language_function_Result *pResult = invoke.Recv (CRequestBuilder::GetDefaultTimeout ());
	ASSERT (pResult);
	ASSERT (!pResult->fudgeCountResult);
}

BEGIN_TESTS(FunctionsTest)
	TEST (QueryAvailable)
	TEST (InvokeInvalid)
	BEFORE_TEST (StartConnector)
	AFTER_TEST (StopConnector)
END_TESTS
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/component/collision/DefaultCollisionGroupManager.h>
#include <sofa/component/collision/SolverMerger.h>
#include <sofa/core/CollisionModel.h>
#include <sofa/simulation/common/Node.h>
#include <sofa/simulation/common/Simulation.h>

namespace sofa
{

namespace component
{

namespace collision
{

using core::collision::Contact;

DefaultCollisionGroupManager::DefaultCollisionGroupManager()
{
}

DefaultCollisionGroupManager::~DefaultCollisionGroupManager()
{
}

simulation::Node* DefaultCollisionGroupManager::buildCollisionGroup()
{
    return simulation::getSimulation()->newNode("CollisionGroup");
}

void DefaultCollisionGroupManager::createGroups(core::objectmodel::BaseContext* scene, const sofa::helper::vector<Contact*>& contacts)
{
    int groupIndex = 1;
    simulation::Node* node = dynamic_cast<simulation::Node*>(scene);
    if (node==NULL)
    {
        serr << "DefaultCollisionGroupManager only support graph-based scenes."<<sendl;
        return;
    }

    if (node && !node->getLogTime()) node=NULL; // Only use node for time logging
    simulation::Node::ctime_t t0 = 0;

    if (node) t0 = node->startTime();

    // Map storing group merging history
    std::map<simulation::Node*, simulation::Node*> mergedGroups;
    sofa::helper::vector<simulation::Node*> contactGroup;
    sofa::helper::vector<simulation::Node*> removedGroup;
    contactGroup.reserve(contacts.size());
    for(sofa::helper::vector<Contact*>::const_iterator cit = contacts.begin(); cit != contacts.end(); cit++)
    {
        Contact* contact = *cit;
        simulation::Node* group1 = getIntegrationNode(contact->getCollisionModels().first);
        simulation::Node* group2 = getIntegrationNode(contact->getCollisionModels().second);
        simulation::Node* group = NULL;
        if (group1==NULL || group2==NULL)
        {
        }
        else if (group1 == group2)
        {
            // same group, no new group necessary
            group = group1;
        }
        else if (simulation::Node* parent=findCommonParent(group1,group2))
        {
            // we can merge the groups
            // if solvers are compatible...
            bool mergeSolvers = (!group1->solver.empty() || !group2->solver.empty());
            SolverSet solver;
            if (mergeSolvers)
                solver = SolverMerger::merge(group1->solver[0], group2->solver[0]);
            //else std::cout << "New integration group below multi-group solver" << std::endl;
            if (!mergeSolvers || solver.odeSolver!=NULL)
            {
                bool group1IsColl = groupSet.find(group1)!=groupSet.end();
                bool group2IsColl = groupSet.find(group2)!=groupSet.end();
                if (!group1IsColl && !group2IsColl)
                {
                    char groupName[32];
                    snprintf(groupName,sizeof(groupName),"collision%d",groupIndex++);
                    // create a new group
                    group = buildCollisionGroup();
                    group->setName(groupName);
                    parent->addChild(group);

                    core::objectmodel::Context *current_context = dynamic_cast< core::objectmodel::Context *>(parent->getContext());
                    group->copyVisualContext( (*current_context));

                    group->updateSimulationContext();
                    group->moveChild((simulation::Node*)group1);
                    group->moveChild((simulation::Node*)group2);
                    groupSet.insert(group);
                }
                else if (group1IsColl)
                {
                    group = group1;
                    // merge group2 in group1
                    if (!group2IsColl)
                    {
                        group->moveChild(group2);
                    }
                    else
                    {
                        // merge groups and remove group2
                        SolverSet solver2;
                        if (mergeSolvers)
                        {
                            solver2.odeSolver = group2->solver[0];
                            group2->removeObject(solver2.odeSolver);
                            if (!group2->linearSolver.empty())
                            {
                                solver2.linearSolver = group2->linearSolver[0];
                                group2->removeObject(solver2.linearSolver);
                            }
                            if (!group2->constraintSolver.empty())
                            {
                                solver2.constraintSolver = group2->constraintSolver[0];
                                group2->removeObject(solver2.constraintSolver);
                            }
                        }
                        while(!group2->object.empty())
                            group->moveObject(*group2->object.begin());
                        while(!group2->child.empty())
                            group->moveChild(*group2->child.begin());
                        parent->removeChild((simulation::Node*)group2);
                        groupSet.erase(group2);
                        mergedGroups[group2] = group;
                        if (solver2.odeSolver) delete solver2.odeSolver;
                        if (solver2.linearSolver) delete solver2.linearSolver;
                        if (solver2.constraintSolver) delete solver2.constraintSolver;
                        // BUGFIX(2007-06-23 Jeremie A): we can't remove group2 yet, to make sure the keys in mergedGroups are unique.
                        removedGroup.push_back(group2);
                        //delete group2;
                    }
                }
                else
                {
                    // group1 is not a collision group while group2 is
                    group = group2;
                    group->moveChild(group1);
                }
                if (!group->solver.empty())
                {
                    core::behavior::OdeSolver* solver2 = group->solver[0];
                    group->removeObject(solver2);
                    delete solver2;
                }
                if (!group->linearSolver.empty())
                {
                    core::behavior::LinearSolver* solver2 = group->linearSolver[0];
                    group->removeObject(solver2);
                    delete solver2;
                }
                if (!group->constraintSolver.empty())
                {
                    core::behavior::ConstraintSolver* solver2 = group->constraintSolver[0];
                    group->removeObject(solver2);
                    delete solver2;
                }
                if (solver.linearSolver)
                    group->addObject(solver.odeSolver);
                if (solver.linearSolver)
                    group->addObject(solver.linearSolver);
                if (solver.constraintSolver)
                    group->addObject(solver.constraintSolver);
            }
        }
        contactGroup.push_back(group);
    }

    if (node) t0 = node->endTime(t0, "collision/groups", this);

    // now that the groups are final, attach contacts' response
    for(unsigned int i=0; i<contacts.size(); i++)
    {
        Contact* contact = contacts[i];
        simulation::Node* group = contactGroup[i];
        while (group!=NULL && mergedGroups.find(group)!=mergedGroups.end())
            group = mergedGroups[group];
        if (group!=NULL)
            contact->createResponse(group);
        else
            contact->createResponse(scene);
    }

    if (node) t0 = node->endTime(t0, "collision/contacts", this);

    // delete removed groups
    for (sofa::helper::vector<simulation::Node*>::iterator it = removedGroup.begin(); it!=removedGroup.end(); ++it)
    {
        simulation::Node *node=*it;
        node->detachFromGraph();
        node->execute<simulation::DeleteVisitor>();
        delete *it;
    }
    removedGroup.clear();

    // finally recreate group vector
    groups.clear();
    for (std::set<simulation::Node*>::iterator it = groupSet.begin(); it!=groupSet.end(); ++it)
        groups.push_back(*it);
    //if (!groups.empty())
    //	sout << groups.size()<<" collision groups created."<<sendl;
}

simulation::Node* DefaultCollisionGroupManager::getIntegrationNode(core::CollisionModel* model)
{
    simulation::Node* node = static_cast<simulation::Node*>(model->getContext());
    helper::vector< core::behavior::OdeSolver *> listSolver;
    node->get< core::behavior::OdeSolver >(&listSolver);

    if (listSolver.empty())
        return NULL;
    simulation::Node* solvernode = static_cast<simulation::Node*>(listSolver.back()->getContext());
    if (solvernode->linearSolver.empty())
        return solvernode; // no linearsolver
    core::behavior::LinearSolver * linearSolver = solvernode->linearSolver[0];
    if (!linearSolver->isMultiGroup())
    {
        //std::cout << "Linear solver " << linearSolver->getName() << " of CM " << model->getName() << " is not multi-group" << std::endl;
        return solvernode;
    }
    // This solver handles multiple groups, we have to find which group contains this collision model
    // First move up to the node of the initial mechanical object
    while (node->mechanicalMapping && node->mechanicalMapping->getMechFrom()[0])
        node = static_cast<simulation::Node*>(node->mechanicalMapping->getMechFrom()[0]->getContext());
    // Then check if it is one of the child nodes of the solver node
    for (simulation::Node::ChildIterator it = solvernode->child.begin(), itend = solvernode->child.end(); it != itend; ++it)
        if (*it == node)
        {
            //std::cout << "Group of CM " << model->getName() << " is " << (*it)->getName() << " child of " << solvernode->getName() << std::endl;
            return *it;
        }
    // Then check if it is a child of one of the child nodes of the solver node
    for (simulation::Node::ChildIterator it = solvernode->child.begin(), itend = solvernode->child.end(); it != itend; ++it)
        if (node->hasParent(*it))
            return *it;
    // Then check if it is a grand-childs of one of the child nodes of the solver node
    for (simulation::Node::ChildIterator it = solvernode->child.begin(), itend = solvernode->child.end(); it != itend; ++it)
        if (node->getContext()->hasAncestor(*it))
            return *it;
    // group not found, simply return the solver node
    return solvernode;
}

} // namespace collision

} // namespace component

} // namespace Sofa
<commit_msg>r8207/sofa-dev : FIX: bug in DefaultCollisionGroupManager. This should close ticket #202<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/component/collision/DefaultCollisionGroupManager.h>
#include <sofa/component/collision/SolverMerger.h>
#include <sofa/core/CollisionModel.h>
#include <sofa/simulation/common/Node.h>
#include <sofa/simulation/common/Simulation.h>

namespace sofa
{

namespace component
{

namespace collision
{

using core::collision::Contact;

DefaultCollisionGroupManager::DefaultCollisionGroupManager()
{
}

DefaultCollisionGroupManager::~DefaultCollisionGroupManager()
{
}

simulation::Node* DefaultCollisionGroupManager::buildCollisionGroup()
{
    return simulation::getSimulation()->newNode("CollisionGroup");
}

void DefaultCollisionGroupManager::createGroups(core::objectmodel::BaseContext* scene, const sofa::helper::vector<Contact*>& contacts)
{
    int groupIndex = 1;
    simulation::Node* node = dynamic_cast<simulation::Node*>(scene);
    if (node==NULL)
    {
        serr << "DefaultCollisionGroupManager only support graph-based scenes."<<sendl;
        return;
    }

    if (node && !node->getLogTime()) node=NULL; // Only use node for time logging
    simulation::Node::ctime_t t0 = 0;

    if (node) t0 = node->startTime();

    // Map storing group merging history
    std::map<simulation::Node*, simulation::Node*> mergedGroups;
    sofa::helper::vector<simulation::Node*> contactGroup;
    sofa::helper::vector<simulation::Node*> removedGroup;
    contactGroup.reserve(contacts.size());
    for(sofa::helper::vector<Contact*>::const_iterator cit = contacts.begin(); cit != contacts.end(); cit++)
    {
        Contact* contact = *cit;
        simulation::Node* group1 = getIntegrationNode(contact->getCollisionModels().first);
        simulation::Node* group2 = getIntegrationNode(contact->getCollisionModels().second);
        simulation::Node* group = NULL;
        if (group1==NULL || group2==NULL)
        {
        }
        else if (group1 == group2)
        {
            // same group, no new group necessary
            group = group1;
        }
        else if (simulation::Node* parent=findCommonParent(group1,group2))
        {
            // we can merge the groups
            // if solvers are compatible...
            bool mergeSolvers = (!group1->solver.empty() || !group2->solver.empty());
            SolverSet solver;
            if (mergeSolvers)
                solver = SolverMerger::merge(group1->solver[0], group2->solver[0]);

            //else std::cout << "New integration group below multi-group solver" << std::endl;
            if (!mergeSolvers || solver.odeSolver!=NULL)
            {
                bool group1IsColl = groupSet.find(group1)!=groupSet.end();
                bool group2IsColl = groupSet.find(group2)!=groupSet.end();
                if (!group1IsColl && !group2IsColl)
                {
                    char groupName[32];
                    snprintf(groupName,sizeof(groupName),"collision%d",groupIndex++);
                    // create a new group
                    group = buildCollisionGroup();
                    group->setName(groupName);
                    parent->addChild(group);

                    core::objectmodel::Context *current_context = dynamic_cast< core::objectmodel::Context *>(parent->getContext());
                    group->copyVisualContext( (*current_context));

                    group->updateSimulationContext();
                    group->moveChild((simulation::Node*)group1);
                    group->moveChild((simulation::Node*)group2);
                    groupSet.insert(group);
                }
                else if (group1IsColl)
                {
                    group = group1;
                    // merge group2 in group1
                    if (!group2IsColl)
                    {
                        group->moveChild(group2);
                    }
                    else
                    {
                        // merge groups and remove group2
                        SolverSet solver2;
                        if (mergeSolvers)
                        {
                            solver2.odeSolver = group2->solver[0];
                            group2->removeObject(solver2.odeSolver);
                            if (!group2->linearSolver.empty())
                            {
                                solver2.linearSolver = group2->linearSolver[0];
                                group2->removeObject(solver2.linearSolver);
                            }
                            if (!group2->constraintSolver.empty())
                            {
                                solver2.constraintSolver = group2->constraintSolver[0];
                                group2->removeObject(solver2.constraintSolver);
                            }
                        }
                        while(!group2->object.empty())
                            group->moveObject(*group2->object.begin());
                        while(!group2->child.empty())
                            group->moveChild(*group2->child.begin());
                        parent->removeChild((simulation::Node*)group2);
                        groupSet.erase(group2);
                        mergedGroups[group2] = group;
                        if (solver2.odeSolver) delete solver2.odeSolver;
                        if (solver2.linearSolver) delete solver2.linearSolver;
                        if (solver2.constraintSolver) delete solver2.constraintSolver;
                        // BUGFIX(2007-06-23 Jeremie A): we can't remove group2 yet, to make sure the keys in mergedGroups are unique.
                        removedGroup.push_back(group2);
                        //delete group2;
                    }
                }
                else
                {
                    // group1 is not a collision group while group2 is
                    group = group2;
                    group->moveChild(group1);
                }
                if (!group->solver.empty())
                {
                    core::behavior::OdeSolver* solver2 = group->solver[0];
                    group->removeObject(solver2);
                    delete solver2;
                }
                if (!group->linearSolver.empty())
                {
                    core::behavior::LinearSolver* solver2 = group->linearSolver[0];
                    group->removeObject(solver2);
                    delete solver2;
                }
                if (!group->constraintSolver.empty())
                {
                    core::behavior::ConstraintSolver* solver2 = group->constraintSolver[0];
                    group->removeObject(solver2);
                    delete solver2;
                }
                if (solver.odeSolver)
                    group->addObject(solver.odeSolver);
                if (solver.linearSolver)
                    group->addObject(solver.linearSolver);
                if (solver.constraintSolver)
                    group->addObject(solver.constraintSolver);
            }
        }
        contactGroup.push_back(group);
    }

    if (node) t0 = node->endTime(t0, "collision/groups", this);

    // now that the groups are final, attach contacts' response
    for(unsigned int i=0; i<contacts.size(); i++)
    {
        Contact* contact = contacts[i];
        simulation::Node* group = contactGroup[i];
        while (group!=NULL && mergedGroups.find(group)!=mergedGroups.end())
            group = mergedGroups[group];
        if (group!=NULL)
            contact->createResponse(group);
        else
            contact->createResponse(scene);
    }

    if (node) t0 = node->endTime(t0, "collision/contacts", this);

    // delete removed groups
    for (sofa::helper::vector<simulation::Node*>::iterator it = removedGroup.begin(); it!=removedGroup.end(); ++it)
    {
        simulation::Node *node=*it;
        node->detachFromGraph();
        node->execute<simulation::DeleteVisitor>();
        delete *it;
    }
    removedGroup.clear();

    // finally recreate group vector
    groups.clear();
    for (std::set<simulation::Node*>::iterator it = groupSet.begin(); it!=groupSet.end(); ++it)
        groups.push_back(*it);
    //if (!groups.empty())
    //	sout << groups.size()<<" collision groups created."<<sendl;
}

simulation::Node* DefaultCollisionGroupManager::getIntegrationNode(core::CollisionModel* model)
{
    simulation::Node* node = static_cast<simulation::Node*>(model->getContext());
    helper::vector< core::behavior::OdeSolver *> listSolver;
    node->get< core::behavior::OdeSolver >(&listSolver);

    if (listSolver.empty())
        return NULL;
    simulation::Node* solvernode = static_cast<simulation::Node*>(listSolver.back()->getContext());
    if (solvernode->linearSolver.empty())
        return solvernode; // no linearsolver
    core::behavior::LinearSolver * linearSolver = solvernode->linearSolver[0];
    if (!linearSolver->isMultiGroup())
    {
        //std::cout << "Linear solver " << linearSolver->getName() << " of CM " << model->getName() << " is not multi-group" << std::endl;
        return solvernode;
    }
    // This solver handles multiple groups, we have to find which group contains this collision model
    // First move up to the node of the initial mechanical object
    while (node->mechanicalMapping && node->mechanicalMapping->getMechFrom()[0])
        node = static_cast<simulation::Node*>(node->mechanicalMapping->getMechFrom()[0]->getContext());
    // Then check if it is one of the child nodes of the solver node
    for (simulation::Node::ChildIterator it = solvernode->child.begin(), itend = solvernode->child.end(); it != itend; ++it)
        if (*it == node)
        {
            //std::cout << "Group of CM " << model->getName() << " is " << (*it)->getName() << " child of " << solvernode->getName() << std::endl;
            return *it;
        }
    // Then check if it is a child of one of the child nodes of the solver node
    for (simulation::Node::ChildIterator it = solvernode->child.begin(), itend = solvernode->child.end(); it != itend; ++it)
        if (node->hasParent(*it))
            return *it;
    // Then check if it is a grand-childs of one of the child nodes of the solver node
    for (simulation::Node::ChildIterator it = solvernode->child.begin(), itend = solvernode->child.end(); it != itend; ++it)
        if (node->getContext()->hasAncestor(*it))
            return *it;
    // group not found, simply return the solver node
    return solvernode;
}

} // namespace collision

} // namespace component

} // namespace Sofa
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
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 <array>
#include <iostream>
#include <memory>

#include "gtest/gtest.h"
#include "paddle/fluid/platform/enforce.h"
#include "paddle/fluid/string/piece.h"

using StringPiece = paddle::string::Piece;
using paddle::string::HasPrefix;

TEST(ENFORCE, OK) {
  PADDLE_ENFORCE(true, "Enforce is ok %d now %f", 123, 0.345);
  size_t val = 1;
  const size_t limit = 10;
  PADDLE_ENFORCE(val < limit, "Enforce is OK too");
}

TEST(ENFORCE, FAILED) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE(false, "Enforce is not ok %d at all", 123);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(
        HasPrefix(StringPiece(error.what()), "Enforce is not ok 123 at all"));
  }
  EXPECT_TRUE(caught_exception);

  caught_exception = false;
  try {
    PADDLE_ENFORCE(false, "Enforce is not ok at all");
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(
        HasPrefix(StringPiece(error.what()), "Enforce is not ok at all"));
  }
  EXPECT_TRUE(caught_exception);

  caught_exception = false;
  try {
    PADDLE_ENFORCE(false);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_NE(std::string(error.what()).find("  at "), 0);
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE, NO_ARG_OK) {
  int a = 2;
  int b = 2;
  PADDLE_ENFORCE_EQ(a, b);
  // test enforce with extra message.
  PADDLE_ENFORCE_EQ(a, b, "some thing wrong %s", "info");
}

TEST(ENFORCE_EQ, NO_EXTRA_MSG_FAIL) {
  int a = 2;
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_EQ(a, 1 + 3);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected a == 1 + 3, but received a:2 != 1 + 3:4.");
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_EQ, EXTRA_MSG_FAIL) {
  int a = 2;
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_EQ(a, 1 + 3, "%s size not match", "their");
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    HasPrefix(StringPiece(error.what()),
              "Enforce failed. Expected a == 1 + 3, but received a:2 != 1 + "
              "3:4.\ntheir size not match");
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_NE, OK) {
  PADDLE_ENFORCE_NE(1, 2);
  PADDLE_ENFORCE_NE(1.0, 2UL);
}
TEST(ENFORCE_NE, FAIL) {
  bool caught_exception = false;

  try {
    // 2UL here to check data type compatible
    PADDLE_ENFORCE_NE(1.0, 1UL);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected 1.0 != 1UL, but received 1.0:1 == 1UL:1."))
        << error.what() << " does not have expected prefix";
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_GT, OK) { PADDLE_ENFORCE_GT(2, 1); }
TEST(ENFORCE_GT, FAIL) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_GT(1, 2UL);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected 1 > 2UL, but received 1:1 <= 2UL:2."));
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_GE, OK) {
  PADDLE_ENFORCE_GE(2, 2UL);
  PADDLE_ENFORCE_GE(3, 2UL);
  PADDLE_ENFORCE_GE(3, 2);
  PADDLE_ENFORCE_GE(3.21, 2UL);
}
TEST(ENFORCE_GE, FAIL) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_GE(1, 2UL);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected 1 >= 2UL, but received 1:1 < 2UL:2."));
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_LE, OK) {
  PADDLE_ENFORCE_LE(1, 1);
  PADDLE_ENFORCE_LE(1, 1UL);
  PADDLE_ENFORCE_LE(2, 3UL);
  PADDLE_ENFORCE_LE(2UL, 3);
  PADDLE_ENFORCE_LE(2UL, 3.2);
}
TEST(ENFORCE_LE, FAIL) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_GT(1, 2UL);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected 1 > 2UL, but received 1:1 <= 2UL:2."));
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_LT, OK) {
  PADDLE_ENFORCE_LT(3, 10);
  PADDLE_ENFORCE_LT(2, 3UL);
  PADDLE_ENFORCE_LT(2UL, 3);
}
TEST(ENFORCE_LT, FAIL) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_LT(1UL, 0.12);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(StringPiece(error.what()),
                          "Enforce failed. Expected 1UL < 0.12, but "
                          "received 1UL:1 >= 0.12:0.12."));
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_NOT_NULL, OK) {
  int* a = new int;
  PADDLE_ENFORCE_NOT_NULL(a);
  delete a;
}
TEST(ENFORCE_NOT_NULL, FAIL) {
  bool caught_exception = false;
  try {
    int* a = nullptr;
    PADDLE_ENFORCE_NOT_NULL(a);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(StringPiece(error.what()), "a should not be null"));
  }
  EXPECT_TRUE(caught_exception);
}

struct Dims {
  size_t dims_[4];

  bool operator==(const Dims& o) const {
    for (size_t i = 0; i < 4; ++i) {
      if (dims_[i] != o.dims_[i]) return false;
    }
    return true;
  }
};

std::ostream& operator<<(std::ostream& os, const Dims& d) {
  for (size_t i = 0; i < 4; ++i) {
    if (i == 0) {
      os << "[";
    }
    os << d.dims_[i];
    if (i == 4 - 1) {
      os << "]";
    } else {
      os << ", ";
    }
  }
  return os;
}

TEST(ENFORCE_USER_DEFINED_CLASS, EQ) {
  Dims a{{1, 2, 3, 4}}, b{{1, 2, 3, 4}};
  PADDLE_ENFORCE_EQ(a, b);
}

TEST(ENFORCE_USER_DEFINED_CLASS, NE) {
  Dims a{{1, 2, 3, 4}}, b{{5, 6, 7, 8}};
  ASSERT_THROW(PADDLE_ENFORCE_EQ(a, b), paddle::platform::EnforceNotMet);
}

TEST(EOF_EXCEPTION, THROW_EOF) {
  bool caught_eof = false;
  try {
    PADDLE_THROW_EOF();
  } catch (paddle::platform::EOFException error) {
    caught_eof = true;
    EXPECT_TRUE(HasPrefix(StringPiece(error.what()), "There is no next data."));
  }
  EXPECT_TRUE(caught_eof);
}
<commit_msg>fix enforce_test test=develop<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
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 <array>
#include <iostream>
#include <memory>

#include "gtest/gtest.h"
#include "paddle/fluid/platform/enforce.h"
#include "paddle/fluid/string/piece.h"

using StringPiece = paddle::string::Piece;
using paddle::string::HasPrefix;

TEST(ENFORCE, OK) {
  PADDLE_ENFORCE(true, "Enforce is ok %d now %f", 123, 0.345);
  size_t val = 1;
  const size_t limit = 10;
  PADDLE_ENFORCE(val < limit, "Enforce is OK too");
}

TEST(ENFORCE, FAILED) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE(false, "Enforce is not ok %d at all", 123);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(
        HasPrefix(StringPiece(error.what()), "Enforce is not ok 123 at all"));
  }
  EXPECT_TRUE(caught_exception);

  caught_exception = false;
  try {
    PADDLE_ENFORCE(false, "Enforce is not ok at all");
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(
        HasPrefix(StringPiece(error.what()), "Enforce is not ok at all"));
  }
  EXPECT_TRUE(caught_exception);

  caught_exception = false;
  try {
    PADDLE_ENFORCE(false);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_NE(std::string(error.what()).find("  at "), 0);
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE, NO_ARG_OK) {
  int a = 2;
  int b = 2;
  PADDLE_ENFORCE_EQ(a, b);
  // test enforce with extra message.
  PADDLE_ENFORCE_EQ(a, b, "some thing wrong %s", "info");
}

TEST(ENFORCE_EQ, NO_EXTRA_MSG_FAIL) {
  int a = 2;
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_EQ(a, 1 + 3);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected a == 1 + 3, but received a:2 != 1 + 3:4.");
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_EQ, EXTRA_MSG_FAIL) {
  int a = 2;
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_EQ(a, 1 + 3, "%s size not match", "their");
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    HasPrefix(StringPiece(error.what()),
              "Enforce failed. Expected a == 1 + 3, but received a:2 != 1 + "
              "3:4.\ntheir size not match");
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_NE, OK) {
  PADDLE_ENFORCE_NE(1, 2);
  PADDLE_ENFORCE_NE(1.0, 2UL);
}
TEST(ENFORCE_NE, FAIL) {
  bool caught_exception = false;

  try {
    // 2UL here to check data type compatible
    PADDLE_ENFORCE_NE(1.0, 1UL);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected 1.0 != 1UL, but received 1.0:1 == 1UL:1."))
        << error.what() << " does not have expected prefix";
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_GT, OK) { PADDLE_ENFORCE_GT(2, 1); }
TEST(ENFORCE_GT, FAIL) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_GT(1, 2UL);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected 1 > 2UL, but received 1:1 <= 2UL:2."));
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_GE, OK) {
  PADDLE_ENFORCE_GE(2, 2UL);
  PADDLE_ENFORCE_GE(3, 2UL);
  PADDLE_ENFORCE_GE(3, 2);
  PADDLE_ENFORCE_GE(3.21, 2UL);
}
TEST(ENFORCE_GE, FAIL) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_GE(1, 2UL);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected 1 >= 2UL, but received 1:1 < 2UL:2."));
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_LE, OK) {
  PADDLE_ENFORCE_LE(1, 1);
  PADDLE_ENFORCE_LE(1, 1UL);
  PADDLE_ENFORCE_LE(2, 3UL);
  PADDLE_ENFORCE_LE(2UL, 3);
  PADDLE_ENFORCE_LE(2UL, 3.2);
}
TEST(ENFORCE_LE, FAIL) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_GT(1, 2UL);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(
        StringPiece(error.what()),
        "Enforce failed. Expected 1 > 2UL, but received 1:1 <= 2UL:2."));
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_LT, OK) {
  PADDLE_ENFORCE_LT(3, 10);
  PADDLE_ENFORCE_LT(2, 3UL);
  PADDLE_ENFORCE_LT(2UL, 3);
}
TEST(ENFORCE_LT, FAIL) {
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_LT(1UL, 0.12);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(StringPiece(error.what()),
                          "Enforce failed. Expected 1UL < 0.12, but "
                          "received 1UL:1 >= 0.12:0.12."));
  }
  EXPECT_TRUE(caught_exception);
}

TEST(ENFORCE_NOT_NULL, OK) {
  int* a = new int;
  PADDLE_ENFORCE_NOT_NULL(a);
  delete a;
}
TEST(ENFORCE_NOT_NULL, FAIL) {
  bool caught_exception = false;
  try {
    int* a = nullptr;
    PADDLE_ENFORCE_NOT_NULL(a);
  } catch (paddle::platform::EnforceNotMet error) {
    caught_exception = true;
    EXPECT_TRUE(HasPrefix(StringPiece(error.what()), "a should not be null"));
  }
  EXPECT_TRUE(caught_exception);
}

struct Dims {
  size_t dims_[4];

  bool operator==(const Dims& o) const {
    for (size_t i = 0; i < 4; ++i) {
      if (dims_[i] != o.dims_[i]) return false;
    }
    return true;
  }
};

std::ostream& operator<<(std::ostream& os, const Dims& d) {
  for (size_t i = 0; i < 4; ++i) {
    if (i == 0) {
      os << "[";
    }
    os << d.dims_[i];
    if (i == 4 - 1) {
      os << "]";
    } else {
      os << ", ";
    }
  }
  return os;
}

TEST(ENFORCE_USER_DEFINED_CLASS, EQ) {
  Dims a{{1, 2, 3, 4}}, b{{1, 2, 3, 4}};
  PADDLE_ENFORCE_EQ(a, b);
}

TEST(ENFORCE_USER_DEFINED_CLASS, NE) {
  Dims a{{1, 2, 3, 4}}, b{{5, 6, 7, 8}};
  bool caught_exception = false;
  try {
    PADDLE_ENFORCE_EQ(a, b);
  } catch (paddle::platform::EnforceNotMet&) {
    caught_exception = true;
  }
  EXPECT_TRUE(caught_exception);
}

TEST(EOF_EXCEPTION, THROW_EOF) {
  bool caught_eof = false;
  try {
    PADDLE_THROW_EOF();
  } catch (paddle::platform::EOFException error) {
    caught_eof = true;
    EXPECT_TRUE(HasPrefix(StringPiece(error.what()), "There is no next data."));
  }
  EXPECT_TRUE(caught_eof);
}
<|endoftext|>


<commit_before>/***********************************************************************************************************************
 * Copyright (C) 2017 Andrew Zonenberg and contributors                                                                *
 *                                                                                *
 * This program 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 program 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 program; if not, you may   *
 * find one here:                                                                                *
 * https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt                                                              *
 * or you may search the http://www.gnu.org website for the version 2.1 license, or you may write to the Free Software *
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA                                      *
 **********************************************************************************************************************/

#include <log.h>
#include <Greenpak4.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

Greenpak4DAC::Greenpak4DAC(
	Greenpak4Device* device,
	unsigned int cbase_reg,
	unsigned int cbase_pwr,
	unsigned int cbase_insel,
	unsigned int cbase_aon,
	unsigned int dacnum)
	: Greenpak4BitstreamEntity(device, 0, -1, -1, -1)
		, m_vref(device->GetGround())
		, m_dacnum(dacnum)
		, m_cbaseReg(cbase_reg)
		, m_cbasePwr(cbase_pwr)
		, m_cbaseInsel(cbase_insel)
		, m_cbaseAon(cbase_aon)
{
	for(unsigned int i=0; i<8; i++)
		m_din[i] = device->GetGround();

	//Make our output a dual so we don't infer cross connections when driving reference-output pins
	//(even though we don't have a general fabric output)
	m_dual = new Greenpak4DualEntity(this);
}

Greenpak4DAC::~Greenpak4DAC()
{

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Accessors

bool Greenpak4DAC::IsUsed()
{
	return HasLoadsOnPort("VOUT");
}

string Greenpak4DAC::GetDescription() const
{
	char buf[128];
	snprintf(buf, sizeof(buf), "DAC_%u", m_dacnum);
	return string(buf);
}

vector<string> Greenpak4DAC::GetInputPorts() const
{
	vector<string> r;
	//no general fabric inputs
	return r;
}

void Greenpak4DAC::SetInput(string port, Greenpak4EntityOutput src)
{
	if(port == "VREF")
		m_vref = src;

	else if(port.find("DIN") == 0)
	{
		int b = 0;
		if(1 != sscanf(port.c_str(), "DIN[%d]", &b))
		{
			LogError("Greenpak4DAC: Malformed input name\n");
			return;
		}
		if( (b < 0) || (b >= 8) )
		{
			LogError("Greenpak4DAC: Out of range input index\n");
			return;
		}

		m_din[b] = src;
	}

	//ignore anything else silently (should not be possible since synthesis would error out)
}

Greenpak4EntityOutput Greenpak4DAC::GetInput(string port) const
{
	if(port == "VREF")
		return m_vref;
	else if(port.find("DIN") == 0)
	{
		int b = 0;
		if(1 != sscanf(port.c_str(), "DIN[%d]", &b))
		{
			LogError("Greenpak4DAC: Malformed input name\n");
			return Greenpak4EntityOutput(NULL);
		}
		if( (b < 0) || (b >= 8) )
		{
			LogError("Greenpak4DAC: Out of range input index\n");
			return Greenpak4EntityOutput(NULL);
		}
		return m_din[b];
	}
	else
		return Greenpak4EntityOutput(NULL);
}

vector<string> Greenpak4DAC::GetOutputPorts() const
{
	vector<string> r;
	//no general fabric outputs
	return r;
}

unsigned int Greenpak4DAC::GetOutputNetNumber(string /*port*/)
{
	//no general fabric outputs
	return -1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Serialization

bool Greenpak4DAC::CommitChanges()
{
	//No configuration
	return true;
}

bool Greenpak4DAC::Load(bool* /*bitstream*/)
{
	//TODO: Do our inputs
	LogError("Unimplemented\n");
	return false;
}

bool Greenpak4DAC::Save(bool* bitstream)
{
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// INPUT BUS

	//If VREF is ground, then the DAC is unused, leave config blank
	if(m_vref.IsPowerRail() && !m_vref.GetPowerRailValue())
		return true;

	//VREF must be from a GP_VREF driving 1v0 for now
	//Sanity check that
	//TODO: DAC1 has a 50 mV offset, so the two are NOT equivalent!
	if(!m_vref.IsVoltageReference())
	{
		LogError("DRC: DAC should have a voltage reference driving VREF, but something else was supplied instead\n");
		return false;
	}
	auto v = dynamic_cast<Greenpak4VoltageReference*>(m_vref.GetRealEntity());
	if(!v->IsConstantVoltage() || (v->GetOutputVoltage() != 1000) )
	{
		LogError("DRC: DAC should be driven by a constant 1000 mV reference\n");
		return false;
	}

	//Verify that all 8 bits of each input came from the same entity
	//TODO: verify bit ordering?
	for(int i=1; i<8; i++)
	{
		if(m_din[i].GetRealEntity() != m_din[0].GetRealEntity())
		{
			LogError("All bits of GP_DAC DIN must come from the same source node\n");
			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// CONFIGURATION

	//Apparently DAC1 will die a horrible death if the ADC analog part is on
	//so don't turn it on even though the datasheet kinda implies we might need it?

	//Turn our DAC on
	bitstream[m_cbasePwr] = true;

	//SLG4662x: If we're using DAC1, turn on DAC0
	//This is a legal no-op in other situations.
	//TODO: maybe add a routing preference so that DAC0 is preferred to DAC1 in a single-DAC design
	//(otherwise we're wasting a bit of power)
	bitstream[m_cbaseAon] = true;

	if(m_device->GetPart() == Greenpak4Device::GREENPAK4_SLG46140)
		LogError("Greenpak4DAC: not implemented for 46140 yet\n");

	//Input selector
	//WTF, the config is flipped from DAC0 to DAC1??? (see SLG46620V table 40)
	//This also applies to the SLG46140 (see SLG46140 table 28).
	bool dinPower = (m_din[0].IsPowerRail());
	if(m_dacnum == 0)
		bitstream[m_cbaseInsel] = !dinPower;
	else
		bitstream[m_cbaseInsel] = dinPower;

	//Constant input voltage
	if(dinPower)
	{
		for(unsigned int i=0; i<8; i++)
			bitstream[m_cbaseReg + i] = m_din[i].GetPowerRailValue();
	}

	//Input is coming from DCMP.
	//Rely on the DCMP input mux for this, nothing for us to do.
	//Set the input voltage to zero just so the bitstream is deterministic.
	else
	{
		for(unsigned int i=0; i<8; i++)
			bitstream[m_cbaseReg + i] = false;
	}

	return true;
}
<commit_msg>Greenpak4DAC: Added load support for unused DACs (active ones not supported yet)<commit_after>/***********************************************************************************************************************
 * Copyright (C) 2017 Andrew Zonenberg and contributors                                                                *
 *                                                                                *
 * This program 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 program 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 program; if not, you may   *
 * find one here:                                                                                *
 * https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt                                                              *
 * or you may search the http://www.gnu.org website for the version 2.1 license, or you may write to the Free Software *
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA                                      *
 **********************************************************************************************************************/

#include <log.h>
#include <Greenpak4.h>

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

Greenpak4DAC::Greenpak4DAC(
	Greenpak4Device* device,
	unsigned int cbase_reg,
	unsigned int cbase_pwr,
	unsigned int cbase_insel,
	unsigned int cbase_aon,
	unsigned int dacnum)
	: Greenpak4BitstreamEntity(device, 0, -1, -1, -1)
		, m_vref(device->GetGround())
		, m_dacnum(dacnum)
		, m_cbaseReg(cbase_reg)
		, m_cbasePwr(cbase_pwr)
		, m_cbaseInsel(cbase_insel)
		, m_cbaseAon(cbase_aon)
{
	for(unsigned int i=0; i<8; i++)
		m_din[i] = device->GetGround();

	//Make our output a dual so we don't infer cross connections when driving reference-output pins
	//(even though we don't have a general fabric output)
	m_dual = new Greenpak4DualEntity(this);
}

Greenpak4DAC::~Greenpak4DAC()
{

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Accessors

bool Greenpak4DAC::IsUsed()
{
	return HasLoadsOnPort("VOUT");
}

string Greenpak4DAC::GetDescription() const
{
	char buf[128];
	snprintf(buf, sizeof(buf), "DAC_%u", m_dacnum);
	return string(buf);
}

vector<string> Greenpak4DAC::GetInputPorts() const
{
	vector<string> r;
	//no general fabric inputs
	return r;
}

void Greenpak4DAC::SetInput(string port, Greenpak4EntityOutput src)
{
	if(port == "VREF")
		m_vref = src;

	else if(port.find("DIN") == 0)
	{
		int b = 0;
		if(1 != sscanf(port.c_str(), "DIN[%d]", &b))
		{
			LogError("Greenpak4DAC: Malformed input name\n");
			return;
		}
		if( (b < 0) || (b >= 8) )
		{
			LogError("Greenpak4DAC: Out of range input index\n");
			return;
		}

		m_din[b] = src;
	}

	//ignore anything else silently (should not be possible since synthesis would error out)
}

Greenpak4EntityOutput Greenpak4DAC::GetInput(string port) const
{
	if(port == "VREF")
		return m_vref;
	else if(port.find("DIN") == 0)
	{
		int b = 0;
		if(1 != sscanf(port.c_str(), "DIN[%d]", &b))
		{
			LogError("Greenpak4DAC: Malformed input name\n");
			return Greenpak4EntityOutput(NULL);
		}
		if( (b < 0) || (b >= 8) )
		{
			LogError("Greenpak4DAC: Out of range input index\n");
			return Greenpak4EntityOutput(NULL);
		}
		return m_din[b];
	}
	else
		return Greenpak4EntityOutput(NULL);
}

vector<string> Greenpak4DAC::GetOutputPorts() const
{
	vector<string> r;
	//no general fabric outputs
	return r;
}

unsigned int Greenpak4DAC::GetOutputNetNumber(string /*port*/)
{
	//no general fabric outputs
	return -1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Serialization

bool Greenpak4DAC::CommitChanges()
{
	//No configuration
	return true;
}

bool Greenpak4DAC::Load(bool* bitstream)
{
	//TODO: VREF
	LogWarning("TODO: VREF configuration for Greenpak4DAC\n");

	//If DAC is disabled, set VREF to ground (we're not used)
	if(!bitstream[m_cbasePwr])
	{
		m_vref = m_device->GetGround();
		return true;
	}

	//ignore cbaseAon for now

	if(m_device->GetPart() == Greenpak4Device::GREENPAK4_SLG46140)
		LogError("Greenpak4DAC: not implemented for 46140 yet\n");

	//Input selector

	/*
	//WTF, the config is flipped from DAC0 to DAC1??? (see SLG46620V table 40)
	//This also applies to the SLG46140 (see SLG46140 table 28).
	bool dinPower = (m_din[0].IsPowerRail());
	if(m_dacnum == 0)
		bitstream[m_cbaseInsel] = !dinPower;
	else
		bitstream[m_cbaseInsel] = dinPower;

	//Constant input voltage
	if(dinPower)
	{
		for(unsigned int i=0; i<8; i++)
			bitstream[m_cbaseReg + i] = m_din[i].GetPowerRailValue();
	}

	//Input is coming from DCMP.
	//Rely on the DCMP input mux for this, nothing for us to do.
	//Set the input voltage to zero just so the bitstream is deterministic.
	else
	{
		for(unsigned int i=0; i<8; i++)
			bitstream[m_cbaseReg + i] = false;
	}

	*/

	//TODO: Do our inputs
	LogError("Unimplemented\n");
	return false;
}

bool Greenpak4DAC::Save(bool* bitstream)
{
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// INPUT BUS

	//If VREF is ground, then the DAC is unused, leave config blank
	if(m_vref.IsPowerRail() && !m_vref.GetPowerRailValue())
		return true;

	//VREF must be from a GP_VREF driving 1v0 for now
	//Sanity check that
	//TODO: DAC1 has a 50 mV offset, so the two are NOT equivalent!
	if(!m_vref.IsVoltageReference())
	{
		LogError("DRC: DAC should have a voltage reference driving VREF, but something else was supplied instead\n");
		return false;
	}
	auto v = dynamic_cast<Greenpak4VoltageReference*>(m_vref.GetRealEntity());
	if(!v->IsConstantVoltage() || (v->GetOutputVoltage() != 1000) )
	{
		LogError("DRC: DAC should be driven by a constant 1000 mV reference\n");
		return false;
	}

	//Verify that all 8 bits of each input came from the same entity
	//TODO: verify bit ordering?
	for(int i=1; i<8; i++)
	{
		if(m_din[i].GetRealEntity() != m_din[0].GetRealEntity())
		{
			LogError("All bits of GP_DAC DIN must come from the same source node\n");
			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// CONFIGURATION

	//Apparently DAC1 will die a horrible death if the ADC analog part is on
	//so don't turn it on even though the datasheet kinda implies we might need it?

	//Turn our DAC on
	bitstream[m_cbasePwr] = true;

	//SLG4662x: If we're using DAC1, turn on DAC0
	//This is a legal no-op in other situations.
	//TODO: maybe add a routing preference so that DAC0 is preferred to DAC1 in a single-DAC design
	//(otherwise we're wasting a bit of power)
	bitstream[m_cbaseAon] = true;

	if(m_device->GetPart() == Greenpak4Device::GREENPAK4_SLG46140)
		LogError("Greenpak4DAC: not implemented for 46140 yet\n");

	//Input selector
	//WTF, the config is flipped from DAC0 to DAC1??? (see SLG46620V table 40)
	//This also applies to the SLG46140 (see SLG46140 table 28).
	bool dinPower = (m_din[0].IsPowerRail());
	if(m_dacnum == 0)
		bitstream[m_cbaseInsel] = !dinPower;
	else
		bitstream[m_cbaseInsel] = dinPower;

	//Constant input voltage
	if(dinPower)
	{
		for(unsigned int i=0; i<8; i++)
			bitstream[m_cbaseReg + i] = m_din[i].GetPowerRailValue();
	}

	//Input is coming from DCMP.
	//Rely on the DCMP input mux for this, nothing for us to do.
	//Set the input voltage to zero just so the bitstream is deterministic.
	else
	{
		for(unsigned int i=0; i<8; i++)
			bitstream[m_cbaseReg + i] = false;
	}

	return true;
}
<|endoftext|>