text:
#include <cctype>
#include <iostream>
#include <sstream>
#include <vector>
#include <boost/tokenizer.hpp>
#include "Animation.hpp"
#include "Colours.hpp"
#include "Conversion.hpp"
#include "CursesAnimationFactory.hpp"
#include "CursesProperties.hpp"
#include "DisplaySettings.hpp"
#include "EquipmentTextKeys.hpp"
#include "Game.hpp"
#include "Log.hpp"
#include "MapUtils.hpp"
#include "Screen.hpp"
#include "CursesConstants.hpp"
#include "CursesDisplay.hpp"
#include "MapDisplayArea.hpp"
#include "OptionsComponent.hpp"
#include "Serialize.hpp"
#include "Setting.hpp"
#include "StringTable.hpp"
#include "TextKeys.hpp"

using namespace std;

const int CURSES_NUM_BASE_COLOURS = 8;
const int CURSES_NUM_TOTAL_COLOURS = 16;

// Assumption: screens is empty (prototype object), and so this is safe.
Display* CursesDisplay::clone()
{
  return new CursesDisplay(*this);
}

CursesDisplay::CursesDisplay()
: TERMINAL_MAX_ROWS(0),
TERMINAL_MAX_COLS(0),
FIELD_SPACE(2),
MSG_BUFFER_LAST_Y(0),
MSG_BUFFER_LAST_X(0),
message_buffer_screen(nullptr),
can_use_colour(false),
mono_colour(Colour::COLOUR_UNDEFINED),
cursor_mode(1) /* normal visibility */
{
}

bool CursesDisplay::operator==(const CursesDisplay& cd) const
{
  bool result = true;

  result = result && (TERMINAL_MAX_ROWS == cd.TERMINAL_MAX_ROWS);
  result = result && (TERMINAL_MAX_COLS == cd.TERMINAL_MAX_COLS);
  result = result && (FIELD_SPACE == cd.FIELD_SPACE);
  result = result && (MSG_BUFFER_LAST_Y == cd.MSG_BUFFER_LAST_Y);
  result = result && (MSG_BUFFER_LAST_X == cd.MSG_BUFFER_LAST_X);
  result = result && (screens.size() == cd.screens.size());

  if (result)
  {
    for (uint i = 0; i < screens.size(); i++)
    {
      WINDOW* screen = screens.at(i);
      WINDOW* cd_screen = cd.screens.at(i);

      result = result && screen && cd_screen && (memcmp(screen, cd_screen, sizeof(*screen)) == 0);
    }
  }

  result = result && (prompt_processor == cd.prompt_processor);
  result = result && (can_use_colour == cd.can_use_colour);

  return result;
}

// Get the current display width
unsigned int CursesDisplay::get_width() const
{
  return TERMINAL_MAX_COLS;
}

// Get the current display height
unsigned int CursesDisplay::get_height() const
{
  return TERMINAL_MAX_ROWS;
}

// Create a screen and return it.
WINDOW* CursesDisplay::create_screen(int height, int width, int start_row, int start_col)
{
  WINDOW* screen;

	screen = newwin(height, width, start_row, start_col);
	keypad(screen, TRUE);

  // Because screens don't display the player (or have any other meaningful reason to have
  // the cursor present), turn off the cursor.
  curs_set(0);
	wrefresh(screen);

	return screen;
}

// Delete the given window.
void CursesDisplay::destroy_screen(WINDOW *screen)
{
  Log::instance().debug("CursesDisplay::destroy_screen - destroying current screen.");
	delwin(screen);
	screen = nullptr;
}

// Get whether the terminal can support colour.  False by
// default, until SL actually tries to detect the terminal's
// colour capabilities.  This can be turned off in the ini
// settings, also.
bool CursesDisplay::uses_colour() const
{
  string colour_prop = get_property(DisplaySettings::DISPLAY_SETTING_COLOUR);
  bool colour = String::to_bool(colour_prop);

  return colour;
}

// If the cursor mode has been set in the properties, use that.
// Otherwise, use the default.
int CursesDisplay::get_cursor_mode(const CursorSettings cs) const
{
  int mode = cursor_mode;

  if (cs == CursorSettings::CURSOR_SETTINGS_SHOW_CURSOR)
  {
    mode = 1; /* show cursor */
  }
  else
  {
    auto p_it = display_properties.find(CursesProperties::CURSES_PROPERTIES_CURSOR_MODE);

    if (p_it != display_properties.end())
    {
      mode = String::to_int(p_it->second);
    }
  }

  return mode;
}

// Initialize the base ncurses colours.
void CursesDisplay::initialize_colours()
{
  vector<short int> colours{COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE};

  short int pair_counter = 1;
  for (auto bg_colour : colours)
  {
    for (auto fg_colour : colours)
    {
      init_pair(pair_counter, fg_colour, bg_colour);
      pair_counter++;
    }

    pair_counter += CURSES_NUM_BASE_COLOURS;
  }
}

// Turn on colour using attron.
//
// Note that the enable/disable colour need to match!  Don't pass different colours!
void CursesDisplay::enable_colour(const int selected_colour, WINDOW* window)
{
  if (uses_colour())
  {
    set_colour(selected_colour, window);
  }
  else
  {
    // Do we need to set the "monochrome" display to a particular colour?
    // Dark red, like my thirteen-year-old-self's old QBASIC games?
    // Bright green, like an old Apple ][?
    if (mono_colour == Colour::COLOUR_UNDEFINED)
    {
      // Set up the monochrome colour on initial use from the properties
      // set by the game.
      auto m_it = display_properties.find(DisplaySettings::DISPLAY_SETTING_MONOCHROME_COLOUR);

      if (m_it != display_properties.end())
      {
        int mono_i = String::to_int(m_it->second);
        mono_colour = static_cast<Colour>(mono_i);
      }
    }

    set_colour(static_cast<int>(mono_colour), window);
  }
}

// Set the display colour without actually checking for monochrome.
void CursesDisplay::set_colour(const int selected_colour, WINDOW* window)
{
  if ((selected_colour % CURSES_NUM_TOTAL_COLOURS) > static_cast<int>(Colour::COLOUR_WHITE))
  {
    int actual_colour = selected_colour - static_cast<int>(Colour::COLOUR_BOLD_BLACK);
    wattron(window, COLOR_PAIR(actual_colour + 1));
    wattron(window, A_BOLD);
    return;
  }

  wattron(window, COLOR_PAIR(selected_colour + 1));
}

// Turn off colour using attroff.
void CursesDisplay::disable_colour(const int selected_colour, WINDOW* window)
{
  if (uses_colour())
  {
    if ((selected_colour % CURSES_NUM_TOTAL_COLOURS) > static_cast<int>(Colour::COLOUR_WHITE))
    {
      int actual_colour = selected_colour - static_cast<int>(Colour::COLOUR_BOLD_BLACK);
      wattroff(window, COLOR_PAIR(actual_colour+1));
      wattroff(window, A_BOLD);
      return;
    }

    wattroff(window, COLOR_PAIR(selected_colour+1));
  }
}

// The Display function - hooks up to clear_message_buffer
void CursesDisplay::clear_messages()
{
  clear_message_buffer();
}

// Clear the message buffer and reset the cursor.  The message buffer is always lines 0 and 1.
int CursesDisplay::clear_message_buffer()
{
  int return_val;
  WINDOW* screen = get_message_buffer_screen();

  wmove(screen, 0, 0);
  wclrtoeol(screen);

  wmove(screen, 1, 0);
  return_val = wclrtoeol(screen);

  // Reset the internal state
  MSG_BUFFER_LAST_Y = 0;
  MSG_BUFFER_LAST_X = 0;

  // Reset cursor to original position
  wmove(screen, MSG_BUFFER_LAST_Y, MSG_BUFFER_LAST_X);

  return return_val;
}

WINDOW* CursesDisplay::get_message_buffer_screen()
{
  WINDOW* screen = stdscr;

  if (message_buffer_screen != nullptr)
  {
    screen = message_buffer_screen;
  }

  return screen;
}

// Halt processing and force user input to continue.
void CursesDisplay::halt_messages()
{
  WINDOW* screen = get_message_buffer_screen();

  wmove(screen, MSG_BUFFER_LAST_Y, MSG_BUFFER_LAST_X);
  wrefresh(screen);
  wgetch(screen);
}

// Refresh the display's size.
//
//
// JCD FIXME: This doesn't seem to work.
//
// Fix this up once SOTW is compiling on Linux/FreeBSD and I can
// resize terminals.
//
void CursesDisplay::refresh_terminal_size()
{
  getmaxyx(stdscr, TERMINAL_MAX_ROWS, TERMINAL_MAX_COLS);
}

// Set up the Curses-based display.
bool CursesDisplay::create()
{
  bool creation_success = true;

  initscr();
  keypad(stdscr, TRUE);
  nl();
  noecho(); // Don't echo the user input.
  raw(); // pass control characters to the program.
  curs_set(0); // Cursor invisible.  Doesn't seem to work in Cygwin.  Just like colour redefinition.  Fucking Cygwin.

  if (has_colors() == TRUE)
  {
    can_use_colour = true;
    start_color();
    initialize_colours();
  }

  refresh_terminal_size();

  if ((TERMINAL_MAX_ROWS < 25) || (TERMINAL_MAX_COLS < 80))
  {
    printw("Shadow of the Wyrm requires a terminal of 80x25 or larger.\n");
    creation_success = false;
  }

  refresh();

  return creation_success;
}

// Do anything necessary to tear down the Curses-based display.
void CursesDisplay::tear_down()
{
  refresh();
  endwin();
}

// Clear the display (in practice, stdscr).
void CursesDisplay::clear_display()
{
  clear();
}

void CursesDisplay::add_alert(const string& message, const bool require_input)
{
  message_buffer_screen = get_current_screen();

  int prev_curs_state = curs_set(1);
  clear_message_buffer();
  add_message(message, Colour::COLOUR_BOLD_RED, false);
  wrefresh(message_buffer_screen);

  if (require_input)
  {
    wgetch(message_buffer_screen);
    clear_message_buffer();
  }

  curs_set(prev_curs_state);

  message_buffer_screen = nullptr;
}

// Clear the message buffer, and then add a message to display to
// the user.  If it's very long, "..." it.
void CursesDisplay::add_message(const string& message, const bool reset_cursor)
{
  add_message(message, Colour::COLOUR_WHITE, reset_cursor);
}

void CursesDisplay::add_message(const string& to_add_message, const Colour colour, const bool reset_cursor)
{
  string message = to_add_message;
  WINDOW* screen = get_message_buffer_screen();

  // Replace any single instances of "%", as these will cause a crash when
  // the corresponding parameters are not present in printw.
  boost::replace_all(message, "%", "%%");

  int orig_curs_y, orig_curs_x;
  getyx(screen, orig_curs_y, orig_curs_x);

  uint cur_y, cur_x;

  if (reset_cursor)
  {
    clear_message_buffer();
    wmove(screen, 0, 0);
  }
  else
  {
    wmove(screen, MSG_BUFFER_LAST_Y, MSG_BUFFER_LAST_X);
  }

  boost::char_separator<char> separator(" ", " ", boost::keep_empty_tokens); // Keep the tokens!
  boost::tokenizer<boost::char_separator<char>> tokens(message, separator);

  enable_colour(static_cast<int>(colour), screen);

  for (boost::tokenizer<boost::char_separator<char>>::iterator t_iter = tokens.begin(); t_iter != tokens.end(); t_iter++)
  {
    getyx(screen, MSG_BUFFER_LAST_Y, MSG_BUFFER_LAST_X);

    string current_token = *t_iter;
    getyx(screen, cur_y, cur_x);

    if (cur_y == 0)
    {
      if ((cur_x + current_token.length()) > (TERMINAL_MAX_COLS-1))
      {
        // Move to the second line of the buffer
        wmove(screen, 1, 0);
        getyx(screen, cur_y, cur_x);
      }
    }
    else
    {
      if ((cur_x + current_token.length()) > (TERMINAL_MAX_COLS) - 4)
      {
        wmove(screen, 1, TERMINAL_MAX_COLS-4);

        disable_colour(static_cast<int>(colour), screen);
        wprintw(screen, "...");
        wgetch(screen);
        enable_colour(static_cast<int>(colour), screen);

        clear_message_buffer();
        getyx(screen, cur_y, cur_x);
      }
    }

    // If the user presses enter
    if (cur_y > CursesConstants::MESSAGE_BUFFER_END_ROW)
    {
      cur_y--;
    }

    if (cur_x == 0)
    {
      if (String::is_whitespace(current_token))
      {
        // If we're at the start of a new line in the buffer, and the string
        // is entirely whitespace, skip it.
        continue;
      }
    }

    wprintw(screen, current_token.c_str());
  }

  // Ensure that the last coordinates from the message buffer are up to date.
  getyx(screen, MSG_BUFFER_LAST_Y, MSG_BUFFER_LAST_X);

  // Reset the cursor.
  if (reset_cursor)
  {
    wmove(screen, orig_curs_y, orig_curs_x);
  }

  disable_colour(static_cast<int>(colour), screen);

  // This is commented out because every so often I wonder why and it's always
  // because if I include it, the cursor jumps to the message buffer and back,
  // which is ugly.
  // wrefresh(screen);
}

