<commit_before>#include "segwayrmp/segwayrmp.h"
#include "segwayrmp/impl/rmp_ftd2xx.h"

#include <sstream>

using namespace segwayrmp;

static const bool ftd2xx_devices_debug = false;

inline std::string
getErrorMessageByFT_STATUS(FT_STATUS result, std::string what)
{
  std::stringstream msg;
  msg << "FTD2XX error while " << what << ": ";
  switch (result) {
    case FT_INVALID_HANDLE:
        msg << "FT_INVALID_HANDLE";
        break;
    case FT_DEVICE_NOT_FOUND:
        msg << "FT_DEVICE_NOT_FOUND";
        break;
    case FT_DEVICE_NOT_OPENED:
        msg << "FT_DEVICE_NOT_OPENED";
        break;
    case FT_IO_ERROR:
        msg << "FT_IO_ERROR";
        break;
    case FT_INSUFFICIENT_RESOURCES:
        msg << "FT_INSUFFICIENT_RESOURCES";
        break;
    case FT_INVALID_PARAMETER:
        msg << "FT_INVALID_PARAMETER";
        break;
    case FT_INVALID_BAUD_RATE:
        msg << "FT_INVALID_BAUD_RATE";
        break;
    case FT_DEVICE_NOT_OPENED_FOR_ERASE:
        msg << "FT_DEVICE_NOT_OPENED_FOR_ERASE";
        break;
    case FT_DEVICE_NOT_OPENED_FOR_WRITE:
        msg << "FT_DEVICE_NOT_OPENED_FOR_WRITE";
        break;
    case FT_FAILED_TO_WRITE_DEVICE:
        msg << "FT_FAILED_TO_WRITE_DEVICE";
        break;
    case FT_EEPROM_READ_FAILED:
        msg << "FT_EEPROM_READ_FAILED";
        break;
    case FT_EEPROM_WRITE_FAILED:
        msg << "FT_EEPROM_WRITE_FAILED";
        break;
    case FT_EEPROM_ERASE_FAILED:
        msg << "FT_EEPROM_ERASE_FAILED";
        break;
    case FT_EEPROM_NOT_PRESENT:
        msg << "FT_EEPROM_NOT_PRESENT";
        break;
    case FT_EEPROM_NOT_PROGRAMMED:
        msg << "FT_EEPROM_NOT_PROGRAMMED";
        break;
    case FT_INVALID_ARGS:
        msg << "FT_INVALID_ARGS";
        break;
    case FT_NOT_SUPPORTED:
        msg << "FT_NOT_SUPPORTED";
        break;
    case FT_OTHER_ERROR:
        msg << "FT_OTHER_ERROR";
        break;
    default:
        msg << "Unknown FTD2XX Error.";
        break;
  }
  return msg.str();
}

std::vector<FT_DEVICE_LIST_INFO_NODE> segwayrmp::enumerateUSBDevices() {
    FT_STATUS result;
    FT_DEVICE_LIST_INFO_NODE *device_info;
    DWORD number_of_devices;

    // If mac or linux you must set VID/PID
    #ifndef _WIN32
    DWORD FTDI_VID = 0x403;
    DWORD SEGWAY_PID = 0xe729;

    try {
      result = FT_SetVIDPID(FTDI_VID, SEGWAY_PID);
    } catch(std::exception &e) {
      RMP_THROW_MSG(ReadFailedException, e.what());
    }
    if (result != FT_OK) {
      RMP_THROW_MSG(ReadFailedException,
        getErrorMessageByFT_STATUS(result, "setting vid and pid").c_str());
    }
    #endif

    try {
      result = FT_CreateDeviceInfoList(&number_of_devices);
    } catch(std::exception &e) {
      RMP_THROW_MSG(ReadFailedException, e.what());
    }
    if (result != FT_OK) {
      RMP_THROW_MSG(ReadFailedException,
        getErrorMessageByFT_STATUS(result, "enumerating devices").c_str());
    }

    if (ftd2xx_devices_debug)
      std::cout << "Number of devices is: " << number_of_devices << std::endl;

    std::vector<FT_DEVICE_LIST_INFO_NODE> devices;
    if (number_of_devices > 0) {
      device_info = (FT_DEVICE_LIST_INFO_NODE*)malloc(
          sizeof(FT_DEVICE_LIST_INFO_NODE)*number_of_devices
        );
      try {
        result = FT_GetDeviceInfoList(device_info, &number_of_devices);
      } catch(std::exception &e) {
        RMP_THROW_MSG(ReadFailedException, e.what());
      }
      if (result != FT_OK) {
        RMP_THROW_MSG(ReadFailedException,
          getErrorMessageByFT_STATUS(result, "enumerating devices").c_str());
      }
      for (int i = 0; i < number_of_devices; i++) {
          devices.push_back(device_info[i]);
        if (ftd2xx_devices_debug) {
          printf("Dev %d:\n", i);
          printf(" Flags=0x%x\n", device_info[i].Flags);
          printf(" Type=0x%x\n", device_info[i].Type);
          printf(" ID=0x%x\n", device_info[i].ID);
          printf(" LocId=0x%x\n", device_info[i].LocId);
          printf(" SerialNumber=%s\n", device_info[i].SerialNumber);
          printf(" Description=%s\n", device_info[i].Description);
        }
      }
    }
    return devices;
}

/////////////////////////////////////////////////////////////////////////////
// FTD2XXRMPIO

FTD2XXRMPIO::FTD2XXRMPIO()
: configured(false), config_type(by_none), baudrate(460800), is_open(false)
{
  this->port_serial_number = "";
  this->port_description = "";
  this->port_index = 0;
  this->connected = false;
  this->usb_port_handle = NULL;
}

FTD2XXRMPIO::~FTD2XXRMPIO() {
  this->disconnect();
}

void FTD2XXRMPIO::connect() {
  if(!this->configured) {
    RMP_THROW_MSG(ConnectionFailedException, "The usb port must be "
      "configured before connecting.");
  }

  FT_STATUS result;

  this->enumerateUSBDevices_();

  // Select connection method and open
  switch (this->config_type) {
    case by_serial_number:
      this->connectBySerial();
      break;
    case by_description:
      this->connectByDescription();
      break;
    case by_index:
      this->connectByIndex();
      break;
    case by_none:
    default:
      RMP_THROW_MSG(ConnectionFailedException, "The usb port must be "
        "configured before connecting.");
        break;
  }

  this->is_open = true;

  // Configure the Baudrate
  try {
    result = FT_SetBaudRate(this->usb_port_handle, this->baudrate);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "setting the baudrate").c_str());
  }

  // Set default timeouts
  try {
    // 1 sec read and 1 sec write
    result = FT_SetTimeouts(this->usb_port_handle, 1000, 1000);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "setting timeouts").c_str());
  }

  // Set Latency Timer
  try {
    result = FT_SetLatencyTimer(this->usb_port_handle, 1);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "setting latency timer").c_str());
  }

  // Set flowcontrol
  try {
    result = FT_SetFlowControl(this->usb_port_handle, FT_FLOW_NONE, 0, 0);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "setting flowcontrol").c_str());
  }

  // Purge the I/O buffers of the usb device
  try {
    result = FT_Purge(this->usb_port_handle, FT_PURGE_RX | FT_PURGE_TX);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "purging the buffers").c_str());
  }

  this->connected = true;
}

void FTD2XXRMPIO::disconnect() {
  if(this->connected) {
    if (this->is_open) {
      FT_Close(this->usb_port_handle);
    }
    this->connected = false;
  }
}

int FTD2XXRMPIO::read(unsigned char* buffer, int size) {
  FT_STATUS result;
  DWORD bytes_read;

  try {
    result = FT_Read(this->usb_port_handle, buffer, size, &bytes_read);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ReadFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ReadFailedException,
      getErrorMessageByFT_STATUS(result, "reading").c_str());
  }

  return bytes_read;
}

int FTD2XXRMPIO::write(unsigned char* buffer, int size) {
  FT_STATUS result;
  DWORD bytes_written;

  try {
    result = FT_Write(this->usb_port_handle, buffer, size, &bytes_written);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ReadFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ReadFailedException,
      getErrorMessageByFT_STATUS(result, "reading").c_str());
  }

  return bytes_written;
}

std::vector<FT_DEVICE_LIST_INFO_NODE> FTD2XXRMPIO::enumerateUSBDevices_() {
  return enumerateUSBDevices();
}

void
FTD2XXRMPIO::configureUSBBySerial(std::string serial_number, int baudrate)
{
  this->config_type = by_serial_number;
  this->port_serial_number = serial_number;
  this->configured = true;
  this->baudrate = baudrate;
}

void FTD2XXRMPIO::connectBySerial() {
  FT_STATUS result;
  DWORD number_of_devices;

  try {
    // Open the usb port
    result = FT_OpenEx((PVOID)this->port_serial_number.c_str(),
                       (DWORD)FT_OPEN_BY_SERIAL_NUMBER,
                       &(this->usb_port_handle));
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (this->usb_port_handle == NULL) {
    // Failed to open port
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "opening the usb port").c_str());
  }
}

void
FTD2XXRMPIO::configureUSBByDescription(std::string description, int baudrate)
{
  this->config_type = by_description;
  this->port_description = description;
  this->configured = true;
  this->baudrate = baudrate;
}

void FTD2XXRMPIO::connectByDescription() {
  FT_STATUS result;

  try {
    // Open the usb port
    result = FT_OpenEx(const_cast<char *>(this->port_description.c_str()),
                       FT_OPEN_BY_DESCRIPTION,
                       &(this->usb_port_handle));
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    // Failed to open port
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "opening the usb port").c_str());
  }
}

void
FTD2XXRMPIO::configureUSBByIndex(unsigned int device_index, int baudrate)
{
  this->config_type = by_index;
  this->port_index = device_index;
  this->configured = true;
  this->baudrate = baudrate;
}

void FTD2XXRMPIO::connectByIndex() {
  FT_STATUS result;

  try {
    // Open the usb port
    result = FT_Open(this->port_index, &(this->usb_port_handle));
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (this->usb_port_handle == NULL) {
    // Failed to open port
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "opening the usb port").c_str());
  }
}

<commit_msg>Another missing import of iostream<commit_after>#include "segwayrmp/segwayrmp.h"
#include "segwayrmp/impl/rmp_ftd2xx.h"

#include <iostream>
#include <sstream>

using namespace segwayrmp;

static const bool ftd2xx_devices_debug = false;