string CursesDisplay::add_message_with_prompt(const string& message, const Colour colour, const bool reset_prompt)
{
  string prompt_result;

  // Add the message and then get the prompt value.
  // The assumption is that this should only ever (ever!  EVAR!) get called
  // from stdscr, since that's where the message manager is actually
  // displayed!
  add_message(message, colour, reset_prompt);
  prompt_result = prompt_processor.get_user_string(stdscr, true /* allow arbitrary non-alphanumeric characters */);

  return prompt_result;
}

// Draw the specified Display in the term.  This'll be a simplified
// map that contains only the information needed by the display -
// no specific creature, etc., data.
void CursesDisplay::draw(const DisplayMap& current_map, const CursorSettings cs)
{
  refresh_terminal_size();

  DisplayTile display_tile;
  Coordinate map_coords;

  Dimensions d = current_map.size();
  unsigned int map_rows = d.get_y();
  unsigned int map_cols = d.get_x();

  for (unsigned int terminal_row = CursesConstants::MAP_START_ROW; terminal_row < map_rows + CursesConstants::MAP_START_ROW; terminal_row++)
  {
    for (unsigned int terminal_col = CursesConstants::MAP_START_COL; terminal_col < map_cols + CursesConstants::MAP_START_COL; terminal_col++)
    {
      map_coords.first = terminal_row - CursesConstants::MAP_START_ROW;
      map_coords.second = terminal_col - CursesConstants::MAP_START_COL;

      DisplayTile tile = current_map.at(map_coords);
      draw_coordinate(tile, terminal_row, terminal_col);
    }
  }

  Coordinate cursor_coord = current_map.get_cursor_coordinate();

  // Since we're drawing the map (with, presumably, the player) we need the cursor present to show the
  // position of the player's character.
  curs_set(get_cursor_mode(cs));
  move(cursor_coord.first+CursesConstants::MAP_START_ROW, cursor_coord.second+CursesConstants::MAP_START_COL);
  wredrawln(stdscr, CursesConstants::MAP_START_ROW, map_rows);
  refresh();
}

// Refreshes the contents of the current window.
void CursesDisplay::redraw()
{
  if (screens.empty())
  {
    refresh();
  }
  else
  {
    wrefresh(screens.back());
  }
}

void CursesDisplay::draw_update_map(const DisplayMap& update_map, const CursorSettings cs)
{
  DisplayTile display_tile;
  Coordinate map_coords;

  DisplayMapType tiles = update_map.get_tiles();

  uint terminal_row, terminal_col;

  for (DisplayMapType::value_type& tile : tiles)
  {
    Coordinate map_coords = MapUtils::convert_map_key_to_coordinate(tile.first);
    DisplayTile dtile = tile.second;

    terminal_row = CursesConstants::MAP_START_ROW + map_coords.first;
    terminal_col = CursesConstants::MAP_START_COL + map_coords.second;

    draw_coordinate(dtile, terminal_row, terminal_col);
  }

  Coordinate cursor_coord = update_map.get_cursor_coordinate();

  // Since we're drawing the map (with, presumably, the player) we need the cursor present to show the
  // position of the player's character.
  curs_set(get_cursor_mode(cs));
  move(cursor_coord.first+CursesConstants::MAP_START_ROW, cursor_coord.second+CursesConstants::MAP_START_COL);
  wredrawln(stdscr, CursesConstants::MAP_START_ROW, update_map.size().get_y());
}

// draw_tile is called externally from a Display to draw a particular engine
// coordinate.  The display takes the given y and x, adds the appropriate offsets,
// and then calls its own internal function to draw the given DisplayTile at the
// correct location on-screen.
void CursesDisplay::draw_tile(const uint y, const uint x, const DisplayTile& tile)
{
  // Turn off the cursor temporarily - higher level redraw functions will enable it
  // and place it correctly.
  curs_set(0);

  uint terminal_row = CursesConstants::MAP_START_ROW + y;
  uint terminal_col = CursesConstants::MAP_START_COL + x;

  draw_coordinate(tile, terminal_row, terminal_col);

  refresh();
}

AnimationFactoryPtr CursesDisplay::create_animation_factory() const
{
  AnimationFactoryPtr curses_animation_factory = std::make_shared<CursesAnimationFactory>();
  return curses_animation_factory;
}

void CursesDisplay::draw_animation(const Animation& animation)
{
  vector<AnimationInstructionPtr> animation_instructions = animation.get_animation_instructions();

  for(AnimationInstructionPtr& instruct : animation_instructions)
  {
    if (instruct)
    {
      instruct->execute(this);
    }
  }
}

void CursesDisplay::draw_coordinate(const DisplayTile& display_tile, const unsigned int terminal_row, const unsigned int terminal_col)
{
  int colour = display_tile.get_colour();

  // Maps are always drawn on ncurses' stdscr.
  enable_colour(colour, stdscr);
  mvprintw(terminal_row, terminal_col, "%c", display_tile.get_symbol());
  disable_colour(colour, stdscr);
}

// Get the size of the map display in "tiles"
MapDisplayArea CursesDisplay::get_map_display_area()
{
  MapDisplayArea map_display_area;

  map_display_area.set_width(TERMINAL_MAX_COLS);
  map_display_area.set_height(TERMINAL_MAX_ROWS - 5); // JCD FIXME: Remove magic num later

  return map_display_area;
}

// Draw the specified screen, full-screen.
string CursesDisplay::display_screen(const Screen& current_screen)
{
  string result;
  refresh_terminal_size();

  MenuWrapper wrapper;
  WINDOW* screen_window = create_screen(TERMINAL_MAX_ROWS, TERMINAL_MAX_COLS, 0, 0);

  screens.push_back(screen_window);

  int current_row = 0;
  int current_col = 0;

  // Display the header if the text is defined.  Some screens (like the quest list,
  // etc) will have this defined, while others (such as the new character-type
  // screens) will not.
  string title_text_sid = current_screen.get_title_text_sid();
  string header_text = StringTable::get(title_text_sid);

  // The title might not be an actual resource string, but instead an already-
  // formatted message.  Use that if the lookup is empty but the sid is not.
  if (!title_text_sid.empty() && header_text.empty())
  {
    header_text = title_text_sid;
  }

  uint num_pages = current_screen.get_num_pages();

  if (num_pages > 1)
  {
    ostringstream ss;

    ss << header_text << " (" << current_screen.get_current_page_number() << "/" << num_pages << ")";
    header_text = ss.str();
  }

  if (!header_text.empty())
  {
    display_header(header_text, screen_window, current_row);

    // Always allow for some space between the title and the components of the
    // screen, regardless of what the screen has set for line spacing.
    current_row += 2;
  }

  vector<ScreenComponentPtr> components = current_screen.get_current_page();
  uint line_incr = current_screen.get_line_increment();

  uint csize = components.size();
  for(uint i = 0; i < csize; i++)
  {
    ScreenComponentPtr component = components.at(i);
    ComponentAlignment ca = component->get_spacing_after();

    // Check to see if we should override the screen's line increment value.
    if (ca.get_override_default())
    {
      line_incr = ca.get_value();
    }

    if (component)
    {
      TextComponentPtr tc = dynamic_pointer_cast<TextComponent>(component);

      if (tc != nullptr)
      {
        display_text_component(screen_window, &current_row, &current_col, tc, line_incr);
      }
      else
      {
        OptionsComponentPtr oc = dynamic_pointer_cast<OptionsComponent>(component);

        if (oc != nullptr)
        {
          // Process the options...
          display_options_component(screen_window, &current_row, &current_col, oc);

          // Add them so that the prompt processor knows about the options in this set.
          wrapper.add_options(oc);
        }
      }

      // After each line, check to see if we need to throw up a prompt because
      // of hitting the end of the screen, but only if there's still stuff to
      // display.
      if (current_row == (static_cast<int>(TERMINAL_MAX_ROWS) - 1) && (i != csize-1))
      {
        PromptPtr prompt = current_screen.get_prompt();
        prompt_processor.show_prompt(screen_window, prompt, current_row, current_col, TERMINAL_MAX_ROWS, TERMINAL_MAX_COLS);

        result = prompt_processor.get_prompt(screen_window, wrapper, prompt);

        wrefresh(screen_window);

        // We've shown the prompt, the user has intervened, and so
        // now we need to clear the window, reset the current row
        // back to 0 and keep displaying stuff from the screen.
        wclear(screen_window);
        current_row = 0;
      }
    }
  }

  // Done!  Add an appropriate prompt.
  PromptPtr prompt = current_screen.get_prompt();
  prompt_processor.show_prompt(screen_window, prompt, current_row, current_col, TERMINAL_MAX_ROWS, TERMINAL_MAX_COLS);

  result = prompt_processor.get_prompt(screen_window, wrapper, prompt);

  wrefresh(screen_window);

  return result;
}

// Show confirmation text - use the message buffer.
void CursesDisplay::confirm(const string& confirmation_message)
{
  add_message(confirmation_message, Colour::COLOUR_WHITE, false);
}

void CursesDisplay::display_text_component(WINDOW* window, int* row, int* col, TextComponentPtr tc, const uint line_incr)
{
  int cur_col = *col;

  if (tc != nullptr)
  {
    vector<pair<string, Colour>> current_text = tc->get_text();

    for (auto& text_line : current_text)
    {
      string cur_text = text_line.first;
      boost::replace_all(cur_text, "%", "%%");

      enable_colour(static_cast<int>(text_line.second), window);
      mvwprintw(window, *row, cur_col, cur_text.c_str());
      disable_colour(static_cast<int>(text_line.second), window);

      cur_col += cur_text.size();
    }

    *row += line_incr;
  }
}

void CursesDisplay::display_options_component(WINDOW* window, int* row, int* col, OptionsComponentPtr oc)
{
  vector<Option> options = oc->get_options();
  vector<string> option_descriptions = oc->get_option_descriptions();
  bool show_desc = oc->get_show_option_descriptions();

  size_t num_options = options.size();
  size_t num_option_desc = option_descriptions.size();

  int options_added = 0;

  if (!options.empty())
  {
    int temp_row = *row;

    for (unsigned int i = 0; i < num_options; i++)
    {
      Option current_option = options.at(i);
      Colour option_colour = current_option.get_colour();
      TextComponentPtr option_text = current_option.get_description();
      string option_desc;

      // Only get the description if we should show one and if one has been set.
      if (show_desc && (i < num_option_desc))
      {
        option_desc = option_descriptions.at(i);

        if (!option_desc.empty())
        {
          option_text->add_text(" - ");
          option_text->add_text(option_desc);
        }
      }

      enable_colour(static_cast<int>(option_colour), window);

      ostringstream display_option;
      display_option << "  [" << current_option.get_id_char() << "] ";

      int ocol = *col;

      string display_option_s = display_option.str();
      boost::replace_all(display_option_s, "%", "%%");

      mvwprintw(window, *row, ocol, display_option_s.c_str());

      getyx(window, *row, ocol);

      TextComponentPtr text = current_option.get_description();

      // JCD FIXME make 1 a constant later -
      // there should always be a single line break between options.
      display_text_component(window, row, &ocol, text, 1);
      disable_colour(static_cast<int>(option_colour), window);

      options_added++;
      temp_row++;
    }
  }

  // No need to update *row
  // It will have been taken care of when displaying the TextComponent.
}

void CursesDisplay::clear_screen()
{
  if (!screens.empty())
  {
    WINDOW* current_screen_window = screens.back();
    wclear(current_screen_window);
    wrefresh(current_screen_window);
    destroy_screen(current_screen_window);

    screens.pop_back();
  }
}