inline std::string
getErrorMessageByFT_STATUS(FT_STATUS result, std::string what)
{
  std::stringstream msg;
  msg << "FTD2XX error while " << what << ": ";
  switch (result) {
    case FT_INVALID_HANDLE:
        msg << "FT_INVALID_HANDLE";
        break;
    case FT_DEVICE_NOT_FOUND:
        msg << "FT_DEVICE_NOT_FOUND";
        break;
    case FT_DEVICE_NOT_OPENED:
        msg << "FT_DEVICE_NOT_OPENED";
        break;
    case FT_IO_ERROR:
        msg << "FT_IO_ERROR";
        break;
    case FT_INSUFFICIENT_RESOURCES:
        msg << "FT_INSUFFICIENT_RESOURCES";
        break;
    case FT_INVALID_PARAMETER:
        msg << "FT_INVALID_PARAMETER";
        break;
    case FT_INVALID_BAUD_RATE:
        msg << "FT_INVALID_BAUD_RATE";
        break;
    case FT_DEVICE_NOT_OPENED_FOR_ERASE:
        msg << "FT_DEVICE_NOT_OPENED_FOR_ERASE";
        break;
    case FT_DEVICE_NOT_OPENED_FOR_WRITE:
        msg << "FT_DEVICE_NOT_OPENED_FOR_WRITE";
        break;
    case FT_FAILED_TO_WRITE_DEVICE:
        msg << "FT_FAILED_TO_WRITE_DEVICE";
        break;
    case FT_EEPROM_READ_FAILED:
        msg << "FT_EEPROM_READ_FAILED";
        break;
    case FT_EEPROM_WRITE_FAILED:
        msg << "FT_EEPROM_WRITE_FAILED";
        break;
    case FT_EEPROM_ERASE_FAILED:
        msg << "FT_EEPROM_ERASE_FAILED";
        break;
    case FT_EEPROM_NOT_PRESENT:
        msg << "FT_EEPROM_NOT_PRESENT";
        break;
    case FT_EEPROM_NOT_PROGRAMMED:
        msg << "FT_EEPROM_NOT_PROGRAMMED";
        break;
    case FT_INVALID_ARGS:
        msg << "FT_INVALID_ARGS";
        break;
    case FT_NOT_SUPPORTED:
        msg << "FT_NOT_SUPPORTED";
        break;
    case FT_OTHER_ERROR:
        msg << "FT_OTHER_ERROR";
        break;
    default:
        msg << "Unknown FTD2XX Error.";
        break;
  }
  return msg.str();
}

std::vector<FT_DEVICE_LIST_INFO_NODE> segwayrmp::enumerateUSBDevices() {
    FT_STATUS result;
    FT_DEVICE_LIST_INFO_NODE *device_info;
    DWORD number_of_devices;

    // If mac or linux you must set VID/PID
    #ifndef _WIN32
    DWORD FTDI_VID = 0x403;
    DWORD SEGWAY_PID = 0xe729;

    try {
      result = FT_SetVIDPID(FTDI_VID, SEGWAY_PID);
    } catch(std::exception &e) {
      RMP_THROW_MSG(ReadFailedException, e.what());
    }
    if (result != FT_OK) {
      RMP_THROW_MSG(ReadFailedException,
        getErrorMessageByFT_STATUS(result, "setting vid and pid").c_str());
    }
    #endif

    try {
      result = FT_CreateDeviceInfoList(&number_of_devices);
    } catch(std::exception &e) {
      RMP_THROW_MSG(ReadFailedException, e.what());
    }
    if (result != FT_OK) {
      RMP_THROW_MSG(ReadFailedException,
        getErrorMessageByFT_STATUS(result, "enumerating devices").c_str());
    }

    if (ftd2xx_devices_debug)
      std::cout << "Number of devices is: " << number_of_devices << std::endl;

    std::vector<FT_DEVICE_LIST_INFO_NODE> devices;
    if (number_of_devices > 0) {
      device_info = (FT_DEVICE_LIST_INFO_NODE*)malloc(
          sizeof(FT_DEVICE_LIST_INFO_NODE)*number_of_devices
        );
      try {
        result = FT_GetDeviceInfoList(device_info, &number_of_devices);
      } catch(std::exception &e) {
        RMP_THROW_MSG(ReadFailedException, e.what());
      }
      if (result != FT_OK) {
        RMP_THROW_MSG(ReadFailedException,
          getErrorMessageByFT_STATUS(result, "enumerating devices").c_str());
      }
      for (int i = 0; i < number_of_devices; i++) {
          devices.push_back(device_info[i]);
        if (ftd2xx_devices_debug) {
          printf("Dev %d:\n", i);
          printf(" Flags=0x%x\n", device_info[i].Flags);
          printf(" Type=0x%x\n", device_info[i].Type);
          printf(" ID=0x%x\n", device_info[i].ID);
          printf(" LocId=0x%x\n", device_info[i].LocId);
          printf(" SerialNumber=%s\n", device_info[i].SerialNumber);
          printf(" Description=%s\n", device_info[i].Description);
        }
      }
    }
    return devices;
}

/////////////////////////////////////////////////////////////////////////////
// FTD2XXRMPIO

FTD2XXRMPIO::FTD2XXRMPIO()
: configured(false), config_type(by_none), baudrate(460800), is_open(false)
{
  this->port_serial_number = "";
  this->port_description = "";
  this->port_index = 0;
  this->connected = false;
  this->usb_port_handle = NULL;
}

FTD2XXRMPIO::~FTD2XXRMPIO() {
  this->disconnect();
}

void FTD2XXRMPIO::connect() {
  if(!this->configured) {
    RMP_THROW_MSG(ConnectionFailedException, "The usb port must be "
      "configured before connecting.");
  }

  FT_STATUS result;

  this->enumerateUSBDevices_();

  // Select connection method and open
  switch (this->config_type) {
    case by_serial_number:
      this->connectBySerial();
      break;
    case by_description:
      this->connectByDescription();
      break;
    case by_index:
      this->connectByIndex();
      break;
    case by_none:
    default:
      RMP_THROW_MSG(ConnectionFailedException, "The usb port must be "
        "configured before connecting.");
        break;
  }

  this->is_open = true;

  // Configure the Baudrate
  try {
    result = FT_SetBaudRate(this->usb_port_handle, this->baudrate);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "setting the baudrate").c_str());
  }

  // Set default timeouts
  try {
    // 1 sec read and 1 sec write
    result = FT_SetTimeouts(this->usb_port_handle, 1000, 1000);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "setting timeouts").c_str());
  }

  // Set Latency Timer
  try {
    result = FT_SetLatencyTimer(this->usb_port_handle, 1);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "setting latency timer").c_str());
  }

  // Set flowcontrol
  try {
    result = FT_SetFlowControl(this->usb_port_handle, FT_FLOW_NONE, 0, 0);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "setting flowcontrol").c_str());
  }

  // Purge the I/O buffers of the usb device
  try {
    result = FT_Purge(this->usb_port_handle, FT_PURGE_RX | FT_PURGE_TX);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "purging the buffers").c_str());
  }

  this->connected = true;
}

void FTD2XXRMPIO::disconnect() {
  if(this->connected) {
    if (this->is_open) {
      FT_Close(this->usb_port_handle);
    }
    this->connected = false;
  }
}

int FTD2XXRMPIO::read(unsigned char* buffer, int size) {
  FT_STATUS result;
  DWORD bytes_read;

  try {
    result = FT_Read(this->usb_port_handle, buffer, size, &bytes_read);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ReadFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ReadFailedException,
      getErrorMessageByFT_STATUS(result, "reading").c_str());
  }

  return bytes_read;
}

int FTD2XXRMPIO::write(unsigned char* buffer, int size) {
  FT_STATUS result;
  DWORD bytes_written;

  try {
    result = FT_Write(this->usb_port_handle, buffer, size, &bytes_written);
  } catch(std::exception &e) {
    RMP_THROW_MSG(ReadFailedException, e.what());
  }
  if (result != FT_OK) {
    RMP_THROW_MSG(ReadFailedException,
      getErrorMessageByFT_STATUS(result, "reading").c_str());
  }

  return bytes_written;
}

std::vector<FT_DEVICE_LIST_INFO_NODE> FTD2XXRMPIO::enumerateUSBDevices_() {
  return enumerateUSBDevices();
}

void
FTD2XXRMPIO::configureUSBBySerial(std::string serial_number, int baudrate)
{
  this->config_type = by_serial_number;
  this->port_serial_number = serial_number;
  this->configured = true;
  this->baudrate = baudrate;
}

void FTD2XXRMPIO::connectBySerial() {
  FT_STATUS result;
  DWORD number_of_devices;

  try {
    // Open the usb port
    result = FT_OpenEx((PVOID)this->port_serial_number.c_str(),
                       (DWORD)FT_OPEN_BY_SERIAL_NUMBER,
                       &(this->usb_port_handle));
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (this->usb_port_handle == NULL) {
    // Failed to open port
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "opening the usb port").c_str());
  }
}

void
FTD2XXRMPIO::configureUSBByDescription(std::string description, int baudrate)
{
  this->config_type = by_description;
  this->port_description = description;
  this->configured = true;
  this->baudrate = baudrate;
}

void FTD2XXRMPIO::connectByDescription() {
  FT_STATUS result;

  try {
    // Open the usb port
    result = FT_OpenEx(const_cast<char *>(this->port_description.c_str()),
                       FT_OPEN_BY_DESCRIPTION,
                       &(this->usb_port_handle));
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (result != FT_OK) {
    // Failed to open port
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "opening the usb port").c_str());
  }
}

void
FTD2XXRMPIO::configureUSBByIndex(unsigned int device_index, int baudrate)
{
  this->config_type = by_index;
  this->port_index = device_index;
  this->configured = true;
  this->baudrate = baudrate;
}

void FTD2XXRMPIO::connectByIndex() {
  FT_STATUS result;

  try {
    // Open the usb port
    result = FT_Open(this->port_index, &(this->usb_port_handle));
  } catch(std::exception &e) {
    RMP_THROW_MSG(ConnectionFailedException, e.what());
  }
  if (this->usb_port_handle == NULL) {
    // Failed to open port
    RMP_THROW_MSG(ConnectionFailedException,
      getErrorMessageByFT_STATUS(result, "opening the usb port").c_str());
  }
}

<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "server_util.hpp"
#include <glog/logging.h>

#include <iostream>
#include <iomanip>
#include <pficommon/text/json.h>

#include "../common/util.hpp"
#include "../common/network.hpp"
#include "../common/cmdline.h"
#include "../common/exception.hpp"
#include "../common/membership.hpp"
#include "../common/config.hpp"