// Display the player data
void CursesDisplay::display(const DisplayStatistics& player_stats)
{
  Game& game = Game::instance();
  Settings& settings = game.get_settings_ref();

  string name         = player_stats.get_name();
  string synopsis     = player_stats.get_synopsis();

  pair<string, Colour> strength     = player_stats.get_strength();
  pair<string, Colour> dexterity    = player_stats.get_dexterity();
  pair<string, Colour> agility      = player_stats.get_agility();
  pair<string, Colour> health       = player_stats.get_health();
  pair<string, Colour> intelligence = player_stats.get_intelligence();
  pair<string, Colour> willpower    = player_stats.get_willpower();
  pair<string, Colour> charisma     = player_stats.get_charisma();

  string speed        = player_stats.get_speed();

  string level        = player_stats.get_level();
  string defence      = player_stats.get_defence();

  pair<string, Colour> alignment = player_stats.get_alignment();

  string hit_points   = player_stats.get_hit_points();
  Colour hit_points_colour = String::to_colour(settings.get_setting(Setting::DEFAULT_HP_COLOUR), Colour::COLOUR_WHITE);

  string arc_points   = player_stats.get_arcana_points();
  Colour arc_points_colour = String::to_colour(settings.get_setting(Setting::DEFAULT_AP_COLOUR), Colour::COLOUR_WHITE);

  string map_depth    = player_stats.get_map_depth();

  vector<pair<string, Colour>> status_ailments = player_stats.get_status_ailments();

  unsigned int PLAYER_SYNOPSIS_START_ROW = TERMINAL_MAX_ROWS - 3;
  unsigned int current_row = PLAYER_SYNOPSIS_START_ROW;
  unsigned int initial_row = current_row;
  unsigned int current_col = 0;
  bool can_print = true;

  // First, clear the synopsis.
  move(PLAYER_SYNOPSIS_START_ROW, 0);
  clrtobot();

  // Next, set the synopsis values
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, name, synopsis);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, synopsis, strength.first);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, strength.first, dexterity.first, strength.second);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, dexterity.first, agility.first, dexterity.second);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, agility.first, health.first, agility.second);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, health.first, intelligence.first, health.second);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, intelligence.first, willpower.first, intelligence.second);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, willpower.first, charisma.first, willpower.second);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, charisma.first, level, charisma.second);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, level, defence);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, defence, alignment.first);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, alignment.first, speed, alignment.second);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, speed, hit_points);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, hit_points, arc_points, hit_points_colour);
  if (can_print) can_print = print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, arc_points, map_depth, arc_points_colour);
  mvprintw(current_row, current_col, map_depth.c_str());

  // Last row: status ailments
  current_row = TERMINAL_MAX_ROWS-1;
  current_col = 0;

  for (uint x = 0; x < status_ailments.size(); x++)
  {
    pair<string, Colour> status_ailment = status_ailments.at(x);
    bool has_more = (x != (status_ailments.size() - 1));

    if (has_more)
    {
      pair<string, Colour> next_ailment = status_ailments.at(x+1);

      if (can_print)
      {
        Colour colour = status_ailment.second;

        print_display_statistic_and_update_row_and_column(initial_row, &current_row, &current_col, status_ailment.first, next_ailment.first, colour);
      }
    }
    else
    {
      if (can_print)
      {
        Colour colour = status_ailment.second;

        string sail = status_ailment.first;
        boost::replace_all(sail, "%", "%%");

        enable_colour(static_cast<int>(colour), stdscr);
        mvprintw(current_row, current_col, sail.c_str());
        disable_colour(static_cast<int>(colour), stdscr);
      }
    }
  }
}

bool CursesDisplay::print_display_statistic_and_update_row_and_column(const unsigned int initial_row, unsigned int* current_row, unsigned int* current_col, const string& current_stat, const string& next_stat, Colour print_colour)
{
  bool can_print = true;
  string stat = current_stat;
  boost::replace_all(stat, "%", "%%");

  enable_colour(static_cast<int>(print_colour), stdscr);
  mvprintw(*current_row, *current_col, stat.c_str());
  can_print = update_synopsis_row_and_column(initial_row, current_row, current_col, current_stat, next_stat);
  disable_colour(static_cast<int>(print_colour), stdscr);

  return can_print;
}

// Update the row/col for the player synopsis.  Return false if we've run out of space
// and can't print anything else.
bool CursesDisplay::update_synopsis_row_and_column(const unsigned int initial_row, unsigned int* row, unsigned int* col, const string& previous_field, const string& next_field)
{
  bool can_update = true;
  unsigned int next_column_end = *col + previous_field.size() + FIELD_SPACE + next_field.size();

  *col = *col + previous_field.size() + FIELD_SPACE;

  if (next_column_end > TERMINAL_MAX_COLS - 1)
  {
    // We've gone over max cols.  Fine - but can we increment to the next row in the display?
    if (*row < TERMINAL_MAX_ROWS-2)
    {
      *col = 0;
      *row = *row + 1;
    }
    else
    {
      can_update = false;
    }
  }

  return can_update;
}

void CursesDisplay::display_header(const string& header_text, WINDOW* window, const int display_line)
{
  int white = static_cast<int>(Colour::COLOUR_WHITE);
  enable_colour(white, window);

  string header = header_text;
  boost::replace_all(header, "%", "%%");

  size_t header_text_size = header.size();

  unsigned int header_start = (TERMINAL_MAX_COLS/2) - (header_text_size/2);
  unsigned int header_end = (TERMINAL_MAX_COLS/2) - (header_text_size/2) + header_text_size;

  for (unsigned int i = 0; i < header_start-1; i++)
  {
    mvwprintw(window, display_line, i, "-");
  }

  mvwprintw(window, display_line, header_start, header.c_str());

  for (unsigned int i = header_end+1; i < TERMINAL_MAX_COLS; i++)
  {
    mvwprintw(window, display_line, i, "-");
  }

  disable_colour(white, window);
}

WINDOW* CursesDisplay::get_current_screen()
{
  WINDOW* screen = stdscr;

  if (!screens.empty())
  {
    screen = screens.back();
  }

  return screen;
}

bool CursesDisplay::serialize(ostream& stream) const
{
  Display::serialize(stream);

  Serialize::write_uint(stream, TERMINAL_MAX_ROWS);
  Serialize::write_uint(stream, TERMINAL_MAX_COLS);
  Serialize::write_uint(stream, FIELD_SPACE);
  Serialize::write_uint(stream, MSG_BUFFER_LAST_Y);
  Serialize::write_uint(stream, MSG_BUFFER_LAST_X);

  // Screens are not serialized.  Saving can only be done on the main screen,
  // which will be reconstructed based on the game's map/etc data.

  // CursesPromptProcessor is stateless; don't write it.

  Serialize::write_bool(stream, can_use_colour);

  // cursor_mode is a constant set in the constructor - ignore it.

  return true;
}

bool CursesDisplay::deserialize(istream& stream)
{
  Display::deserialize(stream);

  Serialize::read_uint(stream, TERMINAL_MAX_ROWS);
  Serialize::read_uint(stream, TERMINAL_MAX_COLS);
  Serialize::read_uint(stream, FIELD_SPACE);
  Serialize::read_uint(stream, MSG_BUFFER_LAST_Y);
  Serialize::read_uint(stream, MSG_BUFFER_LAST_X);

  // Screens are not serialized.  Saving can only be done on the main screen,
  // which will be reconstructed based on the game's map/etc data.

  // CursesPromptProcessor is stateless; don't load it.

  Serialize::read_bool(stream, can_use_colour);

  // cursor_mode is a constant set in the constructor - ignore it.

  return true;
}

ClassIdentifier CursesDisplay::internal_class_identifier() const
{
  return ClassIdentifier::CLASS_ID_CURSES_DISPLAY;
}

#ifdef UNIT_TESTS
#include "unit_tests/CursesDisplay_test.cpp"
#endif

max_stars_repo_name: sidav/shadow-of-the-wyrm

max_issues_repo_name: sidav/shadow-of-the-wyrm

max_forks_repo_name: sidav/shadow-of-the-wyrm


text:
#include <stdio.h>

#include "rviz/config.h"
#include "robot_command_interface.h"
#include "ros/time.h"
#include <ros/package.h>
#include <boost/format.hpp>
#include <exception>
#include <std_srvs/Empty.h>

namespace jsk_rviz_plugins
{

  // Exception class
  class RobotCommandParseException: public std::runtime_error
  {
  public:
    RobotCommandParseException(const std::string& text): std::runtime_error(text) {}
  };

  RobotCommandInterfaceAction::RobotCommandInterfaceAction( QWidget* parent )
    : rviz::Panel( parent )
  {
    resource_retriever::Retriever r;
    signal_mapper_ = new QSignalMapper(this);
    ros::NodeHandle nh("~");
    QHBoxLayout* layout = new QHBoxLayout();
    // Parse yaml file from parameter
    if (nh.hasParam("robot_command_buttons")) {
      try {
        XmlRpc::XmlRpcValue robot_command_buttons_xmlrpc;
        nh.param("robot_command_buttons", robot_command_buttons_xmlrpc, robot_command_buttons_xmlrpc);
        if (robot_command_buttons_xmlrpc.getType() != XmlRpc::XmlRpcValue::TypeArray) {
          throw RobotCommandParseException("~robot_comamnd_buttons should be an array");
        }
        else {
          for (size_t i = 0; i < robot_command_buttons_xmlrpc.size(); i++) {
            XmlRpc::XmlRpcValue button_xmlrpc = robot_command_buttons_xmlrpc[i];
            if (button_xmlrpc.getType() != XmlRpc::XmlRpcValue::TypeStruct) {
              throw RobotCommandParseException("element of ~robot_comamnd_buttons should be an struct");
            }
            else {
              std::string name;
              QToolButton* button = new QToolButton();
              //button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
              button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

              if (button_xmlrpc.hasMember("name")) {
                name = (std::string)button_xmlrpc["name"];
              }
              else {
                throw RobotCommandParseException("element of ~robot_comamnd_buttons should have name field");
              }
              button->setText(QString(name.c_str()));
              if (button_xmlrpc.hasMember("icon")) {
                // TODO: resolve path
                std::string icon;
                icon = (std::string)button_xmlrpc["icon"];
                if (icon.find("package://") == 0) {
                  icon.erase(0, strlen("package://"));
                  size_t package_end = icon.find("/");
                  std::string package = icon.substr(0, package_end);
                  icon.erase(0, package_end);
                  std::string package_path;
                  package_path = ros::package::getPath(package);
                  icon = package_path + icon;
                }
                button->setIcon(QIcon(QPixmap(QString(icon.c_str()))));
                button->setIconSize(QSize(80, 80));
                button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
              }
              std::string type;
              if (button_xmlrpc.hasMember("type")) {
                type = (std::string)button_xmlrpc["type"];
              }
              if (type == "euscommand") {
                if (button_xmlrpc.hasMember("command")) {
                  euscommand_mapping_[i] = (std::string)button_xmlrpc["command"];
                  button->setToolTip(euscommand_mapping_[i].c_str());
                }
                else {
                  throw RobotCommandParseException("type: euscommand requires command field");
                }
              }
              else if (type == "emptysrv") {
                if (button_xmlrpc.hasMember("srv")) {
                  emptyservice_mapping_[i] = (std::string)button_xmlrpc["srv"];
                  button->setToolTip(emptyservice_mapping_[i].c_str());
                }
                else {
                  throw RobotCommandParseException("type: emptysrv requires srv field");
                }
              }
              else {
                throw RobotCommandParseException("type field is required");
              }
              // connect
              connect(button, SIGNAL(clicked()), signal_mapper_, SLOT(map()));
              signal_mapper_->setMapping(button, i);
              layout->addWidget(button);
            }
          }
        }
      }
      catch (RobotCommandParseException& e) {
        popupDialog((boost::format("Malformed ~robot_command_buttons parameter.\n"
                                  "%s\n"
                                  "See package://jsk_rviz_plugins/config/default_robot_command.yaml")
                     % e.what()).str().c_str());
      }
    }
    else {
      popupDialog("You need to specify ~robot_command_buttons parameter.\n"
                  "See package://jsk_rviz_plugins/launch/robot_command_interface_sample.launch");
    }
    layout->addStretch();
    connect(signal_mapper_, SIGNAL(mapped(int)), this, SLOT(buttonCallback(int)));
    // QToolButton* button = new QToolButton();

    // // button->setPopupMode(QToolButton::MenuButtonPopup);
    // button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    // button->setIcon(QIcon(QPixmap(QString("/home/garaemon/ros/hydro/src/jsk-ros-pkg/jsk_visualization/jsk_rviz_plugins/icons/stop-imp.png"))));

    // button->setText("Hello worpld");
    // layout->addWidget(button);
    this->setLayout(layout);
  }