namespace jubatus {
namespace framework {

static const std::string VERSION(JUBATUS_VERSION);

void print_version(const std::string& progname){
  std::cout << "jubatus-" << VERSION << " (" << progname << ")" << std::endl;
}

std::string get_conf(const server_argv& a){

  config_json conf;

  try{
    if (a.is_standalone()) {
      conf.load_json(a.configpath);
    }else{
#ifdef HAVE_ZOOKEEPER_H
      conf.load_json(a.z, a.type, a.name);
#endif
    }
  } catch (const jubatus::exception::jubatus_exception& e) {
    LOG(ERROR) << e.what();
    exit(1);
  }
  return conf.config;
}

void config_json::load_json(const std::string& zkhosts, const std::string& type, const std::string& name)
{
#ifdef HAVE_ZOOKEEPER_H
  jubatus::common::config_fromzk(*ls, type, name, config);
#endif
}

void config_json::load_json(const std::string& filepath)
{
    jubatus::common::config_fromlocal(filepath, config);
}

server_argv::server_argv(int args, char** argv, const std::string& type)
  : type(type)
{
  google::InitGoogleLogging(argv[0]);

  cmdline::parser p;
  p.add<int>("rpc-port", 'p', "port number", false, 9199);
  p.add<std::string>("listen_addr", 'b', "bind IP address", false, "" );
  p.add<std::string>("listen_if", 'B', "bind network interfance", false, "");
  p.add<int>("thread", 'c', "concurrency = thread number", false, 2);
  p.add<int>("timeout", 't', "time out (sec)", false, 10);
  p.add<std::string>("datadir", 'd', "directory to save and load models", false, "/tmp");
  p.add<std::string>("logdir", 'l', "directory to output logs (instead of stderr)", false, "");
  p.add<int,cmdline::range_reader<int> >("loglevel", 'e', "verbosity of log messages", false,
                                         google::INFO, cmdline::range(google::INFO, google::FATAL));
  p.add<std::string>("configpath", 'f', "config option need to specify json file when standalone mode (without ZK mode)", false, "");

#ifdef HAVE_ZOOKEEPER_H
  p.add<std::string>("zookeeper", 'z', "zookeeper location", false);
  p.add<std::string>("name", 'n', "learning machine instance name", false);
  p.add("join", 'j', "join to the existing cluster");
  p.add<int>("interval_sec", 's', "mix interval by seconds", false, 16);
  p.add<int>("interval_count", 'i', "mix interval by update count", false, 512);
#endif

  // APPLY CHANGES TO JUBAVISOR WHEN ARGUMENTS MODIFIED

  p.add("version", 'v', "version");

  p.parse_check(args, argv);

  if( p.exist("version") ){
    print_version(jubatus::util::get_program_name());
    exit(0);
  }

  port = p.get<int>("rpc-port");
  bind_address = p.get<std::string>("listen_addr");
  bind_if = p.get<std::string>("listen_if");
  threadnum = p.get<int>("thread");
  timeout = p.get<int>("timeout");
  program_name = jubatus::util::get_program_name();
  datadir = p.get<std::string>("datadir");
  logdir = p.get<std::string>("logdir");
  loglevel = p.get<int>("loglevel");
  configpath = p.get<std::string>("configpath");

  // determine listen-address and IPaddr used as ZK 'node-name'
  // TODO: check bind_address is valid format
  if ( !bind_address.empty() ) {
    eth = bind_address;
  } else if ( !bind_if.empty() ) {
    bind_address = eth = jubatus::util::get_ip( bind_if.c_str() );
  } else {
    bind_address = "0.0.0.0";
    eth = jubatus::common::get_default_v4_address();
  }

#ifdef HAVE_ZOOKEEPER_H
  z = p.get<std::string>("zookeeper");
  name = p.get<std::string>("name");
  join = p.exist("join");
  interval_sec = p.get<int>("interval_sec");
  interval_count = p.get<int>("interval_count");
#else
  z = "";
  name = "";
  join = false;
  interval_sec = 16;
  interval_count = 512;
#endif

  if(!is_standalone() && name.empty()){
    std::cerr << "can't start multinode mode without name specified" << std::endl;
    std::cerr << p.usage() << std::endl;
    exit(1);
  }

  if (is_standalone() && configpath.empty()){
    std::cerr << "can't start standalone mode without configpath specified" << std::endl;
    std::cerr << p.usage() << std::endl;
    exit(1);
  }

  if ( (!logdir.empty()) && (!jubatus::util::is_writable(logdir.c_str())) ) {
    std::cerr << "can't create log file: " << strerror(errno) << std::endl;
    exit(1);
  }
  set_log_destination(jubatus::util::get_program_name());

  boot_message(jubatus::util::get_program_name());
}

server_argv::server_argv():
  join(false), port(9199), timeout(10), threadnum(2), z(""), name(""),
  datadir("/tmp"), logdir(""), loglevel(google::INFO), eth("localhost"),
  interval_sec(5), interval_count(1024)
{
}

void server_argv::boot_message(const std::string& progname) const {
  std::stringstream ss;
  ss << "starting " << progname << " " << VERSION << " RPC server at " << eth << ":" << port << '\n';
  ss << "    pid            : " << getpid() << '\n';
  ss << "    user           : " << jubatus::util::get_user_name() << '\n';
  ss << "    mode           : ";
  if(is_standalone()) {
    ss << "standalone mode\n";
  } else {
    ss << "multinode mode\n";
  }
  ss << "    timeout        : " << timeout << '\n';
  ss << "    thread         : " << threadnum << '\n';
  ss << "    datadir        : " << datadir << '\n';
  ss << "    logdir         : " << logdir << '\n';
  ss << "    loglevel       : " << google::GetLogSeverityName(loglevel) << '(' << loglevel << ')' << '\n';
#ifdef HAVE_ZOOKEEPER_H
  ss << "    zookeeper      : " << z << '\n';
  ss << "    name           : " << name << '\n';
  ss << "    join           : " << std::boolalpha << join << '\n';
  ss << "    interval sec   : " << interval_sec << '\n';
  ss << "    interval count : " << interval_count << '\n';
#endif
  LOG(INFO) << ss.str();
}

void server_argv::set_log_destination(const std::string& progname) const {
  if (logdir.empty()) {
    for (int severity = google::INFO; severity < google::NUM_SEVERITIES; severity++) {
      google::SetLogDestination(severity, "");
    }
    google::SetStderrLogging(loglevel);
  } else {
    for (int severity = google::INFO; severity < loglevel; severity++) {
      google::SetLogDestination(severity, "");
    }
    std::ostringstream basename, logdest, symlink;
    basename << progname << "." << eth << "_" << port;
    logdest << logdir << "/" << basename.str() << "." << (name.empty() ? "" : name + ".") << "log.";
    symlink << basename.str() << "." << getpid();
    google::SetLogDestination(loglevel, logdest.str().c_str());
    google::SetLogSymlink(loglevel, symlink.str().c_str());
    google::SetStderrLogging(google::FATAL);
  }
}

std::string get_server_identifier(const server_argv& a) {
  std::stringstream ss;
  ss << a.eth;
  ss << "_";
  ss << a.port;
  return ss.str();
}

keeper_argv::keeper_argv(int args, char** argv, const std::string& t)
  : type(t)
{
  google::InitGoogleLogging(argv[0]);

  cmdline::parser p;
  p.add<int>("rpc-port", 'p', "port number", false, 9199);
  p.add<std::string>("listen_addr", 'b', "bind IP address", false, "" );
  p.add<std::string>("listen_if", 'B', "bind network interfance", false, "");
  p.add<int>("thread", 'c', "concurrency = thread number", false, 16);
  p.add<int>("timeout", 't', "time out (sec)", false, 10);

  p.add<std::string>("zookeeper", 'z', "zookeeper location", false, "localhost:2181");
  p.add<std::string>("logdir", 'l', "directory to output logs (instead of stderr)", false, "");
  p.add<int,cmdline::range_reader<int> >("loglevel", 'e', "verbosity of log messages", false,
                                         google::INFO, cmdline::range(google::INFO, google::FATAL));
  p.add("version", 'v', "version");

  p.parse_check(args, argv);

  if( p.exist("version") ){
    print_version(jubatus::util::get_program_name());
    exit(0);
  }

  port = p.get<int>("rpc-port");
  bind_address = p.get<std::string>("listen_addr");
  bind_if = p.get<std::string>("listen_if");
  threadnum = p.get<int>("thread");
  timeout = p.get<int>("timeout");
  program_name = jubatus::util::get_program_name();
  z = p.get<std::string>("zookeeper");
  logdir = p.get<std::string>("logdir");
  loglevel = p.get<int>("loglevel");

  // determine listen-address and IPaddr used as ZK 'node-name'
  // TODO: check bind_address is valid format
  if ( !bind_address.empty() ) {
    eth = bind_address;
  } else if ( !bind_if.empty() ) {
    bind_address = eth = jubatus::util::get_ip( bind_if.c_str() );
  } else {
    bind_address = "0.0.0.0";
    eth = jubatus::common::get_default_v4_address();
  }

  if ( (!logdir.empty()) && (!jubatus::util::is_writable(logdir.c_str())) ) {
    std::cerr << "can't create log file: " << strerror(errno) << std::endl;
    exit(1);
  }
  set_log_destination(jubatus::util::get_program_name());

  boot_message(jubatus::util::get_program_name());
}

keeper_argv::keeper_argv():
  port(9199), timeout(10), threadnum(16), z("localhost:2181"), logdir(""), loglevel(google::INFO), eth("")
{
}

void keeper_argv::boot_message(const std::string& progname) const {
  std::stringstream ss;
  ss << "starting " << progname << " " << VERSION << " RPC server at " << eth << ":" << port << '\n';
  ss << "    pid            : " << getpid() << '\n';
  ss << "    user           : " << jubatus::util::get_user_name() << '\n';
  ss << "    timeout        : " << timeout << '\n';
  ss << "    thread         : " << threadnum << '\n';
  ss << "    logdir         : " << logdir << '\n';
  ss << "    loglevel       : " << google::GetLogSeverityName(loglevel) << '(' << loglevel << ')' << '\n';
  ss << "    zookeeper      : " << z << '\n';
  LOG(INFO) << ss.str();
}

void keeper_argv::set_log_destination(const std::string& progname) const {
  if (logdir.empty()) {
    for (int severity = google::INFO; severity < google::NUM_SEVERITIES; severity++) {
      google::SetLogDestination(severity, "");
    }
    google::SetStderrLogging(loglevel);
  } else {
    for (int severity = google::INFO; severity < loglevel; severity++) {
      google::SetLogDestination(severity, "");
    }
    std::ostringstream basename, logdest, symlink;
    basename << progname << "." << eth << "_" << port;
    logdest << logdir << "/" << basename.str() << ".log.";
    symlink << basename.str() << "." << getpid();
    google::SetLogDestination(loglevel, logdest.str().c_str());
    google::SetLogSymlink(loglevel, symlink.str().c_str());
    google::SetStderrLogging(google::FATAL);
  }
}

common::cshared_ptr<jubatus::common::lock_service> ls;

void atexit(){
#ifdef HAVE_ZOOKEEPER_H
  if(ls)
    ls->force_close();
#endif
}

} // framework
} // jubatus
<commit_msg>print bind address on booting<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "server_util.hpp"
#include <glog/logging.h>

#include <iostream>
#include <iomanip>
#include <pficommon/text/json.h>

#include "../common/util.hpp"
#include "../common/network.hpp"
#include "../common/cmdline.h"
#include "../common/exception.hpp"
#include "../common/membership.hpp"
#include "../common/config.hpp"

namespace jubatus {
namespace framework {

static const std::string VERSION(JUBATUS_VERSION);

void print_version(const std::string& progname){
  std::cout << "jubatus-" << VERSION << " (" << progname << ")" << std::endl;
}

std::string get_conf(const server_argv& a){

  config_json conf;

  try{
    if (a.is_standalone()) {
      conf.load_json(a.configpath);
    }else{
#ifdef HAVE_ZOOKEEPER_H
      conf.load_json(a.z, a.type, a.name);
#endif
    }
  } catch (const jubatus::exception::jubatus_exception& e) {
    LOG(ERROR) << e.what();
    exit(1);
  }
  return conf.config;
}

void config_json::load_json(const std::string& zkhosts, const std::string& type, const std::string& name)
{
#ifdef HAVE_ZOOKEEPER_H
  jubatus::common::config_fromzk(*ls, type, name, config);
#endif
}

void config_json::load_json(const std::string& filepath)
{
    jubatus::common::config_fromlocal(filepath, config);
}

server_argv::server_argv(int args, char** argv, const std::string& type)
  : type(type)
{
  google::InitGoogleLogging(argv[0]);

  cmdline::parser p;
  p.add<int>("rpc-port", 'p', "port number", false, 9199);
  p.add<std::string>("listen_addr", 'b', "bind IP address", false, "" );
  p.add<std::string>("listen_if", 'B', "bind network interfance", false, "");
  p.add<int>("thread", 'c', "concurrency = thread number", false, 2);
  p.add<int>("timeout", 't', "time out (sec)", false, 10);
  p.add<std::string>("datadir", 'd', "directory to save and load models", false, "/tmp");
  p.add<std::string>("logdir", 'l', "directory to output logs (instead of stderr)", false, "");
  p.add<int,cmdline::range_reader<int> >("loglevel", 'e', "verbosity of log messages", false,
                                         google::INFO, cmdline::range(google::INFO, google::FATAL));
  p.add<std::string>("configpath", 'f', "config option need to specify json file when standalone mode (without ZK mode)", false, "");

#ifdef HAVE_ZOOKEEPER_H
  p.add<std::string>("zookeeper", 'z', "zookeeper location", false);
  p.add<std::string>("name", 'n', "learning machine instance name", false);
  p.add("join", 'j', "join to the existing cluster");
  p.add<int>("interval_sec", 's', "mix interval by seconds", false, 16);
  p.add<int>("interval_count", 'i', "mix interval by update count", false, 512);
#endif

  // APPLY CHANGES TO JUBAVISOR WHEN ARGUMENTS MODIFIED

  p.add("version", 'v', "version");

  p.parse_check(args, argv);

  if( p.exist("version") ){
    print_version(jubatus::util::get_program_name());
    exit(0);
  }

  port = p.get<int>("rpc-port");
  bind_address = p.get<std::string>("listen_addr");
  bind_if = p.get<std::string>("listen_if");
  threadnum = p.get<int>("thread");
  timeout = p.get<int>("timeout");
  program_name = jubatus::util::get_program_name();
  datadir = p.get<std::string>("datadir");
  logdir = p.get<std::string>("logdir");
  loglevel = p.get<int>("loglevel");
  configpath = p.get<std::string>("configpath");

  // determine listen-address and IPaddr used as ZK 'node-name'
  // TODO: check bind_address is valid format
  if ( !bind_address.empty() ) {
    eth = bind_address;
  } else if ( !bind_if.empty() ) {
    bind_address = eth = jubatus::util::get_ip( bind_if.c_str() );
  } else {
    bind_address = "0.0.0.0";
    eth = jubatus::common::get_default_v4_address();
  }

#ifdef HAVE_ZOOKEEPER_H
  z = p.get<std::string>("zookeeper");
  name = p.get<std::string>("name");
  join = p.exist("join");
  interval_sec = p.get<int>("interval_sec");
  interval_count = p.get<int>("interval_count");
#else
  z = "";
  name = "";
  join = false;
  interval_sec = 16;
  interval_count = 512;
#endif

  if(!is_standalone() && name.empty()){
    std::cerr << "can't start multinode mode without name specified" << std::endl;
    std::cerr << p.usage() << std::endl;
    exit(1);
  }

  if (is_standalone() && configpath.empty()){
    std::cerr << "can't start standalone mode without configpath specified" << std::endl;
    std::cerr << p.usage() << std::endl;
    exit(1);
  }

  if ( (!logdir.empty()) && (!jubatus::util::is_writable(logdir.c_str())) ) {
    std::cerr << "can't create log file: " << strerror(errno) << std::endl;
    exit(1);
  }
  set_log_destination(jubatus::util::get_program_name());

  boot_message(jubatus::util::get_program_name());
}

server_argv::server_argv():
  join(false), port(9199), timeout(10), threadnum(2), z(""), name(""),
  datadir("/tmp"), logdir(""), loglevel(google::INFO), eth("localhost"),
  interval_sec(5), interval_count(1024)
{
}

void server_argv::boot_message(const std::string& progname) const {
  std::stringstream ss;
  ss << "starting " << progname << " " << VERSION << " RPC server at " << eth << ":" << port << '\n';
  ss << "    pid            : " << getpid() << '\n';
  ss << "    user           : " << jubatus::util::get_user_name() << '\n';
  ss << "    mode           : ";
  if(is_standalone()) {
    ss << "standalone mode\n";
  } else {
    ss << "multinode mode\n";
  }
  ss << "    timeout        : " << timeout << '\n';
  ss << "    thread         : " << threadnum << '\n';
  ss << "    datadir        : " << datadir << '\n';
  ss << "    logdir         : " << logdir << '\n';
  ss << "    loglevel       : " << google::GetLogSeverityName(loglevel) << '(' << loglevel << ')' << '\n';
  ss << "    bind address   : " << bind_address << '\n';
#ifdef HAVE_ZOOKEEPER_H
  ss << "    zookeeper      : " << z << '\n';
  ss << "    name           : " << name << '\n';
  ss << "    join           : " << std::boolalpha << join << '\n';
  ss << "    interval sec   : " << interval_sec << '\n';
  ss << "    interval count : " << interval_count << '\n';
#endif
  LOG(INFO) << ss.str();
}

void server_argv::set_log_destination(const std::string& progname) const {
  if (logdir.empty()) {
    for (int severity = google::INFO; severity < google::NUM_SEVERITIES; severity++) {
      google::SetLogDestination(severity, "");
    }
    google::SetStderrLogging(loglevel);
  } else {
    for (int severity = google::INFO; severity < loglevel; severity++) {
      google::SetLogDestination(severity, "");
    }
    std::ostringstream basename, logdest, symlink;
    basename << progname << "." << eth << "_" << port;
    logdest << logdir << "/" << basename.str() << "." << (name.empty() ? "" : name + ".") << "log.";
    symlink << basename.str() << "." << getpid();
    google::SetLogDestination(loglevel, logdest.str().c_str());
    google::SetLogSymlink(loglevel, symlink.str().c_str());
    google::SetStderrLogging(google::FATAL);
  }
}

std::string get_server_identifier(const server_argv& a) {
  std::stringstream ss;
  ss << a.eth;
  ss << "_";
  ss << a.port;
  return ss.str();
}

keeper_argv::keeper_argv(int args, char** argv, const std::string& t)
  : type(t)
{
  google::InitGoogleLogging(argv[0]);

  cmdline::parser p;
  p.add<int>("rpc-port", 'p', "port number", false, 9199);
  p.add<std::string>("listen_addr", 'b', "bind IP address", false, "" );
  p.add<std::string>("listen_if", 'B', "bind network interfance", false, "");
  p.add<int>("thread", 'c', "concurrency = thread number", false, 16);
  p.add<int>("timeout", 't', "time out (sec)", false, 10);

  p.add<std::string>("zookeeper", 'z', "zookeeper location", false, "localhost:2181");
  p.add<std::string>("logdir", 'l', "directory to output logs (instead of stderr)", false, "");
  p.add<int,cmdline::range_reader<int> >("loglevel", 'e', "verbosity of log messages", false,
                                         google::INFO, cmdline::range(google::INFO, google::FATAL));
  p.add("version", 'v', "version");

  p.parse_check(args, argv);

  if( p.exist("version") ){
    print_version(jubatus::util::get_program_name());
    exit(0);
  }

  port = p.get<int>("rpc-port");
  bind_address = p.get<std::string>("listen_addr");
  bind_if = p.get<std::string>("listen_if");
  threadnum = p.get<int>("thread");
  timeout = p.get<int>("timeout");
  program_name = jubatus::util::get_program_name();
  z = p.get<std::string>("zookeeper");
  logdir = p.get<std::string>("logdir");
  loglevel = p.get<int>("loglevel");

  // determine listen-address and IPaddr used as ZK 'node-name'
  // TODO: check bind_address is valid format
  if ( !bind_address.empty() ) {
    eth = bind_address;
  } else if ( !bind_if.empty() ) {
    bind_address = eth = jubatus::util::get_ip( bind_if.c_str() );
  } else {
    bind_address = "0.0.0.0";
    eth = jubatus::common::get_default_v4_address();
  }

  if ( (!logdir.empty()) && (!jubatus::util::is_writable(logdir.c_str())) ) {
    std::cerr << "can't create log file: " << strerror(errno) << std::endl;
    exit(1);
  }
  set_log_destination(jubatus::util::get_program_name());

  boot_message(jubatus::util::get_program_name());
}

keeper_argv::keeper_argv():
  port(9199), timeout(10), threadnum(16), z("localhost:2181"), logdir(""), loglevel(google::INFO), eth("")
{
}

void keeper_argv::boot_message(const std::string& progname) const {
  std::stringstream ss;
  ss << "starting " << progname << " " << VERSION << " RPC server at " << eth << ":" << port << '\n';
  ss << "    pid            : " << getpid() << '\n';
  ss << "    user           : " << jubatus::util::get_user_name() << '\n';
  ss << "    timeout        : " << timeout << '\n';
  ss << "    thread         : " << threadnum << '\n';
  ss << "    logdir         : " << logdir << '\n';
  ss << "    loglevel       : " << google::GetLogSeverityName(loglevel) << '(' << loglevel << ')' << '\n';
  ss << "    bind address   : " << bind_address << '\n';
  ss << "    zookeeper      : " << z << '\n';
  LOG(INFO) << ss.str();
}

void keeper_argv::set_log_destination(const std::string& progname) const {
  if (logdir.empty()) {
    for (int severity = google::INFO; severity < google::NUM_SEVERITIES; severity++) {
      google::SetLogDestination(severity, "");
    }
    google::SetStderrLogging(loglevel);
  } else {
    for (int severity = google::INFO; severity < loglevel; severity++) {
      google::SetLogDestination(severity, "");
    }
    std::ostringstream basename, logdest, symlink;
    basename << progname << "." << eth << "_" << port;
    logdest << logdir << "/" << basename.str() << ".log.";
    symlink << basename.str() << "." << getpid();
    google::SetLogDestination(loglevel, logdest.str().c_str());
    google::SetLogSymlink(loglevel, symlink.str().c_str());
    google::SetStderrLogging(google::FATAL);
  }
}

common::cshared_ptr<jubatus::common::lock_service> ls;

void atexit(){
#ifdef HAVE_ZOOKEEPER_H
  if(ls)
    ls->force_close();
#endif
}

} // framework
} // jubatus
<|endoftext|>


<commit_before>#include <vector>
#include <stdio.h>
#include <assert.h>

#include <Kokkos_Core.hpp>

template <class Scalar>
struct fourDTensorArray {
  std::vector<Scalar> _data;
  const unsigned int _numCells;
  const unsigned int _numFields;
  const unsigned int _numPoints;
  const unsigned int _dimVec;

  fourDTensorArray(const unsigned int cl, const unsigned int bf, const unsigned int qp, const unsigned int iVec)
  :_numCells(cl), _numFields(bf), _numPoints(qp), _dimVec(iVec), _data(cl*bf*qp*iVec) {
  }

  inline
  Scalar &
  operator()(const unsigned int cl, const unsigned int bf, const unsigned int qp, const unsigned int iVec) {
    return _data[cl * _numFields * _numPoints * _dimVec + bf * _numPoints * _dimVec  + qp * _dimVec + iVec];
  }

  inline
  Scalar
  operator()(const unsigned int cl, const unsigned int bf, const unsigned int qp, const unsigned int iVec) const {
    return _data[cl * _numFields * _numPoints * _dimVec + bf * _numPoints * _dimVec  + qp * _dimVec + iVec];
  }

  void
  fill(const Scalar d) {
    std::fill(_data.begin(), _data.end(), d);
  }
};