  bool RobotCommandInterfaceAction::callRequestEusCommand(const std::string& command){
    ros::ServiceClient client = nh_.serviceClient<jsk_rviz_plugins::EusCommand>("/eus_command", true);
    jsk_rviz_plugins::EusCommand srv;
    srv.request.command = command;
    return client.call(srv);
  }

  void RobotCommandInterfaceAction::buttonCallback(int i)
  {
    ROS_INFO("buttonCallback(%d)", i);
    if (euscommand_mapping_.find(i) != euscommand_mapping_.end()) {
      if(!callRequestEusCommand(euscommand_mapping_[i])) {
        popupDialog((boost::format("Failed to call %s") % euscommand_mapping_[i]).str().c_str());
      }
    }
    else if (emptyservice_mapping_.find(i) != emptyservice_mapping_.end()) {
      std_srvs::Empty emp;
      if (!ros::service::call(emptyservice_mapping_[i], emp)) {
        popupDialog((boost::format("Failed to call %s") % emptyservice_mapping_[i]).str().c_str());
      }
    }
    else {
      popupDialog((boost::format("Failed to find corresponding command for %d") % i).str().c_str());
    }
  }

  void RobotCommandInterfaceAction::popupDialog(const std::string& text)
  {
    QMessageBox msg_box;
    msg_box.setText("Unexpected error");
    msg_box.setText(QString(text.c_str()));
    msg_box.exec();
  }
}

#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS(jsk_rviz_plugins::RobotCommandInterfaceAction, rviz::Panel )

ext: cpp


text:
/*
 * Part of HTTPP.
 *
 * Distributed under the 2-clause BSD licence (See LICENCE.TXT file at the
 * project root).
 *
 * Copyright (c) 2014 Thomas Sanchez.  All rights reserved.
 *
 */

#include <iostream>
#include <chrono>
#include <thread>

#include <boost/test/unit_test.hpp>

#include "httpp/HttpServer.hpp"
#include "httpp/HttpClient.hpp"

using namespace HTTPP;

BOOST_AUTO_TEST_CASE(follow_redirect)
{
    HttpClient::Request request;
    request
        .url("http://www.google.fr/");

    HttpClient client;
    auto response = client.get(std::move(request));
    for (const auto& h : response.headers)
    {
        std::cout << h.first << ": " << h.second << std::endl;
    }

    std::string str(response.body.data(), response.body.size());
}

max_stars_repo_name: mlove-au/httpp

max_issues_repo_name: mlove-au/httpp

max_forks_repo_name: mlove-au/httpp


text:
/*
 * graph.cpp
 *
 * Purpose: Graph
 * Created by: Keisuke Okumura <okumura.k@coord.c.titech.ac.jp>
 */

#include "graph.h"
#include <random>
#include <unordered_set>
#include "util.h"
#include <boost/heap/fibonacci_heap.hpp>

Graph::Graph() {
  std::random_device seed_gen;
  MT = new std::mt19937(seed_gen());
  init();
}

Graph::Graph(std::mt19937* _MT) : MT(_MT) {
  init();
}

void Graph::init() {
  directed = false;
  regFlg = true;
}

Graph::~Graph() {
  for (auto v : nodes) delete v;
  nodes.clear();
  for (auto p : knownPaths) delete p.second;
  knownPaths.clear();
}

Node* Graph::getNode(int id) {
  auto itr = std::find_if(nodes.begin(), nodes.end(),
                          [id](Node* v){ return v->getId() == id; });
  // error check
  if (itr == nodes.end()) {
    std::cout << "error@Graph::getNode, "
              << "node index is over, " << id << "\n";
    std::exit(1);
  }

  return *itr;
}

Node* Graph::getNode(int x, int y) {
  auto itr = std::find_if(nodes.begin(), nodes.end(),
                          [x, y](Node* v)
                          { return v->getPos().x == x
                              && v->getPos().y == y; });
  if (itr == nodes.end()) return nullptr;
  return *itr;
}

bool Graph::existNode(int id) {
  auto itr = std::find_if(nodes.begin(), nodes.end(),
                          [id](Node* v){ return v->getId() == id; });
  return itr != nodes.end();
}

int Graph::getNodeIndex(Node* v) {
  return v->getIndex();
}

Nodes Graph::neighbor(Node* v) {
  return v->getNeighbor();
}

Nodes Graph::neighbor(int i) {
  return getNode(i)->getNeighbor();
}

Nodes Graph::getPath(Node* s, Node* g, Nodes &prohibitedNodes) {
  return {};
}

// regFlg : whether register
Nodes Graph::getPath(Node* _s, Node* _g,
                     Nodes &prohibitedNodes, int (*dist) (Node*, Node*))
{
  bool prohibited = !prohibitedNodes.empty();
  Nodes path, C;
  std::string key;

  // ==== fast implementation ====
  if (regFlg && !prohibited) {
    key = getKey(_s, _g);
    auto itrK = knownPaths.find(key);
    if (itrK != knownPaths.end()) {  // known
      path = itrK->second->path;
      return path;
    }
  }
  // =============================

  int f;
  bool invalid = true;

  // prepare node open hashtable
  boost::heap::fibonacci_heap<Fib_AN> OPEN;
  std::unordered_map<int, boost::heap::fibonacci_heap<Fib_AN>::handle_type> SEARCHED;
  std::unordered_set<int> CLOSE;
  AN* n = new AN { _s, 0, dist(_s, _g), nullptr };
  auto handle = OPEN.push(Fib_AN(n));
  SEARCHED.emplace(n->v->getId(), handle);

  while (!OPEN.empty()) {
    // argmin
    n = OPEN.top().node;

    // check goal condition
    if (n->v == _g) {
      invalid = false;
      break;
    }

    // ==== fast implementation ====
    key = getKey(n->v, _g);
    auto itrK = knownPaths.find(key);
    if (itrK != knownPaths.end()) {  // known
      Nodes kPath = itrK->second->path;
      bool valid = true;
      if (prohibited) {
        for (auto v : kPath) {
          if (inArray(v, prohibitedNodes)) {
            valid = false;
            break;
          }
        }
      }
      if (valid) {
        for (int i = 1; i < kPath.size(); ++i) {
          n = new AN { kPath[i], 0, 0, n };
        }
        invalid = false;
        break;
      }
    }
    // =============================

    // update list
    OPEN.pop();
    CLOSE.emplace(n->v->getId());

    // search neighbor
    C = neighbor(n->v);

    for (auto m : C) {
      if (prohibited && inArray(m, prohibitedNodes)) continue;
      if (CLOSE.find(m->getId()) != CLOSE.end()) continue;
      f = n->g + 1 + dist(m, _g);

      // ==== fast implementation ====
      if (regFlg) {
        key = getKey(m, _g);
        auto itrK = knownPaths.find(key);
        if (itrK != knownPaths.end()) {
          f = n->g + 1 + itrK->second->path.size() - 1;
        }
      }
      // =============================

      auto itrS = SEARCHED.find(m->getId());
      if (itrS == SEARCHED.end()) {  // new node
        AN* l = new AN { m, n->g + 1, f, n };
        auto handle = OPEN.push(Fib_AN(l));
        SEARCHED.emplace(l->v->getId(), handle);
      } else {
        auto handle = itrS->second;
        AN* l = (*handle).node;
        if (l->f > f) {
          l->g = n->g + 1;
          l->f = f;
          l->p = n;
          OPEN.increase(handle);
        }
      }
    }
  }

  if (invalid) return path;

  // back tracking
  while (n != nullptr) {
    path.push_back(n->v);
    n = n->p;
  }
  std::reverse(path.begin(), path.end());

  // register path
  if (regFlg && !prohibited) registerPath(path);

  return path;
}

std::string Graph::getKey(Node* s, Node* g) {
  int sIndex = getNodeIndex(s);
  int gIndex = getNodeIndex(g);
  std::string key = "";
  key += std::to_string(sIndex);
  key += "-";
  key += std::to_string(gIndex);
  return key;
}

void Graph::registerPath(const Nodes &path) {
  if (path.empty()) return;

  Nodes tmp = path;
  std::string key;

  Node *v1, *v2;
  do {
    v1 = tmp[0];
    v2 = tmp[tmp.size() - 1];
    key = getKey(v1, v2);
    KnownPath* knownPath = new KnownPath { v1, v2, tmp };
    knownPaths.emplace(key, knownPath);
    tmp.erase(tmp.begin());
  } while (tmp.size() > 2);
}

Paths Graph::getRandomStartGoal(int num) {
  if (num > starts.size() || num > goals.size()) {
    std::cout << "error@Graph::getStartGoal, over node size" << "\n";
    std::exit(1);
  }

  Paths points;
  Nodes ss(starts.size());
  Nodes gs(goals.size());
  bool flg;

  std::copy(starts.begin(), starts.end(), ss.begin());
  std::copy(goals.begin(),  goals.end(), gs.begin());

  while (true) {
    points.clear();
    std::shuffle(ss.begin(), ss.end(), *MT);
    std::shuffle(gs.begin(), gs.end(), *MT);

    flg = true;
    for (int i = 0; i < num; ++i) {
      if (ss[i] != gs[i]) {
        points.push_back({ ss[i], gs[i] });
      } else {
        flg = false;
        break;
      }
    }

    if (flg) break;
  }

  return points;
}


text:
// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION

// Copyright Aleksey Gurtovoy 2000-2004
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/mpl for documentation.

// $Source: /cvsroot/boost/boost/boost/mpl/aux_/shift_op.hpp,v $
// $Date: 2004/09/07 08:51:32 $
// $Revision: 1.4 $

#if !defined(BOOST_MPL_PREPROCESSING_MODE)
#   include <boost/mpl/integral_c.hpp>
#   include <boost/mpl/aux_/value_wknd.hpp>
#endif

#if !defined(AUX778076_OP_PREFIX)
#   define AUX778076_OP_PREFIX AUX778076_OP_NAME
#endif

#define AUX778076_OP_ARITY 2

#include <boost/mpl/aux_/numeric_op.hpp>
#include <boost/mpl/aux_/config/static_constant.hpp>
#include <boost/mpl/aux_/config/use_preprocessed.hpp>

#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
    && !defined(BOOST_MPL_PREPROCESSING_MODE)

#   define BOOST_MPL_PREPROCESSED_HEADER AUX778076_OP_PREFIX.hpp
#   include <boost/mpl/aux_/include_preprocessed.hpp>

#else

#   include <boost/mpl/aux_/config/integral.hpp>
#   include <boost/preprocessor/cat.hpp>

namespace boost { namespace mpl {

#if defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC)
namespace aux {
template< typename T, typename Shift, T n, Shift s >
struct BOOST_PP_CAT(AUX778076_OP_PREFIX,_wknd)
{
    BOOST_STATIC_CONSTANT(T, value = (n AUX778076_OP_TOKEN s));
    typedef integral_c<T,value> type;
};
}
#endif

template<>
struct AUX778076_OP_IMPL_NAME<integral_c_tag,integral_c_tag>
{
    template< typename N, typename S > struct apply
#if !defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC)
        : integral_c<
              typename N::value_type
            , ( BOOST_MPL_AUX_VALUE_WKND(N)::value
                  AUX778076_OP_TOKEN BOOST_MPL_AUX_VALUE_WKND(S)::value
                )
            >
#else
        : aux::BOOST_PP_CAT(AUX778076_OP_PREFIX,_wknd)<
              typename N::value_type
            , typename S::value_type
            , N::value
            , S::value
            >::type
#endif
    {
    };
};

}}

#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS

#undef AUX778076_OP_TAG_NAME
#undef AUX778076_OP_IMPL_NAME
#undef AUX778076_OP_ARITY
#undef AUX778076_OP_PREFIX
#undef AUX778076_OP_NAME
#undef AUX778076_OP_TOKEN

ext: hpp

max_stars_repo_name: dstrigl/mcotf