template <class Scalar>
struct threeDTensorArray {
  std::vector<Scalar> _data;
  const unsigned int _numCells;
  const unsigned int _numFields;
  const unsigned int _numPoints;

  threeDTensorArray(const unsigned int cl, const unsigned int bf, const unsigned int qp)
  :_numCells(cl), _numFields(bf), _numPoints(qp), _data(cl*bf*qp) {
  }

  inline
  Scalar &
  operator()(const unsigned int cl, const unsigned int bf, const unsigned int qp) {
    return _data[cl * _numFields * _numPoints + bf * _numPoints + qp];
  }

  inline
  Scalar
  operator()(const unsigned int cl, const unsigned int bf, const unsigned int qp) const {
    return _data[cl * _numFields * _numPoints + bf * _numPoints + qp];
  }

  void
  fill(const Scalar d) {
    std::fill(_data.begin(), _data.end(), d);
  }
};

enum ECompEngine {COMP_CPP, COMP_BLAS, COMP_KOKKOS};

template <class Scalar>
void contractFieldFieldVectorSerial(threeDTensorArray<Scalar> &         outputFields,
                                    const fourDTensorArray<Scalar> &    leftFields,
                                    const fourDTensorArray<Scalar> &    rightFields,
                                    const ECompEngine           compEngine,
                                    const bool                  sumInto) {

  const unsigned int numCells        = leftFields._numCells;
  const unsigned int numLeftFields   = leftFields._numFields;
  const unsigned int numRightFields  = rightFields._numFields;
  const unsigned int numPoints       = leftFields._numPoints;
  const unsigned int dimVec          = leftFields._dimVec;

  switch(compEngine) {
    case COMP_CPP: {
      if (sumInto) {
        for (unsigned int cl = 0; cl < numCells; cl++) {
          for (unsigned int lbf = 0; lbf < numLeftFields; lbf++) {
            for (unsigned int rbf = 0; rbf < numRightFields; rbf++) {
              Scalar tmpVal(0);
              for (unsigned int qp = 0; qp < numPoints; qp++) {
                for (unsigned int iVec = 0; iVec < dimVec; iVec++) {
                  tmpVal += leftFields(cl, lbf, qp, iVec)*rightFields(cl, rbf, qp, iVec);
                } //D-loop
              } // P-loop
              outputFields(cl, lbf, rbf) += tmpVal;
            } // R-loop
          } // L-loop
        } // C-loop
      }
      else {
        for (unsigned int cl = 0; cl < numCells; cl++) {
          for (unsigned int lbf = 0; lbf < numLeftFields; lbf++) {
            for (unsigned int rbf = 0; rbf < numRightFields; rbf++) {
              Scalar tmpVal(0);
              for (unsigned int qp = 0; qp < numPoints; qp++) {
                for (unsigned int iVec = 0; iVec < dimVec; iVec++) {
                  tmpVal += leftFields(cl, lbf, qp, iVec)*rightFields(cl, rbf, qp, iVec);
                } //D-loop
              } // P-loop
              outputFields(cl, lbf, rbf) = tmpVal;
            } // R-loop
          } // L-loop
        } // C-loop
      }
    }
    break;
  }
}

int main(int argc, const char* argv[]) {
  const unsigned int dummySize = 10;

  fourDTensorArray<double> leftInput(dummySize, dummySize, dummySize, dummySize);
  fourDTensorArray<double> rightInput(dummySize, dummySize, dummySize, dummySize);
  threeDTensorArray<double> output(dummySize, dummySize, dummySize);

  leftInput.fill(1);
  rightInput.fill(1);
  output.fill(1);

  for (unsigned int cl = 0; cl < dummySize; cl++) {
    for (unsigned int lbf = 0; lbf < dummySize; lbf++) {
      for (unsigned int rbf = 0; rbf < dummySize; rbf++) {
        if (output(cl, lbf, rbf) != 1) {
          printf("Output at %d, %d, %d should be 1; instead is %f\n", cl, lbf, rbf, output(cl, lbf, rbf));
          return 1;
        }
      }
    }
  }

  contractFieldFieldVectorSerial<double>(output, leftInput, rightInput, COMP_CPP, false);

  for (unsigned int cl = 0; cl < dummySize; cl++) {
    for (unsigned int lbf = 0; lbf < dummySize; lbf++) {
      for (unsigned int rbf = 0; rbf < dummySize; rbf++) {
        if (output(cl, lbf, rbf) != 100) {
          printf("Output at %d, %d, %d should be 100; instead is %f\n", cl, lbf, rbf, output(cl, lbf, rbf));
          return 1;
        }
      }
    }
  }

  printf("passed serial, sumInto = false\n");

  output.fill(1);

  contractFieldFieldVectorSerial<double>(output, leftInput, rightInput, COMP_CPP, true);

  for (unsigned int cl = 0; cl < dummySize; cl++) {
    for (unsigned int lbf = 0; lbf < dummySize; lbf++) {
      for (unsigned int rbf = 0; rbf < dummySize; rbf++) {
        if (output(cl, lbf, rbf) != 101) {
          printf("Output at %d, %d, %d should be 101; instead is %f\n", cl, lbf, rbf, output(cl, lbf, rbf));
          return 1;
        }
      }
    }
  }
  printf("passed serial, sumInto = true\n");

  return 0;
}
<commit_msg>fixed some compile warnings<commit_after>#include <vector>
#include <stdio.h>
#include <assert.h>

#include <Kokkos_Core.hpp>

template <class Scalar>
struct fourDTensorArray {
  std::vector<Scalar> _data;
  const unsigned int _numCells;
  const unsigned int _numFields;
  const unsigned int _numPoints;
  const unsigned int _dimVec;

  fourDTensorArray(const unsigned int cl, const unsigned int bf, const unsigned int qp, const unsigned int iVec)
  :_data(cl*bf*qp*iVec), _numCells(cl), _numFields(bf), _numPoints(qp), _dimVec(iVec) {
  }

  inline
  Scalar &
  operator()(const unsigned int cl, const unsigned int bf, const unsigned int qp, const unsigned int iVec) {
    return _data[cl * _numFields * _numPoints * _dimVec + bf * _numPoints * _dimVec  + qp * _dimVec + iVec];
  }

  inline
  Scalar
  operator()(const unsigned int cl, const unsigned int bf, const unsigned int qp, const unsigned int iVec) const {
    return _data[cl * _numFields * _numPoints * _dimVec + bf * _numPoints * _dimVec  + qp * _dimVec + iVec];
  }

  void
  fill(const Scalar d) {
    std::fill(_data.begin(), _data.end(), d);
  }
};

template <class Scalar>
struct threeDTensorArray {
  std::vector<Scalar> _data;
  const unsigned int _numCells;
  const unsigned int _numFields;
  const unsigned int _numPoints;

  threeDTensorArray(const unsigned int cl, const unsigned int bf, const unsigned int qp)
  :_data(cl*bf*qp), _numCells(cl), _numFields(bf), _numPoints(qp) {
  }

  inline
  Scalar &
  operator()(const unsigned int cl, const unsigned int bf, const unsigned int qp) {
    return _data[cl * _numFields * _numPoints + bf * _numPoints + qp];
  }

  inline
  Scalar
  operator()(const unsigned int cl, const unsigned int bf, const unsigned int qp) const {
    return _data[cl * _numFields * _numPoints + bf * _numPoints + qp];
  }

  void
  fill(const Scalar d) {
    std::fill(_data.begin(), _data.end(), d);
  }
};

enum ECompEngine {COMP_CPP, COMP_BLAS, COMP_KOKKOS};

template <class Scalar>
void contractFieldFieldVectorSerial(threeDTensorArray<Scalar> &         outputFields,
                                    const fourDTensorArray<Scalar> &    leftFields,
                                    const fourDTensorArray<Scalar> &    rightFields,
                                    const ECompEngine           compEngine,
                                    const bool                  sumInto) {

  const unsigned int numCells        = leftFields._numCells;
  const unsigned int numLeftFields   = leftFields._numFields;
  const unsigned int numRightFields  = rightFields._numFields;
  const unsigned int numPoints       = leftFields._numPoints;
  const unsigned int dimVec          = leftFields._dimVec;

  switch(compEngine) {
    case COMP_CPP: {
      if (sumInto) {
        for (unsigned int cl = 0; cl < numCells; cl++) {
          for (unsigned int lbf = 0; lbf < numLeftFields; lbf++) {
            for (unsigned int rbf = 0; rbf < numRightFields; rbf++) {
              Scalar tmpVal(0);
              for (unsigned int qp = 0; qp < numPoints; qp++) {
                for (unsigned int iVec = 0; iVec < dimVec; iVec++) {
                  tmpVal += leftFields(cl, lbf, qp, iVec)*rightFields(cl, rbf, qp, iVec);
                } //D-loop
              } // P-loop
              outputFields(cl, lbf, rbf) += tmpVal;
            } // R-loop
          } // L-loop
        } // C-loop
      }
      else {
        for (unsigned int cl = 0; cl < numCells; cl++) {
          for (unsigned int lbf = 0; lbf < numLeftFields; lbf++) {
            for (unsigned int rbf = 0; rbf < numRightFields; rbf++) {
              Scalar tmpVal(0);
              for (unsigned int qp = 0; qp < numPoints; qp++) {
                for (unsigned int iVec = 0; iVec < dimVec; iVec++) {
                  tmpVal += leftFields(cl, lbf, qp, iVec)*rightFields(cl, rbf, qp, iVec);
                } //D-loop
              } // P-loop
              outputFields(cl, lbf, rbf) = tmpVal;
            } // R-loop
          } // L-loop
        } // C-loop
      }
    }
    break;
  }
}

int main(int argc, const char* argv[]) {
  const unsigned int dummySize = 10;

  fourDTensorArray<double> leftInput(dummySize, dummySize, dummySize, dummySize);
  fourDTensorArray<double> rightInput(dummySize, dummySize, dummySize, dummySize);
  threeDTensorArray<double> output(dummySize, dummySize, dummySize);

  leftInput.fill(1);
  rightInput.fill(1);
  output.fill(1);

  for (unsigned int cl = 0; cl < dummySize; cl++) {
    for (unsigned int lbf = 0; lbf < dummySize; lbf++) {
      for (unsigned int rbf = 0; rbf < dummySize; rbf++) {
        if (output(cl, lbf, rbf) != 1) {
          printf("Output at %d, %d, %d should be 1; instead is %f\n", cl, lbf, rbf, output(cl, lbf, rbf));
          return 1;
        }
      }
    }
  }

  contractFieldFieldVectorSerial<double>(output, leftInput, rightInput, COMP_CPP, false);

  for (unsigned int cl = 0; cl < dummySize; cl++) {
    for (unsigned int lbf = 0; lbf < dummySize; lbf++) {
      for (unsigned int rbf = 0; rbf < dummySize; rbf++) {
        if (output(cl, lbf, rbf) != 100) {
          printf("Output at %d, %d, %d should be 100; instead is %f\n", cl, lbf, rbf, output(cl, lbf, rbf));
          return 1;
        }
      }
    }
  }

  printf("passed serial, sumInto = false\n");

  output.fill(1);

  contractFieldFieldVectorSerial<double>(output, leftInput, rightInput, COMP_CPP, true);

  for (unsigned int cl = 0; cl < dummySize; cl++) {
    for (unsigned int lbf = 0; lbf < dummySize; lbf++) {
      for (unsigned int rbf = 0; rbf < dummySize; rbf++) {
        if (output(cl, lbf, rbf) != 101) {
          printf("Output at %d, %d, %d should be 101; instead is %f\n", cl, lbf, rbf, output(cl, lbf, rbf));
          return 1;
        }
      }
    }
  }
  printf("passed serial, sumInto = true\n");

  return 0;
}
<|endoftext|>


<commit_before>/* This file is part of the KDE project
   Copyright (C) 2009 Erlend Hamberg <ehamberg@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include <klocale.h>
#include "kateapp.h"
#include "kateappcommands.h"
#include "katemainwindow.h"
#include "katedocmanager.h"
#include "kateviewmanager.h"

KateAppCommands::KateAppCommands()
    : KTextEditor::Command()
{
    KTextEditor::Editor *editor = KateDocManager::self()->editor();
    KTextEditor::CommandInterface *iface = qobject_cast<KTextEditor::CommandInterface*>(editor);

    if (iface) {
        iface->registerCommand(this);
    }

    re_write.setPattern("w(a)?");
    re_quit.setPattern("(w)?q?(a)?");
    re_exit.setPattern("x(a)?");
    re_changeBuffer.setPattern("b(n|p)");
    re_edit.setPattern("e(dit)?");
    re_new.setPattern("(v)?new");
}

KateAppCommands::~KateAppCommands()
{
    KTextEditor::Editor *editor = KateDocManager::self()->editor();
    KTextEditor::CommandInterface *iface = qobject_cast<KTextEditor::CommandInterface*>(editor);

    if (iface) {
        iface->unregisterCommand(this);
    }
}

const QStringList& KateAppCommands::cmds()
{
    static QStringList l;

    if (l.empty()) {
        l << "q" << "qa" << "w" << "wq" << "wa" << "wqa" << "x" << "xa"
          << "bn" << "bp" << "new" << "vnew" << "e" << "edit" << "enew";
    }

    return l;
}

bool KateAppCommands::exec(KTextEditor::View *view, const QString &cmd, QString &msg)
{
    QStringList args(cmd.split( QRegExp("\\s+"), QString::SkipEmptyParts)) ;
    QString command( args.takeFirst() );

    KateMainWindow *mainWin = KateApp::self()->activeMainWindow();

    if (re_write.exactMatch(command)) {
        if (!re_write.cap(1).isEmpty()) { // [a]ll
            KateDocManager::self()->saveAll();
            msg = i18n("All documents written to disk");
        } else {
            view->document()->documentSave();
            msg = i18n("Document written to disk");
        }
    }
    else if (re_quit.exactMatch(command)) {
        if (!re_quit.cap(2).isEmpty()) { // a[ll]
            if (!re_quit.cap(1).isEmpty()) { // [w]rite
                KateDocManager::self()->saveAll();
            }
            QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
        } else {
            if (!re_quit.cap(1).isEmpty() && view->document()->isModified()) { // [w]rite
                view->document()->documentSave();
            }

            if (KateDocManager::self()->documents() > 1)
                QTimer::singleShot(0, mainWin, SLOT(slotFileClose()));
            else
                QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
         }
    } else if (re_exit.exactMatch(command)) {
        if (!re_exit.cap(1).isEmpty()) { // a[ll]
            KateDocManager::self()->saveAll();
            QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
        } else {
            if (view->document()->isModified()) {
                view->document()->documentSave();
            }

            if (KateDocManager::self()->documents() > 1)
                QTimer::singleShot(0, mainWin, SLOT(slotFileClose()));
            else
                QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
        }
        QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
    }
    else if (re_changeBuffer.exactMatch(command)) {
        if (re_changeBuffer.cap(1) == "n") { // next document
            KateApp::self()->activeMainWindow()->switchToNextDocument();
        }
        else { // previous document
            KateApp::self()->activeMainWindow()->switchToPreviousDocument();
        }
    }
    else if (re_edit.exactMatch(command)) {
        view->document()->documentReload();
    }
    else if (re_new.exactMatch(command)) {
        if (re_new.cap(1) == "v") { // vertical split
            mainWin->viewManager()->slotSplitViewSpaceVert();
        } else {                    // horizontal split
            mainWin->viewManager()->slotSplitViewSpaceHoriz();
        }
        mainWin->viewManager()->slotDocumentNew();
    }
    else if (command == "enew") {
        mainWin->viewManager()->slotDocumentNew();
    }
    return true;
}

bool KateAppCommands::help(KTextEditor::View *view, const QString &cmd, QString &msg)
{
    Q_UNUSED(view);

    if (re_write.exactMatch(cmd)) {
        msg = i18n("
w/wa — write document(s) to disk
"
              "
Usage: <tt>w[a]</tt>
"
              "
Writes the current document(s) to disk. "
              "It can be called in two ways:
"
              " <tt>w</tt> — writes the current document to disk
"
              " <tt>wa</tt> — writes all document to disk.
"
              "
If no file name is associated with the document, "
              "a file dialog will be shown.
");
        return true;
    }
    else if (re_quit.exactMatch(cmd)) {
        msg = i18n("
q/qa/wq/wqa — [write and] quit
"
              "
Usage: <tt>[w]q[a]</tt>
"
              "
Quits the application. If <tt>w</tt> is prepended, it also writes"
              " the document(s) to disk. This command "
              "can be called in several ways:
"
              " <tt>q</tt> — closes the current view.
"
              " <tt>qa</tt> — closes all view, effectively quitting the application.
"
              " <tt>wq</tt> — writes the current document to disk and closes its view.
"
              " <tt>wqa</tt> — writes all documents to disk and quits.
"
              "
In all cases, if the view being closed is the last view, the application quits. "
              "If no file name is associated with the document and it should be written to disk, "
              "a file dialog will be shown.
");
        return true;
    }
    else if (re_exit.exactMatch(cmd)) {
        msg = i18n("
x/xa — write and quit
"
              "
Usage: <tt>x[a]</tt>
"
              "
Saves document(s) and quits (exits). This command "
              "can be called in two ways:
"
              " <tt>x</tt> — closes the current view.
"
              " <tt>xa</tt> — closes all view, effectively quitting the application.
"
              "
In all cases, if the view being closed is the last view, the application quits. "
              "If no file name is associated with the document and it should be written to disk, "
              "a file dialog will be shown.
"
              "
Unlike the 'w' commands, this command only writes the document if it is modified."
              "
");
        return true;
    }
    else if (re_changeBuffer.exactMatch(cmd)) {
        msg = i18n("
bp/bn — switch to previous/next document
"
              "
Usage: <tt>bp/bn</tt>
"
              "
Goes to previous or next document (\"buffer\"). The two"
              " commands are:
"
              " <tt>bp</tt> — goes to the document before the current one in the document"
              " list.
"
              " <tt>bn</tt> — goes to the document after the current one in the document"
              " list.
"
              "
Both commands wrap around, i.e., if you go past the last document you end up"
              " at the first and vice versa.
");
        return true;
    }
    else if (re_new.exactMatch(cmd)) {
        msg = i18n("
[v]new — split view and create new document
"
              "
Usage: <tt>[v]new</tt>
"
              "
Splits the current view and opens a new document in the new view."
              " This command can be called in two ways:
"
              " <tt>new</tt> — splits the view horizontally and opens a new document.
"
              " <tt>vnew</tt> — splits the view vertically and opens a new document.
"
              "
");
        return true;
    }
    else if (re_edit.exactMatch(cmd)) {
        msg = i18n("
e[dit] — reload current document
"
              "
Usage: <tt>e[dit]</tt>
"
              "
Starts editing the current document again. This is useful to re-edit"
             " the current file, when it has been changed by another program.
");
        return true;
    }

    return false;
}
<commit_msg>The previous commit fixed two typos, but unfixed three others.  Please be careful.  This commit re-fixes those three typos.<commit_after>/* This file is part of the KDE project
   Copyright (C) 2009 Erlend Hamberg <ehamberg@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include <klocale.h>
#include "kateapp.h"
#include "kateappcommands.h"
#include "katemainwindow.h"
#include "katedocmanager.h"
#include "kateviewmanager.h"

KateAppCommands::KateAppCommands()
    : KTextEditor::Command()
{
    KTextEditor::Editor *editor = KateDocManager::self()->editor();
    KTextEditor::CommandInterface *iface = qobject_cast<KTextEditor::CommandInterface*>(editor);

    if (iface) {
        iface->registerCommand(this);
    }

    re_write.setPattern("w(a)?");
    re_quit.setPattern("(w)?q?(a)?");
    re_exit.setPattern("x(a)?");
    re_changeBuffer.setPattern("b(n|p)");
    re_edit.setPattern("e(dit)?");
    re_new.setPattern("(v)?new");
}

KateAppCommands::~KateAppCommands()
{
    KTextEditor::Editor *editor = KateDocManager::self()->editor();
    KTextEditor::CommandInterface *iface = qobject_cast<KTextEditor::CommandInterface*>(editor);

    if (iface) {
        iface->unregisterCommand(this);
    }
}

const QStringList& KateAppCommands::cmds()
{
    static QStringList l;

    if (l.empty()) {
        l << "q" << "qa" << "w" << "wq" << "wa" << "wqa" << "x" << "xa"
          << "bn" << "bp" << "new" << "vnew" << "e" << "edit" << "enew";
    }

    return l;
}

bool KateAppCommands::exec(KTextEditor::View *view, const QString &cmd, QString &msg)
{
    QStringList args(cmd.split( QRegExp("\\s+"), QString::SkipEmptyParts)) ;
    QString command( args.takeFirst() );

    KateMainWindow *mainWin = KateApp::self()->activeMainWindow();

    if (re_write.exactMatch(command)) {
        if (!re_write.cap(1).isEmpty()) { // [a]ll
            KateDocManager::self()->saveAll();
            msg = i18n("All documents written to disk");
        } else {
            view->document()->documentSave();
            msg = i18n("Document written to disk");
        }
    }
    else if (re_quit.exactMatch(command)) {
        if (!re_quit.cap(2).isEmpty()) { // a[ll]
            if (!re_quit.cap(1).isEmpty()) { // [w]rite
                KateDocManager::self()->saveAll();
            }
            QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
        } else {
            if (!re_quit.cap(1).isEmpty() && view->document()->isModified()) { // [w]rite
                view->document()->documentSave();
            }

            if (KateDocManager::self()->documents() > 1)
                QTimer::singleShot(0, mainWin, SLOT(slotFileClose()));
            else
                QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
         }
    } else if (re_exit.exactMatch(command)) {
        if (!re_exit.cap(1).isEmpty()) { // a[ll]
            KateDocManager::self()->saveAll();
            QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
        } else {
            if (view->document()->isModified()) {
                view->document()->documentSave();
            }

            if (KateDocManager::self()->documents() > 1)
                QTimer::singleShot(0, mainWin, SLOT(slotFileClose()));
            else
                QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
        }
        QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
    }
    else if (re_changeBuffer.exactMatch(command)) {
        if (re_changeBuffer.cap(1) == "n") { // next document
            KateApp::self()->activeMainWindow()->switchToNextDocument();
        }
        else { // previous document
            KateApp::self()->activeMainWindow()->switchToPreviousDocument();
        }
    }
    else if (re_edit.exactMatch(command)) {
        view->document()->documentReload();
    }
    else if (re_new.exactMatch(command)) {
        if (re_new.cap(1) == "v") { // vertical split
            mainWin->viewManager()->slotSplitViewSpaceVert();
        } else {                    // horizontal split
            mainWin->viewManager()->slotSplitViewSpaceHoriz();
        }
        mainWin->viewManager()->slotDocumentNew();
    }
    else if (command == "enew") {
        mainWin->viewManager()->slotDocumentNew();
    }
    return true;
}

bool KateAppCommands::help(KTextEditor::View *view, const QString &cmd, QString &msg)
{
    Q_UNUSED(view);

    if (re_write.exactMatch(cmd)) {
        msg = i18n("
w/wa — write document(s) to disk
"
              "
Usage: <tt>w[a]</tt>
"
              "
Writes the current document(s) to disk. "
              "It can be called in two ways:
"
              " <tt>w</tt> — writes the current document to disk
"
              " <tt>wa</tt> — writes all documents to disk.
"
              "
If no file name is associated with the document, "
              "a file dialog will be shown.
");
        return true;
    }
    else if (re_quit.exactMatch(cmd)) {
        msg = i18n("
q/qa/wq/wqa — [write and] quit
"
              "
Usage: <tt>[w]q[a]</tt>
"
              "
Quits the application. If <tt>w</tt> is prepended, it also writes"
              " the document(s) to disk. This command "
              "can be called in several ways:
"
              " <tt>q</tt> — closes the current view.
"
              " <tt>qa</tt> — closes all views, effectively quitting the application.
"
              " <tt>wq</tt> — writes the current document to disk and closes its view.
"
              " <tt>wqa</tt> — writes all documents to disk and quits.
"
              "
In all cases, if the view being closed is the last view, the application quits. "
              "If no file name is associated with the document and it should be written to disk, "
              "a file dialog will be shown.
");
        return true;
    }
    else if (re_exit.exactMatch(cmd)) {
        msg = i18n("
x/xa — write and quit
"
              "
Usage: <tt>x[a]</tt>
"
              "
Saves document(s) and quits (exits). This command "
              "can be called in two ways:
"
              " <tt>x</tt> — closes the current view.
"
              " <tt>xa</tt> — closes all views, effectively quitting the application.
"
              "
In all cases, if the view being closed is the last view, the application quits. "
              "If no file name is associated with the document and it should be written to disk, "
              "a file dialog will be shown.
"
              "
Unlike the 'w' commands, this command only writes the document if it is modified."
              "
");
        return true;
    }
    else if (re_changeBuffer.exactMatch(cmd)) {
        msg = i18n("
bp/bn — switch to previous/next document
"
              "
Usage: <tt>bp/bn</tt>
"
              "
Goes to previous or next document (\"buffer\"). The two"
              " commands are:
"
              " <tt>bp</tt> — goes to the document before the current one in the document"
              " list.
"
              " <tt>bn</tt> — goes to the document after the current one in the document"
              " list.
"
              "
Both commands wrap around, i.e., if you go past the last document you end up"
              " at the first and vice versa.
");
        return true;
    }
    else if (re_new.exactMatch(cmd)) {
        msg = i18n("
[v]new — split view and create new document
"
              "
Usage: <tt>[v]new</tt>
"
              "
Splits the current view and opens a new document in the new view."
              " This command can be called in two ways:
"
              " <tt>new</tt> — splits the view horizontally and opens a new document.
"
              " <tt>vnew</tt> — splits the view vertically and opens a new document.
"
              "
");
        return true;
    }
    else if (re_edit.exactMatch(cmd)) {
        msg = i18n("
e[dit] — reload current document
"
              "
Usage: <tt>e[dit]</tt>
"
              "
Starts editing the current document again. This is useful to re-edit"
             " the current file, when it has been changed by another program.
");
        return true;
    }

    return false;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File IncNavierStokesSolver.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Incompressible Navier Stokes solver
//
///////////////////////////////////////////////////////////////////////////////

#include <cstdio>
#include <cstdlib>
#include <cmath>

#include <IncNavierStokesSolver/IncNavierStokes.h>
#include <IncNavierStokesSolver/VelocityCorrectionScheme.h>

using namespace Nektar;

int main(int argc, char *argv[])
{
#ifdef TIMING
    timeval timer1, timer2;
    NekDouble time1, time2;
    NekDouble exeTime;
#endif

    if(argc != 2 && (argc != 4))
    {
        cerr << "\n \t Usage: IncNavierStokes  input.xml [GlobalOptimizationFile ElementalOptimizationFile] \n" << endl;
        exit(1);
    }

    string fileNameString(argv[1]);
    string globoptfile;

    //----------------------------------------------------------------
    // Read the mesh and construct container class
    if(argc == 2)
    {
        globoptfile = NekNullString;
    }
    else
    {
        string eloptfile  (argv[3]);
        NekOptimize::LoadElementalOptimizationParameters(eloptfile);

        globoptfile = argv[2];
    }

    VelocityCorrectionScheme dom(fileNameString,globoptfile);
    dom.Summary(cout);

    switch(dom.GetEquationType())
    {
    case eUnsteadyStokes:
    case eUnsteadyNavierStokes:
        {

            int nsteps = dom.GetSteps();

            // Set initial condition using time t=0
            dom.SetInitialConditions(0.0);

#ifdef TIMING
            dom.AdvanceInTime(1);
            gettimeofday(&timer1, NULL);
#endif
            // Integrate from start time to end time
            dom.AdvanceInTime(nsteps);
#ifdef TIMING
            gettimeofday(&timer2, NULL);
            time1 = timer1.tv_sec*1000000.0+(timer1.tv_usec);
            time2 = timer2.tv_sec*1000000.0+(timer2.tv_usec);
            exeTime = (time2-time1)/1000000.0;
            cout << "Execution Time: " << exeTime << endl;
#endif
            break;
        }
    case eNoEquationType:
    default:
        ASSERTL0(false,"Unknown or undefined equation type");
    }

    // Dump output
    dom.Output();

    // Evaluate L2 Error
    cout << endl;
    for(int i = 0; i < dom.GetNvariables(); ++i)
    {
        cout << "L2 Error (variable " << dom.GetVariable(i) << ") : " << dom.L2Error(i,true) << endl;
    }

}

/**
* $Log $
**/
<commit_msg>Added L inf error to be consistent with other solver and regression tests<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File IncNavierStokesSolver.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Incompressible Navier Stokes solver
//
///////////////////////////////////////////////////////////////////////////////