max_issues_repo_name: dstrigl/mcotf

max_forks_repo_name: dstrigl/mcotf


text:
/*=============================================================================
    Copyright (c) 2001-2007 Joel de Guzman

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#ifndef PHOENIX_CORE_HPP
#define PHOENIX_CORE_HPP

#include <boost/spirit/home/phoenix/version.hpp>
#include <boost/spirit/home/phoenix/core/limits.hpp>
#include <boost/spirit/home/phoenix/core/basic_environment.hpp>
#include <boost/spirit/home/phoenix/core/actor.hpp>
#include <boost/spirit/home/phoenix/core/as_actor.hpp>
#include <boost/spirit/home/phoenix/core/is_actor.hpp>
#include <boost/spirit/home/phoenix/core/argument.hpp>
#include <boost/spirit/home/phoenix/core/value.hpp>
#include <boost/spirit/home/phoenix/core/reference.hpp>
#include <boost/spirit/home/phoenix/core/compose.hpp>
#include <boost/spirit/home/phoenix/core/composite.hpp>
#include <boost/spirit/home/phoenix/core/nothing.hpp>

#endif

max_stars_repo_name: randolphwong/mcsema

max_issues_repo_name: randolphwong/mcsema

max_forks_repo_name: randolphwong/mcsema


text:
#include "readline_buffer.h"
#include <readline/readline.h>
#include <readline/history.h>
#include <sys/select.h>
#include <unistd.h>
#include <mutex>
#include <condition_variable>
#include <boost/thread.hpp>

static int process_input();
static void install_line_handler();
static void remove_line_handler();

static std::string last_line;
static std::string last_prompt;
std::mutex line_mutex, sync_mutex, process_mutex;
std::condition_variable have_line;

namespace
{
  rdln::readline_buffer* current = NULL;
}

rdln::suspend_readline::suspend_readline()
: m_buffer(NULL), m_restart(false)
{
  m_buffer = current;
  if(!m_buffer)
    return;
  m_restart = m_buffer->is_running();
  if(m_restart)
    m_buffer->stop();
}

rdln::suspend_readline::~suspend_readline()
{
  if(!m_buffer)
    return;
  if(m_restart)
    m_buffer->start();
}

rdln::readline_buffer::readline_buffer()
: std::stringbuf(), m_cout_buf(NULL)
{
  current = this;
}

void rdln::readline_buffer::start()
{
  std::unique_lock<std::mutex> lock(process_mutex);
  if(m_cout_buf != NULL)
    return;
  m_cout_buf = std::cout.rdbuf();
  std::cout.rdbuf(this);
  install_line_handler();
}

void rdln::readline_buffer::stop()
{
  std::unique_lock<std::mutex> lock(process_mutex);
  if(m_cout_buf == NULL)
    return;
  std::cout.rdbuf(m_cout_buf);
  m_cout_buf = NULL;
  remove_line_handler();
}

void rdln::readline_buffer::get_line(std::string& line) const
{
  std::unique_lock<std::mutex> lock(line_mutex);
  have_line.wait(lock);
  line = last_line;
}

void rdln::readline_buffer::set_prompt(const std::string& prompt)
{
  last_prompt = prompt;
  if(m_cout_buf == NULL)
    return;
  rl_set_prompt(last_prompt.c_str());
  rl_redisplay();
}

int rdln::readline_buffer::process()
{
  process_mutex.lock();
  if(m_cout_buf == NULL)
  {
    process_mutex.unlock();
    boost::this_thread::sleep_for(boost::chrono::milliseconds( 1 ));
    return 0;
  }
  int count = process_input();
  process_mutex.unlock();
  boost::this_thread::sleep_for(boost::chrono::milliseconds( 1 ));
  return count;
}

int rdln::readline_buffer::sync()
{
  std::lock_guard<std::mutex> lock(sync_mutex);
  char* saved_line;
  int saved_point;

  saved_point = rl_point;
  saved_line = rl_copy_text(0, rl_end);

  rl_set_prompt("");
  rl_replace_line("", 0);
  rl_redisplay();

  do
  {
    char x = this->sgetc();
    m_cout_buf->sputc(x);
  }
  while ( this->snextc() != EOF );

  rl_set_prompt(last_prompt.c_str());
  rl_replace_line(saved_line, 0);
  rl_point = saved_point;
  rl_redisplay();
  free(saved_line);

  return 0;
}

static int process_input()
{
  int count;
  struct timeval t;
  fd_set fds;

  t.tv_sec = 0;
  t.tv_usec = 1000;

  FD_ZERO(&fds);
  FD_SET(STDIN_FILENO, &fds);
  count = select(STDIN_FILENO + 1, &fds, NULL, NULL, &t);
  if (count < 1)
  {
    return count;
  }
  rl_callback_read_char();
  return count;
}

static void handle_line(char* line)
{
  if (line != NULL)
  {
    std::lock_guard<std::mutex> lock(sync_mutex);
    rl_set_prompt(last_prompt.c_str());
    rl_already_prompted = 1;
    return;
  }
  rl_set_prompt("");
  rl_replace_line("", 0);
  rl_redisplay();
  rl_set_prompt(last_prompt.c_str());
}

static int handle_enter(int x, int y)
{
  std::lock_guard<std::mutex> lock(sync_mutex);
  char* line = NULL;

  line = rl_copy_text(0, rl_end);
  rl_set_prompt("");
  rl_replace_line("", 1);
  rl_redisplay();

  if (strcmp(line, "") != 0)
  {
    last_line = line;
    add_history(line);
    have_line.notify_one();
  }
  free(line);

  if(last_line != "exit")
  {
    rl_set_prompt(last_prompt.c_str());
    rl_redisplay();
  }

  rl_done = 1;
  return 0;
}

static int startup_hook()
{
  rl_bind_key(RETURN, handle_enter);
  rl_bind_key(NEWLINE, handle_enter);
  return 0;
}

static void install_line_handler()
{
  rl_startup_hook = startup_hook;
  rl_callback_handler_install("", handle_line);
}

static void remove_line_handler()
{
  rl_unbind_key(RETURN);
  rl_callback_handler_remove();
}

max_stars_repo_name: chipbomb/monero-test

max_issues_repo_name: chipbomb/monero-test

max_forks_repo_name: chipbomb/monero-test


text: #include <boost/mpl/aux_/preprocessed/no_ttp/greater_equal.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#include <iostream>
#include <fstream>

// Boost includes
#include <boost/filesystem.hpp>

#include <warpSynchronousGenerator.h>
#include <traceEvent.h>
#include <performanceBoundGenerator.h>

#include <debug.h>
#include <string.h>

// Debugging messages
#ifdef REPORT_BASE
#undef REPORT_BASE
#endif

#define REPORT_BASE 1
#define REPORT_KERNEL_INSTRUCTIONS 0

//////////////////////////////////////////////////////////////////////////////////////////////////

unsigned int trace::PerformanceBoundGenerator::_counter = 0;

//////////////////////////////////////////////////////////////////////////////////////////////////

trace::PerformanceBoundGenerator::Counter::Counter():
	memoryDemand(0),
	warpInstructions(0),
	branchInstructions(0),
	noopInstructions(0),
	instructions(0),
	flops(0),
	sharedBytes(0),
	bankConflicts(0),
	stackDepth(0),
	stackVisitNodes(0),
	stackVisitEnd(0),
	stackVisitMiddle(0),
	stackInsert(0),
	stackMerge(0),
	conservativeBranches(0)
{

}

struct thousands: std::numpunct<char> {
   char do_thousands_sep() const { return ','; }
   std::string do_grouping() const { return "\3"; }
};

/*!
\brief place commas between every three digits
*/
static std::string formatInteger(size_t n) {
	std::stringstream ss;
	ss.imbue(std::locale(std::locale(), new thousands));
	ss << n;
	return ss.str();
}