#include <cstdio>
#include <cstdlib>
#include <cmath>

#include <IncNavierStokesSolver/IncNavierStokes.h>
#include <IncNavierStokesSolver/VelocityCorrectionScheme.h>

using namespace Nektar;

int main(int argc, char *argv[])
{
#ifdef TIMING
    timeval timer1, timer2;
    NekDouble time1, time2;
    NekDouble exeTime;
#endif

    if(argc != 2 && (argc != 4))
    {
        cerr << "\n \t Usage: IncNavierStokes  input.xml [GlobalOptimizationFile ElementalOptimizationFile] \n" << endl;
        exit(1);
    }

    string fileNameString(argv[1]);
    string globoptfile;

    //----------------------------------------------------------------
    // Read the mesh and construct container class
    if(argc == 2)
    {
        globoptfile = NekNullString;
    }
    else
    {
        string eloptfile  (argv[3]);
        NekOptimize::LoadElementalOptimizationParameters(eloptfile);

        globoptfile = argv[2];
    }

    VelocityCorrectionScheme dom(fileNameString,globoptfile);
    dom.Summary(cout);

    switch(dom.GetEquationType())
    {
    case eUnsteadyStokes:
    case eUnsteadyNavierStokes:
        {

            int nsteps = dom.GetSteps();

            // Set initial condition using time t=0
            dom.SetInitialConditions(0.0);

#ifdef TIMING
            dom.AdvanceInTime(1);
            gettimeofday(&timer1, NULL);
#endif
            // Integrate from start time to end time
            dom.AdvanceInTime(nsteps);
#ifdef TIMING
            gettimeofday(&timer2, NULL);
            time1 = timer1.tv_sec*1000000.0+(timer1.tv_usec);
            time2 = timer2.tv_sec*1000000.0+(timer2.tv_usec);
            exeTime = (time2-time1)/1000000.0;
            cout << "Execution Time: " << exeTime << endl;
#endif
            break;
        }
    case eNoEquationType:
    default:
        ASSERTL0(false,"Unknown or undefined equation type");
    }

    // Dump output
    dom.Output();

    // Evaluate L2 Error
    cout << endl;
    for(int i = 0; i < dom.GetNvariables(); ++i)
    {
        cout << "L 2 error (variable " << dom.GetVariable(i) << ") : " << dom.L2Error(i,true) << endl;
		cout << "L inf error (variable " << dom.GetVariable(i) << ") : " << dom.LinfError(i) << endl;
    }

}

/**
* $Log $
**/
<|endoftext|>


<commit_before>/* This file is part of the KDE project
   Copyright (C) 2009 Erlend Hamberg <ehamberg@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include <klocale.h>
#include "kateapp.h"
#include "kateappcommands.h"
#include "katemainwindow.h"
#include "katedocmanager.h"
#include "kateviewmanager.h"

KateAppCommands::KateAppCommands()
    : KTextEditor::Command()
{
    KTextEditor::Editor *editor = KateDocManager::self()->editor();
    KTextEditor::CommandInterface *iface = qobject_cast<KTextEditor::CommandInterface*>(editor);

    if (iface) {
        iface->registerCommand(this);
    }

    re_write.setPattern("w(a)?");
    re_quit.setPattern("(w)?q?(a)?");
    re_exit.setPattern("x(a)?");
    re_changeBuffer.setPattern("b(n|p)");
    re_edit.setPattern("e(dit)?");
    re_new.setPattern("(v)?new");
}

KateAppCommands::~KateAppCommands()
{
    KTextEditor::Editor *editor = KateDocManager::self()->editor();
    KTextEditor::CommandInterface *iface = qobject_cast<KTextEditor::CommandInterface*>(editor);

    if (iface) {
        iface->unregisterCommand(this);
    }
}

const QStringList& KateAppCommands::cmds()
{
    static QStringList l;

    if (l.empty()) {
        l << "q" << "qa" << "w" << "wq" << "wa" << "wqa" << "x" << "xa"
          << "bn" << "bp" << "new" << "vnew" << "e" << "edit" << "enew";
    }

    return l;
}

bool KateAppCommands::exec(KTextEditor::View *view, const QString &cmd, QString &msg)
{
    QStringList args(cmd.split( QRegExp("\\s+"), QString::SkipEmptyParts)) ;
    QString command( args.takeFirst() );

    KateMainWindow *mainWin = KateApp::self()->activeMainWindow();

    if (re_write.exactMatch(command)) {
        if (!re_quit.cap(1).isEmpty()) { // [a]ll
            KateDocManager::self()->saveAll();
            msg = i18n("All documents written to disk");
        } else {
            view->document()->documentSave();
            msg = i18n("Document written to disk");
        }
    }
    else if (re_quit.exactMatch(command)) {
        if (!re_quit.cap(1).isEmpty()) { // [w]rite
            view->document()->documentSave();
        }
        if (!re_quit.cap(2).isEmpty()) { // a[ll]
            KateDocManager::self()->saveAll();
        }
        mainWin->slotFileQuit();
    }
    else if (re_exit.exactMatch(command)) {
        if (!re_exit.cap(1).isEmpty()) { // a[ll]
            KateDocManager::self()->saveAll();
        } else if (view->document()->isModified()) {
            view->document()->documentSave();
        }
        mainWin->slotFileQuit();
    }
    else if (re_changeBuffer.exactMatch(command)) {
        if (re_changeBuffer.cap(1) == "n") { // next document
            KateApp::self()->activeMainWindow()->switchToNextDocument();
        }
        else { // previous document
            KateApp::self()->activeMainWindow()->switchToPreviousDocument();
        }
    }
    else if (re_edit.exactMatch(command)) {
        view->document()->documentReload();
    }
    else if (re_new.exactMatch(command)) {
        if (re_new.cap(1) == "v") { // vertical split
            mainWin->viewManager()->slotSplitViewSpaceVert();
        } else {                    // horizontal split
            mainWin->viewManager()->slotSplitViewSpaceHoriz();
        }
        mainWin->viewManager()->slotDocumentNew();
    }
    else if (command == "enew") {
        mainWin->viewManager()->slotDocumentNew();
    }
    return true;
}

bool KateAppCommands::help(KTextEditor::View *view, const QString &cmd, QString &msg)
{
    Q_UNUSED(view);

    if (re_write.exactMatch(cmd)) {
        msg = "
w/wa — write document(s) to disk
"
              "
Usage: <tt>w[a]</tt>
"
              "
Writes the current document(s) to disk. "
              "It can be called in two ways:
"
              " <tt>w</tt> — writes the current document to disk
"
              " <tt>wa</tt> — writes all document to disk.
"
              "
If no file name is associated with the document, "
              "a file dialog will be shown.
";
        return true;
    }
    else if (re_quit.exactMatch(cmd)) {
        msg = "
q/qa/wq/wqa — [write and] quit
"
              "
Usage: <tt>[w]q[a]</tt>
"
              "
Quits the application. If <tt>w</tt> is prepended, it also writes"
              " the document(s) to disk. This command "
              "can be called in several ways:
"
              " <tt>q</tt> — closes the current view..
"
              " <tt>qa</tt> — closes all view, effectively quitting the application.
"
              " <tt>wq</tt> — writes the current document to disk and closes its view.
"
              " <tt>wqa</tt> — writes all document to disk and quits.
"
              "
In all cases, if the view being closed is the last view, the application quits. "
              "If no file name is associated with the document and it should be written to disk, "
              "a file dialog will be shown.
";
        return true;
    }
    else if (re_exit.exactMatch(cmd)) {
        msg = "
x/xa — write and quit
"
              "
Usage: <tt>x[a]</tt>
"
              "
Saves document(s) and quits (exits). This command "
              "can be called in two ways:
"
              " <tt>x</tt> — closes the current view..
"
              " <tt>xa</tt> — closes all view, effectively quitting the application.
"
              "
In all cases, if the view being closed is the last view, the application quits. "
              "If no file name is associated with the document and it should be written to disk, "
              "a file dialog will be shown.
"
              "
Unlike the 'w' commands, this command only writes the doucment if it is modified."
              "
";
        return true;
    }
    else if (re_changeBuffer.exactMatch(cmd)) {
        msg = "
bp/bn — switch no previous/next document
"
              "
Usage: <tt>bp/bn</tt>
"
              "
Goes to previous or next document (\"buffer\"). The two"
              " commands are:
"
              " <tt>bp</tt> — goes to the document before the current one in the document"
              " list.
"
              " <tt>bn</tt> — goes to the document after the current one in the document"
              " list.
"
              "
Both commands wrap around, i.e., if you go past the last document you and up"
              " at the first and vice versa.
";
        return true;
    }
    else if (re_new.exactMatch(cmd)) {
        msg = "
[v]new — split view and create new document
"
              "
Usage: <tt>[v]new</tt>
"
              "
Splits the current view and opens a new document in the new view."
              " This command can be called in two ways:
"
              " <tt>new</tt> — splits the view horizontally and opens a new document.
"
              " <tt>vnew</tt> — splits the view vertically and opens a new document.
"
              "
";
        return true;
    }
    else if (re_edit.exactMatch(cmd)) {
        msg = "
e[dit] — reload current document
"
              "
Usage: <tt>e[dit]</tt>
"
              "
Starts editing the current document again. This is useful to re-edit"
             " the current file, when it has been changed by another program.
";
        return true;
    }

    return false;
}
<commit_msg>erlend: fix crash on quit.<commit_after>/* This file is part of the KDE project
   Copyright (C) 2009 Erlend Hamberg <ehamberg@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include <klocale.h>
#include "kateapp.h"
#include "kateappcommands.h"
#include "katemainwindow.h"
#include "katedocmanager.h"
#include "kateviewmanager.h"

KateAppCommands::KateAppCommands()
    : KTextEditor::Command()
{
    KTextEditor::Editor *editor = KateDocManager::self()->editor();
    KTextEditor::CommandInterface *iface = qobject_cast<KTextEditor::CommandInterface*>(editor);

    if (iface) {
        iface->registerCommand(this);
    }

    re_write.setPattern("w(a)?");
    re_quit.setPattern("(w)?q?(a)?");
    re_exit.setPattern("x(a)?");
    re_changeBuffer.setPattern("b(n|p)");
    re_edit.setPattern("e(dit)?");
    re_new.setPattern("(v)?new");
}

KateAppCommands::~KateAppCommands()
{
    KTextEditor::Editor *editor = KateDocManager::self()->editor();
    KTextEditor::CommandInterface *iface = qobject_cast<KTextEditor::CommandInterface*>(editor);

    if (iface) {
        iface->unregisterCommand(this);
    }
}

const QStringList& KateAppCommands::cmds()
{
    static QStringList l;

    if (l.empty()) {
        l << "q" << "qa" << "w" << "wq" << "wa" << "wqa" << "x" << "xa"
          << "bn" << "bp" << "new" << "vnew" << "e" << "edit" << "enew";
    }

    return l;
}

bool KateAppCommands::exec(KTextEditor::View *view, const QString &cmd, QString &msg)
{
    QStringList args(cmd.split( QRegExp("\\s+"), QString::SkipEmptyParts)) ;
    QString command( args.takeFirst() );

    KateMainWindow *mainWin = KateApp::self()->activeMainWindow();

    if (re_write.exactMatch(command)) {
        if (!re_quit.cap(1).isEmpty()) { // [a]ll
            KateDocManager::self()->saveAll();
            msg = i18n("All documents written to disk");
        } else {
            view->document()->documentSave();
            msg = i18n("Document written to disk");
        }
    }
    else if (re_quit.exactMatch(command)) {
        if (!re_quit.cap(1).isEmpty()) { // [w]rite
            view->document()->documentSave();
        }
        if (!re_quit.cap(2).isEmpty()) { // a[ll]
            KateDocManager::self()->saveAll();
        }
        QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
    }
    else if (re_exit.exactMatch(command)) {
        if (!re_exit.cap(1).isEmpty()) { // a[ll]
            KateDocManager::self()->saveAll();
        } else if (view->document()->isModified()) {
            view->document()->documentSave();
        }
        QTimer::singleShot(0, mainWin, SLOT(slotFileQuit()));
    }
    else if (re_changeBuffer.exactMatch(command)) {
        if (re_changeBuffer.cap(1) == "n") { // next document
            KateApp::self()->activeMainWindow()->switchToNextDocument();
        }
        else { // previous document
            KateApp::self()->activeMainWindow()->switchToPreviousDocument();
        }
    }
    else if (re_edit.exactMatch(command)) {
        view->document()->documentReload();
    }
    else if (re_new.exactMatch(command)) {
        if (re_new.cap(1) == "v") { // vertical split
            mainWin->viewManager()->slotSplitViewSpaceVert();
        } else {                    // horizontal split
            mainWin->viewManager()->slotSplitViewSpaceHoriz();
        }
        mainWin->viewManager()->slotDocumentNew();
    }
    else if (command == "enew") {
        mainWin->viewManager()->slotDocumentNew();
    }
    return true;
}

bool KateAppCommands::help(KTextEditor::View *view, const QString &cmd, QString &msg)
{
    Q_UNUSED(view);

    if (re_write.exactMatch(cmd)) {
        msg = "
w/wa — write document(s) to disk
"
              "
Usage: <tt>w[a]</tt>
"
              "
Writes the current document(s) to disk. "
              "It can be called in two ways:
"
              " <tt>w</tt> — writes the current document to disk
"
              " <tt>wa</tt> — writes all document to disk.
"
              "
If no file name is associated with the document, "
              "a file dialog will be shown.
";
        return true;
    }
    else if (re_quit.exactMatch(cmd)) {
        msg = "
q/qa/wq/wqa — [write and] quit
"
              "
Usage: <tt>[w]q[a]</tt>
"
              "
Quits the application. If <tt>w</tt> is prepended, it also writes"
              " the document(s) to disk. This command "
              "can be called in several ways:
"
              " <tt>q</tt> — closes the current view..
"
              " <tt>qa</tt> — closes all view, effectively quitting the application.
"
              " <tt>wq</tt> — writes the current document to disk and closes its view.
"
              " <tt>wqa</tt> — writes all document to disk and quits.
"
              "
In all cases, if the view being closed is the last view, the application quits. "
              "If no file name is associated with the document and it should be written to disk, "
              "a file dialog will be shown.
";
        return true;
    }
    else if (re_exit.exactMatch(cmd)) {
        msg = "
x/xa — write and quit
"
              "
Usage: <tt>x[a]</tt>
"
              "
Saves document(s) and quits (exits). This command "
              "can be called in two ways:
"
              " <tt>x</tt> — closes the current view..
"
              " <tt>xa</tt> — closes all view, effectively quitting the application.
"
              "
In all cases, if the view being closed is the last view, the application quits. "
              "If no file name is associated with the document and it should be written to disk, "
              "a file dialog will be shown.
"
              "
Unlike the 'w' commands, this command only writes the doucment if it is modified."
              "
";
        return true;
    }
    else if (re_changeBuffer.exactMatch(cmd)) {
        msg = "
bp/bn — switch no previous/next document
"
              "
Usage: <tt>bp/bn</tt>
"
              "
Goes to previous or next document (\"buffer\"). The two"
              " commands are:
"
              " <tt>bp</tt> — goes to the document before the current one in the document"
              " list.
"
              " <tt>bn</tt> — goes to the document after the current one in the document"
              " list.
"
              "
Both commands wrap around, i.e., if you go past the last document you and up"
              " at the first and vice versa.
";
        return true;
    }
    else if (re_new.exactMatch(cmd)) {
        msg = "
[v]new — split view and create new document
"
              "
Usage: <tt>[v]new</tt>
"
              "
Splits the current view and opens a new document in the new view."
              " This command can be called in two ways:
"
              " <tt>new</tt> — splits the view horizontally and opens a new document.
"
              " <tt>vnew</tt> — splits the view vertically and opens a new document.
"
              "
";
        return true;
    }
    else if (re_edit.exactMatch(cmd)) {
        msg = "
e[dit] — reload current document
"
              "
Usage: <tt>e[dit]</tt>
"
              "
Starts editing the current document again. This is useful to re-edit"
             " the current file, when it has been changed by another program.
";
        return true;
    }

    return false;
}
<|endoftext|>