std::ostream & operator <<(std::ostream &out,
	const trace::PerformanceBoundGenerator::Counter &counter) {

	out << " | memory demand: " << formatInteger(counter.memoryDemand) << " bytes ";
	if (counter.sharedBytes) {
		out << " | shared mem demand: " << formatInteger(counter.sharedBytes) << " bytes ";
		out << " | shared conflicts: " << formatInteger(counter.bankConflicts) << " ";
	}
	out << " | warp instr: " << formatInteger(counter.warpInstructions) << " ";
	out << " | dynamic instr: " << formatInteger(counter.instructions) << " ";
	out << " | FLOPs: " << formatInteger(counter.flops) << " ";
	if (counter.memoryDemand) {
		out << " | FLOPs per word: " << (double)counter.flops / (double)(counter.memoryDemand) * 4.0 << " ";
		out << " | OPs per byte: " << (double)counter.instructions / (double)(counter.memoryDemand) << " ";
	}
	if (counter.stackDepth) {
		out << " | avg stack depth: " << (double)counter.stackDepth / (double)counter.warpInstructions << " ";
	}
	if (counter.stackVisitNodes && counter.branchInstructions) {
		out << " | avg stack iterations: " << (double)counter.stackVisitNodes / (double)counter.branchInstructions << " ";
	}
	if (counter.stackVisitEnd) {
		out << " | stack visit end: " << counter.stackVisitEnd << " ";
		out << " | stack visit middle: " << counter.stackVisitMiddle << " ";
		out << " | stack inserts: " << counter.stackInsert << " ";
		out << " | stack merges: " << counter.stackMerge << " ";
	}
	if (counter.conservativeBranches) {
		out << " | " << counter.conservativeBranches << " ";
	}
	if (counter.noopInstructions) {
		out << " | " << counter.noopInstructions << " ";
	}

	return out;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

trace::PerformanceBoundGenerator::PerformanceBoundGenerator() {

}

trace::PerformanceBoundGenerator::~PerformanceBoundGenerator() {

}

//////////////////////////////////////////////////////////////////////////////////////////////////

void trace::PerformanceBoundGenerator::initialize(const executive::ExecutableKernel &kernel) {

	const executive::EmulatedKernel & emuKernel =
		static_cast<const executive::EmulatedKernel &>(kernel);

	//
	// initialize kernel header
	//
	_entry.name = kernel.name;
	_entry.module = kernel.module->path();
	_entry.format = TraceGenerator::PerformanceBoundTraceFormat;
	_entry.path = "";
	_entry.header = "";
	_entry.program = "";
	_entry.gridDim = kernel.gridDim();
	_entry.blockDim = kernel.blockDim();
		std::string name = kernel.name;

	if( name.size() > 20 ) {
		name.resize( 20 );
	}

	std::stringstream stream;
	stream << _entry.format << "_" << trace::PerformanceBoundGenerator::_counter++;

	boost::filesystem::path path( database );
	path = path.parent_path();
	path /= _entry.program + "_" + name + "_" + stream.str() + ".json";
	path = boost::filesystem::system_complete( path );

	_entry.header = path.string();

	this->kernel = (& emuKernel);
	analyzeKernel(emuKernel);
}

//! \brief visits each basic block and initializes a counter for each block
void trace::PerformanceBoundGenerator::analyzeKernel(const executive::EmulatedKernel &kernel) {
	ir::ControlFlowGraph *cfg = const_cast<ir::ControlFlowGraph *>(kernel.cfg());
	ir::ControlFlowGraph::BlockPointerVector blocks = cfg->executable_sequence();
	ir::ControlFlowGraph::BlockPointerVector::iterator bb_it;
	for (bb_it = blocks.begin(); bb_it != blocks.end(); ++bb_it) {
		Counter counter;
		counterMap[(*bb_it)->label()] = counter;
	}

	Counter counter;
	counterMap["entry"] = counter;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

class Formatter: public ir::ControlFlowGraph::BasicBlock::DotFormatter {
public:
	std::map< std::string, int > blocksToPC;
public:

	static std::string colorToString(
		unsigned int r, unsigned int g, unsigned int b, unsigned int a=0) {
		std::stringstream ss;

		ss << "#";
		ss << std::setfill('0') << std::setw(2) << std::hex << (r & 0x0ff);
		ss << std::setfill('0') << std::setw(2) << std::hex << (g & 0x0ff);
		ss << std::setfill('0') << std::setw(2) << std::hex << (b & 0x0ff);
	//	ss << std::setfill('0') << std::setw(2) << std::hex << (a & 0x0ff);

		return ss.str();
	}

	Formatter(trace::PerformanceBoundGenerator * gen): generator(gen), maxEvents(1) {
		for (std::map< int, std::string >::const_iterator bl_it = generator->kernel->basicBlockPC.begin();
			bl_it != generator->kernel->basicBlockPC.end(); ++bl_it) {

			blocksToPC[bl_it->second] = bl_it->first;
		}
	}

	/*!

	*/
	virtual std::string entryLabel(const ir::ControlFlowGraph::BasicBlock *block) {
		std::stringstream out;
		out << "[shape=record,style=\"bold,filled\",fillcolor=\"#4444cc\",";
		out << "label=";
		out << "\"{ KERNEL: " << hydrazine::toGraphVizParsableLabel(generator->kernel->name);

		if (generator->counterMap.find(block->label()) != generator->counterMap.end()) {

			const trace::PerformanceBoundGenerator::Counter &
				counter = generator->counterMap[block->label()];

			/*
			if (blocksToPC.find(block->label) != blocksToPC.end()) {
				out << " | near " << generator->kernel->location(blocksToPC[block->label]);
			}

			out << " | memory demand: " << counter.memoryDemand << " bytes ";
			out << " | dynamic instr: " << counter.instructions << " ";
			out << " | FLOPs: " << counter.flops << " ";
			if (counter.memoryDemand) {
			out << " | FLOPs per word: " << (double)counter.flops / (double)(counter.memoryDemand) * 4.0 << " ";
			out << " | OPs per byte: " << (double)counter.instructions / (double)(counter.memoryDemand) << " ";
			}
			*/
			out << counter;
		}

		out << "}\"]";
		return out.str();
	}

	/*!
		\brief prints string representation of a block
	*/
	virtual std::string toString(const ir::ControlFlowGraph::BasicBlock *block) {
		std::stringstream out;

		float t = 1.0f;

		if (generator->counterMap.find(block->label()) != generator->counterMap.end()) {

			const trace::PerformanceBoundGenerator::Counter &
				counter = generator->counterMap[block->label()];

			t = 0.0f;
			// log-scale color intensity based on number of times block has been reached by a warp
			if (counter.instructions) {
				t = log((float)(counter.instructions)) / (float)log((float)(maxEvents) + 1.0f);
			}
			unsigned int r = (unsigned int)(t * 255.0);
			unsigned int g = (unsigned int)(t * 64.0), b = (unsigned int)(t * 64.0);

			out << "[";
			out << "fillcolor=\"" << Formatter::colorToString(r,g,b) << "\",style=filled,";
			out << "shape=record,label=\"{";

			out << hydrazine::toGraphVizParsableLabel(block->label());

			if (blocksToPC.find(block->label()) != blocksToPC.end()) {
				std::string loc = generator->kernel->location(blocksToPC[block->label()]);
				if (loc != ":0:0") {
					out << " | near " << generator->kernel->location(blocksToPC[block->label()]);
				}
			}
			out << counter;
		}
		else {
			out << "[shape=record,";
			out << "label=";
			out << "\"{" << hydrazine::toGraphVizParsableLabel(block->label());
		}

		out << "}\"";

		if (t < 0.5) {
			out << ",fontcolor=\"#aaaaaa\"";
		}
		out << "]";

		return out.str();
	}

public:

	trace::PerformanceBoundGenerator *generator;

	/*!
		\brief maximum number of operations performed by some block
	*/
	size_t maxEvents;
};

//! \brief aggregates statistics and emits kernel results
void trace::PerformanceBoundGenerator::finish() {

	// aggregate entry statistics
	for (OperationCounterMap::const_iterator op_it = counterMap.begin();
		op_it != counterMap.end(); ++op_it) {

		if (op_it->first != "entry" && op_it->first != "exit") {
			counterMap["entry"] += op_it->second;
		}
	}

	Formatter formatter(this);

	std::stringstream ss;

	for (OperationCounterMap::const_iterator opit = counterMap.begin(); opit != counterMap.end(); ++opit) {
		if (opit->second.instructions > formatter.maxEvents) {
			formatter.maxEvents = opit->second.instructions;
		}
	}

	if (outputFormat == Output_append_csv) {

		//
		// append kernel aggregate results
		//
		boost::filesystem::path path(database);
		path = path.parent_path();
		path = boost::filesystem::system_complete(path);
		ss << path.string() << "/performance-bound-results.txt";
		std::ofstream resultsFile(ss.str().c_str(), std::ios_base::app);

		const char *app = getenv("APPLICATION");
		const char *reconverge = getenv("RECONVERGE");

		app = (app ? app: "unknown-app");
		reconverge = (reconverge ? reconverge : "unknown-reconverge");

		// appliction, reconvergence method, kernel name, counter, warp instructions, dynamic scalar instructions,
		resultsFile
			<< app << ", "
			<< reconverge
			<< _entry.name << ", "
			<< _counter << ", "
			<< counterMap["entry"].warpInstructions << ", "
			<< counterMap["entry"].instructions << ", "
			<< counterMap["entry"].stackVisitEnd << ", "
			<< counterMap["entry"].stackVisitMiddle << ", "
			<< counterMap["entry"].stackInsert << ", "
			<< counterMap["entry"].stackMerge << ", "
			<< (double)counterMap["entry"].stackDepth / (double)counterMap["entry"].warpInstructions << ", "
			<< counterMap["entry"].branchInstructions << ", "
			<< counterMap["entry"].stackVisitNodes << ", "
			<< counterMap["entry"].conservativeBranches << ", "
			<< counterMap["entry"].noopInstructions;

		resultsFile	<< std::endl;

	}
	else if (outputFormat == Output_dot) {

		boost::filesystem::path path( database );
		path = path.parent_path();
		path = boost::filesystem::system_complete( path );
		ss << path.string() << "/" << _entry.program << "_" << _entry.name << "_"
			<< _counter << "_perf.dot";

		std::string filename = ss.str();

		ir::ControlFlowGraph *controlFlowGraph = const_cast<ir::ControlFlowGraph*>(kernel->cfg());
		std::ofstream cfgFile(filename.c_str());
		cfgFile << "/*\n";
		cfgFile << "     kernel: " << " kernel-name " << "\n";
		cfgFile << "*/\n";

		controlFlowGraph->write(cfgFile, formatter);
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////

void trace::PerformanceBoundGenerator::event(const trace::TraceEvent &event) {
	std::string bbLabel = kernel->getInstructionBlock(event.PC);
	if (bbLabel == "") {
		report("event.PC = " << event.PC << " does not correspond to a BB");
		return;  // PC doesn't correspond to a basic block
	}

	OperationCounterMap::iterator op = counterMap.find(bbLabel);
	if (op == counterMap.end()) {
		report(" counter not found ");
		return;  // counter not found
	}

	/*
	report(bbLabel << " - " << event.instruction->toString() << " - "
		<< event.active.count() << " active threads");
	*/

	if (event.instruction->opcode != ir::PTXInstruction::Reconverge) {
		op->second.warpInstructions ++;
		op->second.stackDepth += event.contextStackSize;
		op->second.instructions += event.active.count();
	}
	else if (!event.active.count()) {
		op->second.noopInstructions ++;
	}

	if (event.instruction->opcode == ir::PTXInstruction::Bra) {
		op->second.branchInstructions ++;
		op->second.stackVisitEnd += event.reconvergence.stackVisitEnd;
		op->second.stackVisitMiddle += event.reconvergence.stackVisitMiddle;
		op->second.stackInsert += event.reconvergence.stackInsert;
		op->second.stackMerge += event.reconvergence.stackMerge;
		op->second.stackVisitNodes += event.reconvergence.stackVisitNodes;
		op->second.conservativeBranches += (event.reconvergence.conservativeBranch ? 1 : 0);
	}

	if (isFlop(*event.instruction)) {
		op->second.flops += event.active.count();
	}

	if (isGlobalMemoryOp(*event.instruction)) {
		//op->second.memoryDemand += computeMemoryDemand(event, protocol);
	}

	//int conflicts = 0;
	//op->second.sharedBytes += computeSharedDemand(event, &conflicts);
	//op->second.bankConflicts += conflicts;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

//! \brief computes bytes loaded or stored to shared memory and number of conflicts
size_t trace::PerformanceBoundGenerator::computeSharedDemand(const trace::TraceEvent &event,
	int * conflicts) {
	typedef std::map< size_t, size_t > SharedBankCounter;
	size_t bytes = 0;
	*conflicts = 0;

	if ((event.instruction->opcode == ir::PTXInstruction::Ld ||
		event.instruction->opcode == ir::PTXInstruction::St) &&
		event.instruction->addressSpace == ir::PTXInstruction::Shared) {

		size_t end = 0xffffffff;
		std::vector< size_t > addresses;
		for (int n = 0, tid = 0; tid < (int)event.active.size(); ++tid) {
			if (event.active[tid]) {
				addresses.push_back(event.memory_addresses[n++]);
			}
			else {
				addresses.push_back(end);
			}
		}

		for (int tid = 0; tid < (int)event.active.size(); tid += 16) {
			SharedBankCounter bankAddresses;
			for (int t = 0; t < 16; t++) {
				size_t addr = addresses[tid + t];
				if (addr != end) {
					size_t base = (addr & 0x3c);
					SharedBankCounter::iterator bank = bankAddresses.find(base);
					if (bank == bankAddresses.end()) {
						bankAddresses[base] = addr;
					}
					else {
						if (bank->second != addr) {
							++ *conflicts;
						}
					}

					bytes += event.memory_size;
				}
			}
		}
	}

	return bytes;
}

//! \brief computes the number of bytes of effective demand from an event given a coalescing protocol
size_t trace::PerformanceBoundGenerator::computeMemoryDemand(const trace::TraceEvent &event,
	CoalescingProtocol protocol) {

	size_t bytes = 0;

	// special handling of texture (assume coalesced reads)
	if (event.instruction->opcode == ir::PTXInstruction::Tex) {
		size_t elsize = 1;
		switch (event.instruction->d.type) {
			case ir::PTXOperand::s8:
			case ir::PTXOperand::u8:
			case ir::PTXOperand::b8:
				elsize = 1;
				break;

			case ir::PTXOperand::s16:
			case ir::PTXOperand::u16:
			case ir::PTXOperand::f16:
			case ir::PTXOperand::b16:
				elsize = 2;
				break;

			case ir::PTXOperand::s32:
			case ir::PTXOperand::u32:
			case ir::PTXOperand::b32:
			case ir::PTXOperand::f32:
				elsize = 4;
				break;

			case ir::PTXOperand::s64:
			case ir::PTXOperand::u64:
			case ir::PTXOperand::f64:
			case ir::PTXOperand::b64:
				elsize = 8;
				break;

			default:
				elsize = 0;
				break;
		}
		size_t vsize = (size_t)event.instruction->d.vec;

		bytes = (size_t)event.active.count() * elsize * vsize;
		return bytes;
	}

	switch (protocol) {
	case Protocol_sm_10:	// fall through
	case Protocol_sm_11:
	{
		size_t tid = 0;
		TraceEvent::U64Vector::const_iterator addr_it = event.memory_addresses.begin();
		size_t transactionSize = (event.memory_size == 16 ? 256 : (event.memory_size == 8 ? 128 : 64));

		std::vector< size_t > addresses;
		addresses.reserve(event.active.size());
		for (int n = 0; tid < event.active.size(); ++tid) {
			if (event.active[tid]) {
				addresses.push_back(event.memory_addresses[n]);
				++n;
			}
			else {
				addresses.push_back(0);
			}
		}

		// iterate over each half-warp
		std::map< size_t, size_t > transactions;
		for (tid = 0; tid < event.active.size(); tid += 16) {

			for (size_t t = 0; t < 16; t++) {
				size_t & address = addresses[t + tid];
				size_t base = (address & (~0x0f));
				if (address) {
					if (event.memory_size * t + base == address) {
						transactions[base] = transactionSize;
					}
					else {
						transactions[address] = transactionSize;
					}
				}
			}

			// add up the size of each transaction
			for (std::map<size_t, size_t>::const_iterator tr_it = transactions.begin();
				tr_it != transactions.end(); ++tr_it) {
				bytes += tr_it->second;
			}
			transactions.clear();
		}

	}
		break;

	case Protocol_sm_12:	// fall through
	case Protocol_sm_13:	// fall through
	case Protocol_sm_20:
	{
		size_t tid = 0;
		TraceEvent::U64Vector::const_iterator addr_it = event.memory_addresses.begin();

		std::vector< size_t > addresses;
		addresses.reserve(event.active.size());
		for (int n = 0; tid < event.active.size(); ++tid) {
			if (event.active[tid]) {
				addresses.push_back(event.memory_addresses[n]);
				++n;
			}
			else {
				addresses.push_back(0);
			}
		}

		// iterate over each half-warp
		std::map< size_t, size_t > transactions;
		for (tid = 0; tid < event.active.size(); tid += 16) {
			for (size_t t = 0; t < 16; t++) {
				size_t & address = addresses[t + tid];
				size_t base = (address & (~0x0f));
				if (address) {
					transactions[base] = (event.memory_size >= 2 ? 64 : 32);
				}
			}
			// add up the size of each transaction
			for (std::map<size_t, size_t>::const_iterator tr_it = transactions.begin();
				tr_it != transactions.end(); ++tr_it) {
				bytes += tr_it->second;
			}
			transactions.clear();
		}
	}
		break;

	// only count the actual number of distinct loads or stores
	case Protocol_ideal:
	{
		std::map< size_t, size_t > transactions;
		for (TraceEvent::U64Vector::const_iterator addr_it = event.memory_addresses.begin();
			addr_it != event.memory_addresses.end(); ++addr_it) {
			transactions[*addr_it] = event.memory_size;
		}
		// add up the size of each transaction
		for (std::map<size_t, size_t>::const_iterator tr_it = transactions.begin();
			tr_it != transactions.end(); ++tr_it) {
			bytes += tr_it->second;
		}
	}
		break;

	default:
		break;
	}

	return bytes;
}

typedef struct {
	ir::PTXInstruction::Opcode opcode;
	int flops;
} OpcodeWeight;

//! \brief determines if instruction is a significant floating-point operation
int trace::PerformanceBoundGenerator::isFlop(const ir::PTXInstruction &instr) {

	OpcodeWeight flopOpcodes[] = {
		{ir::PTXInstruction::Add, 1},
		{ir::PTXInstruction::AddC, 1},
		{ir::PTXInstruction::Mad, 2},

		{ir::PTXInstruction::Cos, 1},
		{ir::PTXInstruction::Div, 1},
		{ir::PTXInstruction::Ex2, 1},

		{ir::PTXInstruction::Fma, 2},
		{ir::PTXInstruction::Lg2, 1},
		{ir::PTXInstruction::Mad, 2},
		{ir::PTXInstruction::Mul, 1},
		{ir::PTXInstruction::Rcp, 1},
		{ir::PTXInstruction::Rsqrt, 1},
		{ir::PTXInstruction::Sin, 1},
		{ir::PTXInstruction::Sqrt, 1},
		{ir::PTXInstruction::Sub, 1},
		{ir::PTXInstruction::SubC, 1},

		{ir::PTXInstruction::Nop, 0}
	};

	int flops = 0;

	if (instr.d.type == ir::PTXOperand::f32 ||
		instr.d.type == ir::PTXOperand::f64) {

		for (int n = 0;
			flopOpcodes[n].opcode != ir::PTXInstruction::Nop && flopOpcodes[n].flops;
			++n) {
			if (flopOpcodes[n].opcode == instr.opcode) {
				flops = flopOpcodes[n].flops * (int)instr.vec;
				break;
			}
		}
	}

	return flops;
}

bool trace::PerformanceBoundGenerator::isGlobalMemoryOp(const ir::PTXInstruction &instr) {
	if (((instr.opcode == ir::PTXInstruction::Ld || instr.opcode == ir::PTXInstruction::St) &&
			instr.addressSpace == ir::PTXInstruction::Global)
		 || instr.opcode == ir::PTXInstruction::Tex) {
		return true;
	}
	return false;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

ext: cc

max_stars_repo_name: wahibium/KFF

max_issues_repo_name: wahibium/KFF

max_forks_repo_name: wahibium/KFF


text:
#ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_POINTER_HPP_INCLUDED
#define BOOST_DESCRIBE_DESCRIPTOR_BY_POINTER_HPP_INCLUDED

// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/describe/detail/config.hpp>

#if defined(__cpp_nontype_template_parameter_auto) && __cpp_nontype_template_parameter_auto >= 201606L

#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/bind.hpp>
#include <boost/mp11/integral.hpp>

namespace boost
{
namespace describe
{

namespace detail
{

template<class Pm> constexpr bool cx_pmeq( Pm p1, Pm p2 )
{
    return p1 == p2;
}

template<class Pm1, class Pm2> constexpr bool cx_pmeq( Pm1, Pm2 )
{
    return false;
}

template<auto Pm> struct match_by_pointer
{
    template<class D> using fn = mp11::mp_bool< cx_pmeq( D::pointer, Pm ) >;
};

} // namespace detail

template<class L, auto Pm> using descriptor_by_pointer = mp11::mp_at<L, mp11::mp_find_if_q<L, detail::match_by_pointer<Pm>>>;

} // namespace describe
} // namespace boost

#endif // __cpp_nontype_template_parameter_auto

#endif // #ifndef BOOST_DESCRIBE_DESCRIPTOR_BY_POINTER_HPP_INCLUDED


text:
// Copyright 2008 by BBN Technologies Corp.
// All Rights Reserved.

#include "Generic/common/leak_detection.h"

#include "Generic/common/GrowableArray.h"
#include "Generic/common/ParamReader.h"
#include "Generic/common/UnrecoverableException.h"
#include "Generic/common/UTF8InputStream.h"
#include "Generic/common/UTF8Token.h"
#include "Generic/common/SymbolConstants.h"
#include "Generic/common/SessionLogger.h"
#include "Generic/discTagger/P1Decoder.h"
#include "Generic/discTagger/DTTagSet.h"
#include "Generic/discTagger/DTFeatureTypeSet.h"
#include "Generic/maxent/MaxEntModel.h"
#include "Generic/edt/discmodel/DTNameLinker.h"
#include "Generic/edt/discmodel/DTCorefObservation.h"
#include "Generic/edt/discmodel/DTCorefFeatureTypes.h"
#include "Generic/edt/discmodel/DTCorefFeatureType.h"
#include "Generic/edt/LexEntity.h"
#include "Generic/edt/DescLinkFunctions.h"
#include "Generic/edt/DescLinkFeatureFunctions.h"
#include "Generic/edt/discmodel/CorefUtils.h"
#include "Generic/theories/EntityType.h"
#include "Generic/wordClustering/WordClusterTable.h"
#include "Generic/edt/SimpleRuleNameLinker.h"

#include <boost/algorithm/string.hpp>

#include <math.h>
#include <stdio.h>

#include "Generic/CASerif/correctanswers/CorrectMention.h"

DebugStream DTNameLinker::_debugStream;

DTNameLinker::DTNameLinker(DocumentMentionInformationMapper *infoMap) :
	_featureTypes(0), _tagSet(0), _tagScores(0)
	, _p1Decoder(0), _maxEntDecoder(0), _p1Weights(0), _maxentWeights(0)
	, _filter_by_entity_type(true), _filter_by_entity_subtype(false)
	, _p1_overgen_threshold(0.0), _rank_overgen_threshold(0.0)
	, _limitToNames(false), _noneFeatureTypes(0), _featureTypesArr(0)
{
	_debugStream.init(Symbol(L"namelink_debug"));

	DTCorefFeatureTypes::ensureFeatureTypesInstantiated();
	WordClusterTable::ensureInitializedFromParamFile();

	_observation = _new DTCorefObservation(infoMap);

	// FILTERING BY ENTITY TYPE AND SUBTYPE
	std::string buffer = ParamReader::getParam("do_name_coref_entity_type_filtering");
	if (buffer == "false")
		_filter_by_entity_type = false;

	_filter_by_entity_subtype = ParamReader::isParamTrue("do_name_coref_entity_subtype_filtering");

	// COREF MODEL TYPE -- MaxEnt or P1
	buffer = ParamReader::getRequiredParam("dt_name_coref_model_type");
	if (boost::iequals(buffer, "maxent"))
		MODEL_TYPE = MAX_ENT;
	else if (boost::iequals(buffer, "p1"))
		MODEL_TYPE = P1;
	else if (boost::iequals(buffer, "both"))
		MODEL_TYPE = BOTH;
	else if (boost::iequals(buffer, "p1_ranking"))
		MODEL_TYPE = P1_RANKING;
	else
		throw UnrecoverableException("DTNameLinker()::DTNameLinker()",
		"Parameter 'dt_name_coref_model_type' must be set to 'maxent', 'p1', 'both' or 'p1_ranking'");

	// TAG SET
	std::string tag_set_file = ParamReader::getRequiredParam("dt_name_coref_tag_set_file");
	_tagSet = _new DTTagSet(tag_set_file.c_str(), false, false);
	_tagScores = _new double[_tagSet->getNTags()];

	// FEATURES
	std::string features_file = ParamReader::getRequiredParam("dt_name_coref_features_file");
	_featureTypes = _new DTFeatureTypeSet(features_file.c_str(), DTCorefFeatureType::modeltype);

	// MODEL FILE NAME
	std::string model_file = ParamReader::getRequiredParam("dt_name_coref_model_file");

	// LIMIT LINKING JUST TO NAMES
	_limitToNames = ParamReader::isParamTrue("dt_name_coref_link_only_to_names");

	if (MODEL_TYPE == P1_RANKING) {
		std::string file = model_file + "-rank";
		_p1Weights = _new DTFeature::FeatureWeightMap(500009);
		DTFeature::readWeights(*_p1Weights, file.c_str(), DTCorefFeatureType::modeltype);

		_noneFeatureTypes = DTCorefFeatureTypes::makeNoneFeatureTypeSet(Mention::NAME);
		_featureTypesArr = _new DTFeatureTypeSet*[_tagSet->getNTags()];
		_featureTypesArr[_tagSet->getNoneTagIndex()] = _noneFeatureTypes;
		_featureTypesArr[_tagSet->getTagIndex(DescLinkFeatureFunctions::getLinkSymbol())] = _featureTypes;

		_p1Decoder = _new P1Decoder(_tagSet, _featureTypesArr, _p1Weights);

		_rank_overgen_threshold = ParamReader::getOptionalFloatParamWithDefaultValue("dt_name_coref_rank_overgen_threshold", 0);

	}
	else if (MODEL_TYPE == P1 || MODEL_TYPE == BOTH) {
		std::string file = model_file + "-p1";
		_p1Weights = _new DTFeature::FeatureWeightMap(500009);
		DTFeature::readWeights(*_p1Weights, file.c_str(), DTCorefFeatureType::modeltype);

		double overgen_percentage = ParamReader::getOptionalFloatParamWithDefaultValue("dt_name_coref_overgen_percentage", 0);
		if (overgen_percentage < 0.0 || overgen_percentage > 100.0)
			throw UnrecoverableException("DTNameLinker::DTNameLinker()",
			"Parameter 'dt_name_coref_overgen_percentage' must range from 0 to 100");

		_p1_overgen_threshold = ParamReader::getOptionalFloatParamWithDefaultValue("dt_name_coref_overgen_threshold", 0);

		_p1Decoder = _new P1Decoder(_tagSet, _featureTypes, _p1Weights, overgen_percentage);

	}
	if (MODEL_TYPE == MAX_ENT || MODEL_TYPE == BOTH) {
		std::string file = model_file + "-maxent";
		_maxentWeights = _new DTFeature::FeatureWeightMap(500009);
		DTFeature::readWeights(*_maxentWeights, file.c_str(), DTCorefFeatureType::modeltype);

		_maxEntDecoder = _new MaxEntModel(_tagSet, _featureTypes, _maxentWeights);
		_maxent_link_threshold = ParamReader::getOptionalFloatParamWithDefaultValue("dt_name_coref_maxent_link_threshold", 0.5);
	}
	_use_rules = ParamReader::getOptionalTrueFalseParamWithDefaultVal("use_simple_rule_namelink", false);
	if (_use_rules){
		_simpleRuleNameLinker = _new SimpleRuleNameLinker();
		_distillation_mode = ParamReader::getOptionalTrueFalseParamWithDefaultVal("simple_rule_name_link_distillation", false);
		if(!_distillation_mode)
			throw UnexpectedInputException("DTNameLinker::DTNameLinker()",
			"If DTNameLinker used and 'use_simple_rule_namelink: true', 'simple_rule_name_link_distillation' must also be true");
	}
}

DTNameLinker::~DTNameLinker() {
	delete _maxentWeights;
	delete _p1Weights;
	delete _p1Decoder;
	delete _maxEntDecoder;
	delete _tagSet;
	delete[] _tagScores;
	delete _featureTypes;
	delete _noneFeatureTypes;
	delete [] _featureTypesArr;
	if (_use_rules)
		delete _simpleRuleNameLinker;
}

void DTNameLinker::resetForNewSentence() {
	_debugStream << L"*** NEW SENTENCE ***\n";
}

void DTNameLinker::resetForNewDocument(Symbol docName) {
	_debugStream << L"*** NEW DOCUMENT " << docName.to_string()  <<  " ***\n";
}

// set up to link. This method doesn't do any of the actual processing - it just provides a way
// for multiple paths to get through
int DTNameLinker::linkMention (LexEntitySet * currSolution, MentionUID currMentionUID,
								 EntityType linkType, LexEntitySet *results[],
								 int max_results)
{
	LexEntitySet *newSet = NULL;
	EntityGuess guesses[64];
	Mention *currMention = currSolution->getMention(currMentionUID);
	if (_use_rules)
		_simpleRuleNameLinker->setCurrSolution(currSolution);

	_debugStream << L"\nPROCESSING Mention #" << currMention->getUID() << L": ";
	_debugStream << currMention->getNode()->toTextString() << L"\n";

	int nGuesses = guessEntity(currSolution, currMention, linkType, guesses,
								max_results>64 ? 64: max_results);

	for (int i = 0; i < nGuesses; i++) {
		newSet = currSolution->fork();
		if (guesses[i].id == EntityGuess::NEW_ENTITY ||
			!guesses[i].type.isRecognized()) { // when used with non-ACE candidates for no-link
			if (!guesses[i].type.isRecognized())
				_debugStream << L"OUTCOME: NOT CREATING A NEW ENTITY BECAUSE OF LINKING TO NON-ACE ENTITY #"<<guesses[i].id<<"\n";
			else {
				newSet->addNew(currMention->getUID(), linkType);
				_debugStream << L"OUTCOME: CREATED NEW ENTITY #" << newSet->getNEntities() - 1 << "\n";
			}
		}
		else {
			newSet->add(currMention->getUID(), guesses[i].id);
			Mention *newMention = newSet->getMention(currMention->getUID());
			if(!_filter_by_entity_type && newMention->getEntityType()!=guesses[i].type) {
				newMention->setEntityType(guesses[i].type);
				newMention->setEntitySubtype(EntitySubtype::getDefaultSubtype(guesses[i].type));
			}
			_debugStream << L"OUTCOME: LINKED TO ENTITY #"  << guesses[i].id << " score: "<< guesses[i].score <<"\n";
		}
		newSet->setScore(newSet->getScore() + static_cast<float>(guesses[i].score));
		results[i] = newSet;
		newSet->customDebugPrint(_debugStream);
	}
	_debugStream << L"\nDONE PROCESSING MENTION #" << currMention->getUID() << "\n\n";

	return nGuesses;
}

// get probability for linking to each entity. If no entity has > 50% chance, put link to
// new entity at top of heap.
int DTNameLinker::guessEntity(LexEntitySet * currSolution, Mention * currMention,
								EntityType linkType, EntityGuess results[], int max_results)
{
	int link_index = _tagSet->getLinkTagIndex();
	int no_link_index = _tagSet->getNoneTagIndex();
	int nResults = 0;

	_debugStream << L"BEGIN_GUESSES... mention type: "<<linkType.getName().to_string()<<L"\n";
	// this is a bit of a hack to get both of these, but because there is no
	// assignment operation on GrowableArrays, we'll just do it this way
	const GrowableArray <Entity *> &entitiesByType = currSolution->getEntitiesByType(linkType);
	const GrowableArray <Entity *> &allEntities = currSolution->getEntities();
	const GrowableArray <Entity *>  &ents =
		(_filter_by_entity_type || _filter_by_entity_subtype) ? entitiesByType : allEntities;

	GrowableArray <Entity *> filteredEnts;
	for (int c = 0; c < ents.length(); c++) {
		Entity *entity = ents[c];
		if (_limitToNames && (CorefUtils::getEntityMentionLevel(currSolution,entity)!=Mention::NAME))
			continue;

		if (_filter_by_entity_subtype) {
			if (CorefUtils::subtypeMatch(currSolution, entity, currMention))
				filteredEnts.add(entity);
		}
		else if (_filter_by_entity_type)
			filteredEnts.add(entity);
		else
			if(ents[c]->getType().isRecognized()) // only ace entities are added
				filteredEnts.add(entity);
	}

	//when approximating document level coreference, you cant use getLastMentionSet()
	//_observation->resetForNewSentence(currSolution->getLastMentionSet(), currSolution);
	int sent_num = currMention->getSentenceNumber();
	const MentionSet* mentionSet = currSolution->getMentionSet(sent_num);
	//TODO: add mentionMapping information + move to Document level
	// this is problematic to do because of the beam.
	_observation->resetForNewDocument(currSolution);
	_observation->resetForNewSentence(mentionSet);

	// compute the no_link score
	// add the new entity case for P1_RANKING
	if (MODEL_TYPE == P1_RANKING && !currMention->getEntityType().useSimpleCoref()){

		EntityGuess newGuess;
		newGuess.id = EntityGuess::NEW_ENTITY;
		newGuess.type = linkType;
		static_cast<DTNoneCorefObservation*>(_observation)->populate(currMention->getUID());
		//having a positive overgen parameter increases the chances for linking
		newGuess.score = _p1Decoder->getScore(_observation, no_link_index) - _rank_overgen_threshold;

		if (_debugStream.isActive()) {
			_debugStream << L"CONSIDERING NO-LINK option\n";
			_p1Decoder->printDebugInfo(_observation, no_link_index, _debugStream);
			_debugStream << L"NO-LINK SCORE " << newGuess.score << L"\n\n";
		}
		results[nResults++] = newGuess;
	}

	for (int i = 0; i < filteredEnts.length(); i++) {
		//document level coreference leaves empty entities behind these cause crashes...
		if (filteredEnts[i]->getNMentions() == 0) {
			continue;
		}
		const EntityType &entType = filteredEnts[i]->getType();
		Symbol linkval = _tagSet->getNoneTag();
		double thisscore = 0.0f;

		if (currMention->getEntityType().useSimpleCoref()) {
			// Only match within a given type, regardless of settings above
			if (filteredEnts[i]->getType() != currMention->getEntityType())
				continue;
			std::wstring name_string = currMention->getAtomicHead()->toTextString();
			for (int m = 0; m < filteredEnts[i]->getNMentions(); m++) {
				const Mention *ment = currSolution->getMention(filteredEnts[i]->getMention(m));
				if (ment->getMentionType() == Mention::NAME) {
					std::wstring candidate_name_string = ment->getAtomicHead()->toTextString();
					if (name_string == candidate_name_string) {
						linkval = _tagSet->getTagSymbol(link_index);
						thisscore = 1.0f;
						break;
					}
				}
			}
		} else {

			if (_use_rules) {
				bool okToLink = false;
				bool metonymyCase = false;
				EntityGuess* guessForRules = _new EntityGuess();
				guessForRules->id = filteredEnts[i]->getID();
				guessForRules->type = filteredEnts[i]->getType();
				if (_simpleRuleNameLinker->isOKToLink(currMention, linkType, guessForRules)) {
					okToLink = true;
				}
				if(_distillation_mode ){
					if( _simpleRuleNameLinker->isMetonymyLinkCase(currMention, linkType, guessForRules)){
						metonymyCase = true;
					}
					//DT Name Linker might link capitals to countries even when isMetonymyLinkCase() is false.
					//Since, we really want to avoid this behavior, block all country --> city links
					else if( _simpleRuleNameLinker->isCityAndCountry(currMention, linkType, guessForRules)){
						metonymyCase = true;
					}
				}
				delete guessForRules;
				if(!okToLink || metonymyCase){
					if (_debugStream.isActive()) {
						_debugStream << L"-------------------------------\n";
						//			_debugStream << L"Mention: " << currMention->getNode()->toTextString() << L"\n";
						_debugStream << L"SKIP LINK (from rules) TO ";
						_debugStream << L"Entity #" << filteredEnts[i]->getID() << L": [";
						for (int m = 0; m < filteredEnts[i]->getNMentions(); m++)
							_debugStream << currSolution->getMention(filteredEnts[i]->getMention(m))->getNode()->toTextString() << L" ,";
						_debugStream << L"]\n";
						_debugStream << L"okToLink: "<<okToLink<<", metonymyCase: "<<metonymyCase<<L"\n";
					}
					continue;
				}
			}
			_observation->populate(currMention->getUID(), filteredEnts[i]->getID());
			if (_debugStream.isActive()) {
				_debugStream << L"-------------------------------\n";
				//			_debugStream << L"Mention: " << currMention->getNode()->toTextString() << L"\n";
				_debugStream << L"CONSIDERING LINK TO ";
				_debugStream << L"Entity #" << filteredEnts[i]->getID() << L": [";
				for (int m = 0; m < filteredEnts[i]->getNMentions(); m++)
					_debugStream << currSolution->getMention(filteredEnts[i]->getMention(m))->getNode()->toTextString() << L" ,";
				_debugStream << L"]\n";
			}

			if (MODEL_TYPE == MAX_ENT || MODEL_TYPE == BOTH) {
				_maxEntDecoder->decodeToDistribution(_observation, _tagScores, _tagSet->getNTags());
				if (_tagScores[link_index] > _maxent_link_threshold) {
					linkval = _tagSet->getTagSymbol(link_index);
					thisscore = _tagScores[link_index];
				}
				else {
					linkval = _tagSet->getNoneTag();
					thisscore = _tagScores[_tagSet->getNoneTagIndex()];
				}
			}

			if (linkval == _tagSet->getNoneTag() && (MODEL_TYPE == P1 || MODEL_TYPE == BOTH)) {
				linkval = _p1Decoder->decodeToSymbol(_observation, thisscore);
				if (linkval == _tagSet->getNoneTag() && thisscore < _p1_overgen_threshold) {
					linkval = _tagSet->getTagSymbol(link_index);
					// I'm not sure what the appropriate behavior is here when thisscore == 0
					// Do we even do anything with these scores?
					if (thisscore != 0)
						thisscore = 1/thisscore;
					else thisscore = 0;
				}
			}

			if (MODEL_TYPE == P1_RANKING) {
				linkval = _tagSet->getTagSymbol(link_index);
				thisscore = _p1Decoder->getScore(_observation, link_index);
			}

			if (_debugStream.isActive()) {
				if (_p1Decoder != 0) _p1Decoder->printDebugInfo(_observation, link_index, _debugStream);
				_debugStream << L"LINK SCORE " << thisscore << L" := ";
				_debugStream << linkval.to_debug_string();
				_debugStream << L"\n\n";
			}
		}

		if (linkval != _tagSet->getNoneTag()) {
			EntityGuess newGuess;;
			newGuess.id = filteredEnts[i]->getID();
			newGuess.type = entType;
			newGuess.score = thisscore;
			// add results in sorted order
			bool insertedSolution = false;
			for (int p = 0; p < nResults; p++) {
				if(results[p].score < newGuess.score) {
					if (nResults < max_results)
						nResults++;
					for (int k = nResults-1; k > p; k--)
						results[k] = results[k-1];
					results[p] = newGuess;
					insertedSolution = true;
					break;
				}
			}
			// solution doesn't make the cut. if there's room, insert it at the end
			// otherwise, ditch it
			if (!insertedSolution) {
				if (nResults < max_results)
					results[nResults++] = newGuess;
			}
		}

	}
	// add the new entity case
	if (nResults < max_results && (MODEL_TYPE != P1_RANKING || currMention->getEntityType().useSimpleCoref())) {
		EntityGuess newGuess;
		newGuess.id = EntityGuess::NEW_ENTITY;
		newGuess.type = linkType;
		// not sure what the proper score here is
		// we'll simply make it slightly less than the next best score
		if (nResults > 0)
			newGuess.score = (results[nResults-1].score - 0.01);
		else
			newGuess.score = 100;
		results[nResults++] = newGuess;

	}
	return nResults;
}

max_stars_repo_name: BBN-E/serif

max_issues_repo_name: BBN-E/serif

max_forks_repo_name: BBN-E/serif