<commit_before>/*
The MIT License (MIT)

Copyright (c) 2014 Conrado Miranda

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.
*/

// Each batch has a header with the following format:
// 1) Number of entries;
// 2) For each entry, the following values:
// 2.1) The hash of the task which provided the result;
// 2.2) The position of the result inside the file;
// 2.3) The size of the result.
//
// Each entry is of type size_t and the header isn't taken into account for the
// maximum file size or entry position.

#include "object_archive.hpp"

#include <algorithm>
#include <boost/filesystem.hpp>

ObjectArchive::ObjectArchive(std::string const& filename,
    size_t max_buffer_size):
  must_rebuild_file_(false),
  max_buffer_size_(max_buffer_size),
  buffer_size_(0) {
    init(filename);

    if (max_buffer_size_ < 1)
      max_buffer_size_ = 1;
}

ObjectArchive::ObjectArchive(std::string const& filename,
    std::string const& max_buffer_size):
  ObjectArchive(filename, 0) {
    size_t length = max_buffer_size.size();
    double buffer_size = atof(max_buffer_size.c_str());

    bool changed = false;
    for (size_t i = 0; i< length && !changed; i++) {
      switch (max_buffer_size[i]) {
        case 'k':
        case 'K':
          buffer_size *= 1e3;
          changed = true;
          break;
        case 'm':
        case 'M':
          buffer_size *= 1e6;
          changed = true;
          break;
        case 'g':
        case 'G':
          buffer_size *= 1e9;
          changed = true;
          break;
      }
    }

    max_buffer_size_ = buffer_size;

    if (max_buffer_size_ < 1)
      max_buffer_size_ = 1;
}

ObjectArchive::~ObjectArchive() {
  flush();
}

void ObjectArchive::init(std::string const& filename) {
  flush();

  filename_ = filename;

  buffer_size_ = 0;
  objects_.clear();
  LRU_.clear();

  stream_.open(filename, std::ios_base::in | std::ios_base::out |
                         std::ios_base::binary);
  stream_.seekg(0, std::ios_base::end);

  // If the file seems ok and has entries, use it. Otherwise, overwrite.
  if (stream_.good() && stream_.tellg() > 0) {
    stream_.seekg(0);

    size_t n_entries;
    stream_.read((char*)&n_entries, sizeof(size_t));

    for (size_t i = 0; i < n_entries; i++) {
      size_t id, pos, size;
      stream_.read((char*)&id, sizeof(size_t));
      stream_.read((char*)&pos, sizeof(size_t));
      stream_.read((char*)&size, sizeof(size_t));

      ObjectEntry entry;
      entry.index_in_file = pos;
      entry.size = size;
      entry.modified = false;
      objects_[id] = entry;
    }

    header_offset_ = stream_.tellg();
  }
  else {
    stream_.open(filename, std::ios_base::in | std::ios_base::out |
        std::ios_base::binary | std::ios_base::trunc);
    header_offset_ = 0;
  }
}

void ObjectArchive::remove(size_t id) {
  auto it = objects_.find(id);
  if (it == objects_.end())
    return;

  ObjectEntry& entry = it->second;
  if (entry.data.size())
    buffer_size_ -= entry.size;
  objects_.erase(id);
  LRU_.remove(id);
  must_rebuild_file_ = true;
}

size_t ObjectArchive::insert_raw(size_t id, std::string&& data,
    bool keep_in_buffer) {
  size_t size = data.size();
  if (size > max_buffer_size_)
    keep_in_buffer = false;

  remove(id);

  if (size + buffer_size_ > max_buffer_size_ && keep_in_buffer)
    unload(max_buffer_size_ - size);

  buffer_size_ += size;

  ObjectEntry& entry = objects_[id];
  entry.data.swap(data);
  entry.size = size;
  entry.modified = true;
  touch_LRU(id);
  must_rebuild_file_ = true;

  if (!keep_in_buffer)
    write_back(id);

  return size;
}

size_t ObjectArchive::load_raw(size_t id, std::string& data,
    bool keep_in_buffer) {
  auto it = objects_.find(id);
  if (it == objects_.end())
    return 0;

  ObjectEntry& entry = it->second;

  size_t size = entry.size;
  if (size > max_buffer_size_)
    keep_in_buffer = false;

  // If the result isn't in the buffer, we must read it.
  if (entry.data.size() == 0) {
    // Only check for size if we have to load.
    if (size + buffer_size_ > max_buffer_size_)
      unload(max_buffer_size_ - size);

    stream_.seekg(entry.index_in_file + header_offset_);
    std::string& buf = entry.data;
    buf.resize(size);
    stream_.read(&buf[0], size);
    buffer_size_ += size;

    entry.modified = false;
    touch_LRU(id);
  }

  if (!keep_in_buffer) {
    data.swap(entry.data);
    entry.data.clear();
  }
  else
    data = entry.data;

  return size;
}

void ObjectArchive::unload(size_t desired_size) {
  while (buffer_size_ > desired_size)
    write_back(LRU_.back());
}

std::list<size_t> ObjectArchive::available_objects() const {
  std::list<size_t> list;
  for (auto& it : objects_)
    list.push_front(it.first);

  return list;
}

void ObjectArchive::flush() {
  unload();

  if (!must_rebuild_file_)
    return;

  must_rebuild_file_ = false;

  boost::filesystem::path temp_filename;
  temp_filename = boost::filesystem::temp_directory_path();
  temp_filename += '/';
  temp_filename += boost::filesystem::unique_path();
  std::fstream temp_stream(temp_filename.string(),
      std::ios_base::in | std::ios_base::out |
      std::ios_base::binary | std::ios_base::trunc);

  size_t n_entries = objects_.size();
  temp_stream.write((char*)&n_entries, sizeof(size_t));

  size_t pos = 0;
  for (auto& it : objects_) {
    size_t id, size;
    ObjectEntry& entry = it.second;
    id = it.first;
    size = entry.size;
    temp_stream.write((char*)&id, sizeof(size_t));
    temp_stream.write((char*)&pos, sizeof(size_t));
    temp_stream.write((char*)&size, sizeof(size_t));
    pos += size;
  }

  char* temp_buffer = new char[max_buffer_size_];

  for (auto& it : objects_) {
    ObjectEntry& entry = it.second;
    stream_.seekg(entry.index_in_file + header_offset_);
    size_t size = entry.size;

    // Only uses the allowed buffer memory.
    for (;
         size > max_buffer_size_;
         size -= max_buffer_size_) {
      stream_.read(temp_buffer, max_buffer_size_);
      temp_stream.write(temp_buffer, max_buffer_size_);
    }
    stream_.read(temp_buffer, size);
    temp_stream.write(temp_buffer, size);
  }

  delete[] temp_buffer;

  stream_.close();
  temp_stream.close();

  boost::filesystem::remove(filename_);
  boost::filesystem::rename(temp_filename, filename_);

  init(filename_);
}

bool ObjectArchive::write_back(size_t id) {
  auto it = objects_.find(id);
  if (it == objects_.end())
    return false;

  ObjectEntry& entry = it->second;

  if (entry.modified) {
    entry.index_in_file = stream_.tellp();
    entry.index_in_file -= header_offset_;
    stream_.write((char*)&entry.data[0], entry.size);
    entry.modified = false;
  }

  entry.data.clear();
  buffer_size_ -= entry.size;
  LRU_.remove(id);
  must_rebuild_file_ = true;

  return true;
}

void ObjectArchive::touch_LRU(size_t id) {
  LRU_.remove(id);
  LRU_.push_front(id);
}
<commit_msg>Removed unnecessary file rebuilding in write back.<commit_after>/*
The MIT License (MIT)

Copyright (c) 2014 Conrado Miranda

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.
*/

// Each batch has a header with the following format:
// 1) Number of entries;
// 2) For each entry, the following values:
// 2.1) The hash of the task which provided the result;
// 2.2) The position of the result inside the file;
// 2.3) The size of the result.
//
// Each entry is of type size_t and the header isn't taken into account for the
// maximum file size or entry position.

#include "object_archive.hpp"

#include <algorithm>
#include <boost/filesystem.hpp>

ObjectArchive::ObjectArchive(std::string const& filename,
    size_t max_buffer_size):
  must_rebuild_file_(false),
  max_buffer_size_(max_buffer_size),
  buffer_size_(0) {
    init(filename);

    if (max_buffer_size_ < 1)
      max_buffer_size_ = 1;
}

ObjectArchive::ObjectArchive(std::string const& filename,
    std::string const& max_buffer_size):
  ObjectArchive(filename, 0) {
    size_t length = max_buffer_size.size();
    double buffer_size = atof(max_buffer_size.c_str());

    bool changed = false;
    for (size_t i = 0; i< length && !changed; i++) {
      switch (max_buffer_size[i]) {
        case 'k':
        case 'K':
          buffer_size *= 1e3;
          changed = true;
          break;
        case 'm':
        case 'M':
          buffer_size *= 1e6;
          changed = true;
          break;
        case 'g':
        case 'G':
          buffer_size *= 1e9;
          changed = true;
          break;
      }
    }

    max_buffer_size_ = buffer_size;

    if (max_buffer_size_ < 1)
      max_buffer_size_ = 1;
}

ObjectArchive::~ObjectArchive() {
  flush();
}

void ObjectArchive::init(std::string const& filename) {
  flush();

  filename_ = filename;

  buffer_size_ = 0;
  objects_.clear();
  LRU_.clear();

  stream_.open(filename, std::ios_base::in | std::ios_base::out |
                         std::ios_base::binary);
  stream_.seekg(0, std::ios_base::end);

  // If the file seems ok and has entries, use it. Otherwise, overwrite.
  if (stream_.good() && stream_.tellg() > 0) {
    stream_.seekg(0);

    size_t n_entries;
    stream_.read((char*)&n_entries, sizeof(size_t));

    for (size_t i = 0; i < n_entries; i++) {
      size_t id, pos, size;
      stream_.read((char*)&id, sizeof(size_t));
      stream_.read((char*)&pos, sizeof(size_t));
      stream_.read((char*)&size, sizeof(size_t));

      ObjectEntry entry;
      entry.index_in_file = pos;
      entry.size = size;
      entry.modified = false;
      objects_[id] = entry;
    }

    header_offset_ = stream_.tellg();
  }
  else {
    stream_.open(filename, std::ios_base::in | std::ios_base::out |
        std::ios_base::binary | std::ios_base::trunc);
    header_offset_ = 0;
  }
}

void ObjectArchive::remove(size_t id) {
  auto it = objects_.find(id);
  if (it == objects_.end())
    return;

  ObjectEntry& entry = it->second;
  if (entry.data.size())
    buffer_size_ -= entry.size;
  objects_.erase(id);
  LRU_.remove(id);
  must_rebuild_file_ = true;
}

size_t ObjectArchive::insert_raw(size_t id, std::string&& data,
    bool keep_in_buffer) {
  size_t size = data.size();
  if (size > max_buffer_size_)
    keep_in_buffer = false;

  remove(id);

  if (size + buffer_size_ > max_buffer_size_ && keep_in_buffer)
    unload(max_buffer_size_ - size);

  buffer_size_ += size;

  ObjectEntry& entry = objects_[id];
  entry.data.swap(data);
  entry.size = size;
  entry.modified = true;
  touch_LRU(id);
  must_rebuild_file_ = true;

  if (!keep_in_buffer)
    write_back(id);

  return size;
}

size_t ObjectArchive::load_raw(size_t id, std::string& data,
    bool keep_in_buffer) {
  auto it = objects_.find(id);
  if (it == objects_.end())
    return 0;

  ObjectEntry& entry = it->second;

  size_t size = entry.size;
  if (size > max_buffer_size_)
    keep_in_buffer = false;

  // If the result isn't in the buffer, we must read it.
  if (entry.data.size() == 0) {
    // Only check for size if we have to load.
    if (size + buffer_size_ > max_buffer_size_)
      unload(max_buffer_size_ - size);

    stream_.seekg(entry.index_in_file + header_offset_);
    std::string& buf = entry.data;
    buf.resize(size);
    stream_.read(&buf[0], size);
    buffer_size_ += size;

    entry.modified = false;
    touch_LRU(id);
  }

  if (!keep_in_buffer) {
    data.swap(entry.data);
    entry.data.clear();
  }
  else
    data = entry.data;

  return size;
}

void ObjectArchive::unload(size_t desired_size) {
  while (buffer_size_ > desired_size)
    write_back(LRU_.back());
}

std::list<size_t> ObjectArchive::available_objects() const {
  std::list<size_t> list;
  for (auto& it : objects_)
    list.push_front(it.first);

  return list;
}

void ObjectArchive::flush() {
  unload();

  if (!must_rebuild_file_)
    return;

  must_rebuild_file_ = false;

  boost::filesystem::path temp_filename;
  temp_filename = boost::filesystem::temp_directory_path();
  temp_filename += '/';
  temp_filename += boost::filesystem::unique_path();
  std::fstream temp_stream(temp_filename.string(),
      std::ios_base::in | std::ios_base::out |
      std::ios_base::binary | std::ios_base::trunc);

  size_t n_entries = objects_.size();
  temp_stream.write((char*)&n_entries, sizeof(size_t));

  size_t pos = 0;
  for (auto& it : objects_) {
    size_t id, size;
    ObjectEntry& entry = it.second;
    id = it.first;
    size = entry.size;
    temp_stream.write((char*)&id, sizeof(size_t));
    temp_stream.write((char*)&pos, sizeof(size_t));
    temp_stream.write((char*)&size, sizeof(size_t));
    pos += size;
  }

  char* temp_buffer = new char[max_buffer_size_];

  for (auto& it : objects_) {
    ObjectEntry& entry = it.second;
    stream_.seekg(entry.index_in_file + header_offset_);
    size_t size = entry.size;

    // Only uses the allowed buffer memory.
    for (;
         size > max_buffer_size_;
         size -= max_buffer_size_) {
      stream_.read(temp_buffer, max_buffer_size_);
      temp_stream.write(temp_buffer, max_buffer_size_);
    }
    stream_.read(temp_buffer, size);
    temp_stream.write(temp_buffer, size);
  }

  delete[] temp_buffer;

  stream_.close();
  temp_stream.close();

  boost::filesystem::remove(filename_);
  boost::filesystem::rename(temp_filename, filename_);

  init(filename_);
}

bool ObjectArchive::write_back(size_t id) {
  auto it = objects_.find(id);
  if (it == objects_.end())
    return false;

  ObjectEntry& entry = it->second;

  if (entry.modified) {
    entry.index_in_file = stream_.tellp();
    entry.index_in_file -= header_offset_;
    stream_.write((char*)&entry.data[0], entry.size);
    entry.modified = false;
    must_rebuild_file_ = true;
  }

  entry.data.clear();
  buffer_size_ -= entry.size;
  LRU_.remove(id);

  return true;
}

void ObjectArchive::touch_LRU(size_t id) {
  LRU_.remove(id);
  LRU_.push_front(id);
}
<|endoftext|>


<commit_before>/**
 *  ofxSoundObject.cpp
 *
 *  Created by Marek Bereza on 10/08/2013.
 */

#include "ofxSoundObject.h"

//----------------------------------------------------
// ofxSoundObject

ofxSoundObject::ofxSoundObject() {
	inputObject = NULL;
    outputObjectRef = NULL;
}

ofxSoundObject &ofxSoundObject::connectTo(ofxSoundObject &soundObject) {
    if (outputObjectRef != NULL) {
        disconnect();
    }
    outputObjectRef = &soundObject;
	soundObject.setInput(this);

	// if we find an infinite loop, we want to disconnect and provide an error
	if(!checkForInfiniteLoops()) {
		ofLogError("ofxSoundObject") << "There's an infinite loop in your chain of ofxSoundObjects";
		disconnect();
	}
	return soundObject;
}

void ofxSoundObject::disconnectInput(ofxSoundObject * input){
    if (inputObject != NULL) {
    inputObject = NULL;
    }
}

void ofxSoundObject::disconnect(){
    outputObjectRef->disconnectInput(this);
    outputObjectRef =NULL;
}

void ofxSoundObject::setInput(ofxSoundObject *obj) {
	inputObject = obj;
}

ofxSoundObject *ofxSoundObject::getInputObject() {
	return inputObject;
}

bool ofxSoundObject::checkForInfiniteLoops() {
	ofxSoundObject *prev = inputObject;

	// move up the dsp chain until we find ourselves or the beginning of the chain (input==NULL)
	while(prev!=this && prev!=NULL) {
		prev = prev->getInputObject();
	}

	// if we found ourselves, return false (to indicate there's an infinite loop)
	return (prev==NULL);
}

// this pulls the audio through from earlier links in the chain
void ofxSoundObject::audioOut(ofSoundBuffer &output) {
	if(inputObject!=NULL) {
		if(workingBuffer.size()!=output.size()) {
            ofLogVerbose("ofxSoundObject") << "working buffer size != output buffer size.";
            workingBuffer.resize(output.size());
            workingBuffer.setNumChannels(output.getNumChannels());
            workingBuffer.setSampleRate(output.getSampleRate());
		}

		inputObject->audioOut(workingBuffer);
	}
	this->process(workingBuffer, output);
}

//----------------------------------------------------
// ofSoundInput

ofxSoundInput::ofxSoundInput() {

}

// copy audio in to internal buffer
void ofxSoundInput::audioIn(ofSoundBuffer &input) {
	if(inputBuffer.size()!=input.size()) {
        ofLogVerbose("ofSoundinput::audioIn") << "input buffer size != output buffer size.";
		inputBuffer.resize(input.size());
        inputBuffer.setNumChannels(inputBuffer.getNumChannels());
        inputBuffer.setSampleRate(inputBuffer.getSampleRate());
	}
	input.copyTo(inputBuffer);
}

void ofxSoundInput::audioOut(ofSoundBuffer &output) {
    if(output.getNumFrames()==inputBuffer.getNumFrames()){
        ofLogVerbose("ofSoundinput::audioOut") << "input buffer size != output buffer size.";
        inputBuffer.resize(output.size());
        inputBuffer.setNumChannels(output.getNumChannels());
        inputBuffer.setSampleRate(output.getSampleRate());
	}
	inputBuffer.copyTo(output);
}

<commit_msg>Fixed wrong audio buffer passing values in ofxSoundInput<commit_after>/**
 *  ofxSoundObject.cpp
 *
 *  Created by Marek Bereza on 10/08/2013.
 */

#include "ofxSoundObject.h"

//----------------------------------------------------
// ofxSoundObject

ofxSoundObject::ofxSoundObject() {
	inputObject = NULL;
    outputObjectRef = NULL;
}

ofxSoundObject &ofxSoundObject::connectTo(ofxSoundObject &soundObject) {
    if (outputObjectRef != NULL) {
        disconnect();
    }
    outputObjectRef = &soundObject;
	soundObject.setInput(this);

	// if we find an infinite loop, we want to disconnect and provide an error
	if(!checkForInfiniteLoops()) {
		ofLogError("ofxSoundObject") << "There's an infinite loop in your chain of ofxSoundObjects";
		disconnect();
	}
	return soundObject;
}

void ofxSoundObject::disconnectInput(ofxSoundObject * input){
    if (inputObject != NULL) {
    inputObject = NULL;
    }
}

void ofxSoundObject::disconnect(){
    outputObjectRef->disconnectInput(this);
    outputObjectRef =NULL;
}

void ofxSoundObject::setInput(ofxSoundObject *obj) {
	inputObject = obj;
}

ofxSoundObject *ofxSoundObject::getInputObject() {
	return inputObject;
}

bool ofxSoundObject::checkForInfiniteLoops() {
	ofxSoundObject *prev = inputObject;

	// move up the dsp chain until we find ourselves or the beginning of the chain (input==NULL)
	while(prev!=this && prev!=NULL) {
		prev = prev->getInputObject();
	}

	// if we found ourselves, return false (to indicate there's an infinite loop)
	return (prev==NULL);
}

// this pulls the audio through from earlier links in the chain
void ofxSoundObject::audioOut(ofSoundBuffer &output) {
	if(inputObject!=NULL) {
		if(workingBuffer.size()!=output.size()) {
            ofLogVerbose("ofxSoundObject") << "working buffer size != output buffer size.";
            workingBuffer.resize(output.size());
            workingBuffer.setNumChannels(output.getNumChannels());
            workingBuffer.setSampleRate(output.getSampleRate());
		}

		inputObject->audioOut(workingBuffer);
	}
	this->process(workingBuffer, output);
}

//----------------------------------------------------
// ofSoundInput

ofxSoundInput::ofxSoundInput() {

}

// copy audio in to internal buffer
void ofxSoundInput::audioIn(ofSoundBuffer &input) {
	if(inputBuffer.size()!=input.size()) {
        ofLogVerbose("ofSoundinput::audioIn") << "input buffer size != output buffer size.";
		inputBuffer.resize(input.size());
        inputBuffer.setNumChannels(input.getNumChannels());
        inputBuffer.setSampleRate(input.getSampleRate());
	}
	input.copyTo(inputBuffer);
}

void ofxSoundInput::audioOut(ofSoundBuffer &output) {
    if(output.getNumFrames()==inputBuffer.getNumFrames()){
        ofLogVerbose("ofSoundinput::audioOut") << "input buffer size != output buffer size.";
        inputBuffer.resize(output.size());
        inputBuffer.setNumChannels(output.getNumChannels());
        inputBuffer.setSampleRate(output.getSampleRate());
	}
	inputBuffer.copyTo(output);
}

<|endoftext|>


<commit_before>/*******************************************************
 SPIDAR-mouse-server for Linux, FreeBSD and Mac OS X
 Copyright (c) 2013 Naoto Hieda
 March 3, 2013
 Licensed under MIT license.
 https://github.com/micuat/SPIDAR-mouse-UNIX

 ofxSpidarMouse.cpp

 ********************************************************/

#include "ofxSpidarMouse.h"
#include "hidapi.h"

ofxSpidarMouse::ofxSpidarMouse()
{
	isInitialized = false;
	isOpened = false;
}

int ofxSpidarMouse::init()
{
	isInitialized = false;

	int res;
	unsigned char buf[256];
#define MAX_STR 255
	wchar_t wstr[MAX_STR];

	devs = hid_enumerate(0x0, 0x0);
	cur_dev = devs;
	while (cur_dev) {
		printf("Device Found\n  type: %04hx %04hx\n  path: %s\n  serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
		printf("\n");
		printf("  Manufacturer: %ls\n", cur_dev->manufacturer_string);
		printf("  Product:      %ls\n", cur_dev->product_string);
		printf("  Release:      %hx\n", cur_dev->release_number);
		printf("  Interface:    %d\n",  cur_dev->interface_number);
		printf("\n");
		cur_dev = cur_dev->next;
	}
	hid_free_enumeration(devs);

	// Set up the command buffer.
	memset(buf,0x00,sizeof(buf));
	buf[0] = 0x01;
	buf[1] = 0x81;

	// Open the device using the VID, PID,
	// and optionally the Serial number.
	////handle = hid_open(0x4d8, 0x3f, L"12345");
	handle = hid_open(0x4d8, 0x3f, NULL);
	if (!handle) {
		printf("unable to open device\n");
 		return 1;
	}

	// Read the Manufacturer String
	wstr[0] = 0x0000;
	res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read manufacturer string\n");
	printf("Manufacturer String: %ls\n", wstr);

	// Read the Product String
	wstr[0] = 0x0000;
	res = hid_get_product_string(handle, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read product string\n");
	printf("Product String: %ls\n", wstr);

	// Read the Serial Number String
	wstr[0] = 0x0000;
	res = hid_get_serial_number_string(handle, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read serial number string\n");
	printf("Serial Number String: (%d) %ls", wstr[0], wstr);
	printf("\n");

	// Read Indexed String 1
	wstr[0] = 0x0000;
	res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read indexed string 1\n");
	printf("Indexed String 1: %ls\n", wstr);

	// Set the hid_read() function to be non-blocking.
	hid_set_nonblocking(handle, 1);

	// Try to read from the device. There shoud be no
	// data here, but execution should not block.
	res = hid_read(handle, buf, 17);

	// Send a Feature Report to the device
	buf[0] = 0x2;
	buf[1] = 0xa0;
	buf[2] = 0x0a;
	buf[3] = 0x00;
	buf[4] = 0x00;
	res = hid_send_feature_report(handle, buf, 17);
	if (res < 0) {
		printf("Unable to send a feature report.\n");
	}

	memset(buf,0,sizeof(buf));

	// Read a Feature Report from the device
	buf[0] = 0x2;
	res = hid_get_feature_report(handle, buf, sizeof(buf));
	if (res < 0) {
		printf("Unable to get a feature report.\n");
		printf("%ls\n", hid_error(handle));
	}
	else {
		// Print out the returned buffer.
		printf("Feature Report\n   ");
		for (int i = 0; i < res; i++)
			printf("%02hhx ", buf[i]);
		printf("\n");
	}

	isInitialized = true;
	return 0;
}

ofxSpidarMouse::~ofxSpidarMouse()
{
	if( isOpened ) {
		close();
	}

	if( isInitialized ) {
		hid_close(handle);

		/* Free static HIDAPI objects. */
		hid_exit();
	}
}

int ofxSpidarMouse::open()
{
	isOpened = false;

	if( !isInitialized ) {
		return 1;
	}

	int res;
	unsigned char buf[256];
	float conf_data[4];

	// Initialize parameters

	interG_X=0.0;
	interG_Y=0.0;
	SetForce_Mag=0.0;
	SetForce_Dirunit_X=0.0;
	SetForce_Dirunit_Y=0.0;
	Max_Force=1.5;
	defaultDuration = 4; // 4ms
	duration = 0;

	forceStack.clear();
	//////////////// Start SPIDAR-mouse

	memset(buf,0,sizeof(buf));

	buf[0] = 0x00;
	buf[1] = 0x82;
	res = hid_write(handle, buf, 65);
	if (res < 0) {
		printf("Unable to write()\n");
		printf("Error: %ls\n", hid_error(handle));
		return 1;
	}

	// Read requested state. hid_read() has been set to be
	// non-blocking by the call to hid_set_nonblocking() above.
	// This loop demonstrates the non-blocking nature of hid_read().
	res = 0;
	while (res == 0) {
		res = hid_read(handle, buf, sizeof(buf));
		if (res == 0)
			printf("waiting...\n");
		if (res < 0)
			printf("Unable to read()\n");
#ifdef WIN32
		Sleep(500);
#else
		usleep(500*1000);
#endif
	}

	printf("Data read:\n   ");
	// Print out the returned buffer.
	for (int i = 0; i < res; i++)
		printf("%02hhx ", buf[i]);
	printf("\n");

	memset(buf,0,sizeof(buf));

	conf_data[0] = 0.3;
	conf_data[1] = 1.5;
	conf_data[2] = 47.9867;
	conf_data[3] = 13.1215;
	MinForce_Bytes = (unsigned char *)&conf_data[0];
	MaxForce_Bytes = (unsigned char *)&conf_data[1];
	Fun_a_Bytes = (unsigned char *)&conf_data[2];
	Fun_b_Bytes = (unsigned char *)&conf_data[3];

	buf[0] = 0;
	buf[1] = 0x80;
	buf[2] = MinForce_Bytes[0];
	buf[3] = MinForce_Bytes[1];
	buf[4] = MinForce_Bytes[2];
	buf[5] = MinForce_Bytes[3];

	buf[6] = MaxForce_Bytes[0];
	buf[7] = MaxForce_Bytes[1];
	buf[8] = MaxForce_Bytes[2];
	buf[9] = MaxForce_Bytes[3];

	buf[10] = Fun_a_Bytes[0];
	buf[11] = Fun_a_Bytes[1];
	buf[12] = Fun_a_Bytes[2];
	buf[13] = Fun_a_Bytes[3];

	buf[14] = Fun_b_Bytes[0];
	buf[15] = Fun_b_Bytes[1];
	buf[16] = Fun_b_Bytes[2];
	buf[17] = Fun_b_Bytes[3];
	res = hid_write(handle, buf, 65);
	if (res < 0) {
		printf("Unable to start SPIDAR-mouse: %ls\n", hid_error(handle));
		return 1;
	}

	setForce(0.0, 0.0);

	isOpened = true;
	return 0;
}

int ofxSpidarMouse::close()
{
	if( !isOpened ) {
		return 1;
	}

	int res;
	unsigned char buf[256];

	buf[0] = 0;
	buf[1] = 0x99;
	res = hid_write(handle, buf, 65);
	if (res < 0) {
		printf("Unable to close SPIDAR-mouse: %d %ls\n", res, hid_error(handle));
	}

	return 0;
}

int ofxSpidarMouse::update()
{
	unsigned long curTime = ofGetSystemTime();

	if( duration != 0 && (curTime - startTime) > duration ) {
		setForce(0.0, 0.0);
		duration = 0;
	}

	forceStack.push_back(ofVec2f(Force_XScale, Force_YScale));
	if( forceStack.size() > 30 ) {
		forceStack.erase(forceStack.begin());
	}

	return 0;
}

int ofxSpidarMouse::setForce(float fx, float fy)
{
	duration = 0; // infinite

	return sForce(fx, fy);
}

int ofxSpidarMouse::setForce(float fx, float fy, int d)
{
	startTime = ofGetSystemTime();

	if( d < defaultDuration ) {
		duration = defaultDuration;
	} else {
		duration = d;
	}

	return sForce(fx, fy);
}

int ofxSpidarMouse::sForce(float fx, float fy)
{
	if( fabsf(fx) > 1.0 ) {
		Force_XScale = fx / fabsf(fx);
	} else {
		Force_XScale = fx;
	}

	if( fabsf(fy) > 1.0 ) {
		Force_YScale = fy / fabsf(fy);
	} else {
		Force_YScale = fy;
	}

	if( !isOpened ) {
		return 1;
	}

	Force_X = Force_XScale * Max_Force;
	Force_Y = Force_YScale * Max_Force;
	SetForce_Mag = sqrt(Force_X * Force_X + Force_Y * Force_Y);
	if ( SetForce_Mag > 0.0 ) {
		SetForce_Dirunit_X = Force_X / SetForce_Mag;
		SetForce_Dirunit_Y = Force_Y / SetForce_Mag;
	}

	int res;
	unsigned char buf[256];

	memset(buf,0x00,sizeof(buf));

	buf[0] = 0;
	buf[1] = 0x97;
	interG_X_Bytes = (unsigned char *)&interG_X;
	interG_Y_Bytes = (unsigned char *)&interG_Y;
	Force_Mag_Bytes = (unsigned char *)&SetForce_Mag;
	Force_Dirunit_X_Bytes = (unsigned char *)&SetForce_Dirunit_X;
	Force_Dirunit_Y_Bytes = (unsigned char *)&SetForce_Dirunit_Y;

	buf[2] = interG_X_Bytes[0];
	buf[3] = interG_X_Bytes[1];
	buf[4] = interG_X_Bytes[2];
	buf[5] = interG_X_Bytes[3];

	buf[6] = interG_Y_Bytes[0];
	buf[7] = interG_Y_Bytes[1];
	buf[8] = interG_Y_Bytes[2];
	buf[9] = interG_Y_Bytes[3];

	buf[10] = Force_Mag_Bytes[0] ;
	buf[11] = Force_Mag_Bytes[1] ;
	buf[12] = Force_Mag_Bytes[2] ;
	buf[13] = Force_Mag_Bytes[3] ;

	buf[14] = Force_Dirunit_X_Bytes[0] ;
	buf[15] = Force_Dirunit_X_Bytes[1] ;
	buf[16] = Force_Dirunit_X_Bytes[2] ;
	buf[17] = Force_Dirunit_X_Bytes[3] ;

	buf[18] = Force_Dirunit_Y_Bytes[0] ;
	buf[19] = Force_Dirunit_Y_Bytes[1] ;
	buf[20] = Force_Dirunit_Y_Bytes[2] ;
	buf[21] = Force_Dirunit_Y_Bytes[3] ;
	res = hid_write(handle, buf, 65);
	if (res < 0) {
		printf("Unable to make feedback: %ls\n", hid_error(handle));
		return 1;
	}

	return 0;
}

void ofxSpidarMouse::draw(int col = 0x000000)
{
	ofVec2f circleCenter(80, 100);
	int r = 30;

	string info = "";
	info += "X Value: "+ofToString(Force_XScale, 3)+"\n";
	info += "Y Value: "+ofToString(Force_YScale, 3)+"\n\n";
 	ofSetHexColor(col);
	ofDrawBitmapString(info, 30, 30);

	ofFill();

	for( int i = 0 ; i < forceStack.size() ; i++ ) {
		ofSetColor(i * 6);
		if( fabsf(forceStack[i].x) > 0.01 || fabsf(forceStack[i].y) > 0.01 ) {
			ofCircle(circleCenter + forceStack[i] * r * i / 30, 3);
		}
	}

	ofNoFill();
 	ofSetHexColor(col);
	ofCircle(circleCenter, r * 1.41);
	ofCircle(circleCenter, r * 1.41 / 2);
}<commit_msg>Improved debug window<commit_after>/*******************************************************
 SPIDAR-mouse-server for Linux, FreeBSD and Mac OS X
 Copyright (c) 2013 Naoto Hieda
 March 3, 2013
 Licensed under MIT license.
 https://github.com/micuat/SPIDAR-mouse-UNIX

 ofxSpidarMouse.cpp

 ********************************************************/

#include "ofxSpidarMouse.h"
#include "hidapi.h"

ofxSpidarMouse::ofxSpidarMouse()
{
	isInitialized = false;
	isOpened = false;
}

int ofxSpidarMouse::init()
{
	isInitialized = false;

	int res;
	unsigned char buf[256];
#define MAX_STR 255
	wchar_t wstr[MAX_STR];

	devs = hid_enumerate(0x0, 0x0);
	cur_dev = devs;
	while (cur_dev) {
		printf("Device Found\n  type: %04hx %04hx\n  path: %s\n  serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
		printf("\n");
		printf("  Manufacturer: %ls\n", cur_dev->manufacturer_string);
		printf("  Product:      %ls\n", cur_dev->product_string);
		printf("  Release:      %hx\n", cur_dev->release_number);
		printf("  Interface:    %d\n",  cur_dev->interface_number);
		printf("\n");
		cur_dev = cur_dev->next;
	}
	hid_free_enumeration(devs);

	// Set up the command buffer.
	memset(buf,0x00,sizeof(buf));
	buf[0] = 0x01;
	buf[1] = 0x81;

	// Open the device using the VID, PID,
	// and optionally the Serial number.
	////handle = hid_open(0x4d8, 0x3f, L"12345");
	handle = hid_open(0x4d8, 0x3f, NULL);
	if (!handle) {
		printf("unable to open device\n");
 		return 1;
	}

	// Read the Manufacturer String
	wstr[0] = 0x0000;
	res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read manufacturer string\n");
	printf("Manufacturer String: %ls\n", wstr);

	// Read the Product String
	wstr[0] = 0x0000;
	res = hid_get_product_string(handle, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read product string\n");
	printf("Product String: %ls\n", wstr);

	// Read the Serial Number String
	wstr[0] = 0x0000;
	res = hid_get_serial_number_string(handle, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read serial number string\n");
	printf("Serial Number String: (%d) %ls", wstr[0], wstr);
	printf("\n");

	// Read Indexed String 1
	wstr[0] = 0x0000;
	res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read indexed string 1\n");
	printf("Indexed String 1: %ls\n", wstr);

	// Set the hid_read() function to be non-blocking.
	hid_set_nonblocking(handle, 1);

	// Try to read from the device. There shoud be no
	// data here, but execution should not block.
	res = hid_read(handle, buf, 17);

	// Send a Feature Report to the device
	buf[0] = 0x2;
	buf[1] = 0xa0;
	buf[2] = 0x0a;
	buf[3] = 0x00;
	buf[4] = 0x00;
	res = hid_send_feature_report(handle, buf, 17);
	if (res < 0) {
		printf("Unable to send a feature report.\n");
	}

	memset(buf,0,sizeof(buf));

	// Read a Feature Report from the device
	buf[0] = 0x2;
	res = hid_get_feature_report(handle, buf, sizeof(buf));
	if (res < 0) {
		printf("Unable to get a feature report.\n");
		printf("%ls\n", hid_error(handle));
	}
	else {
		// Print out the returned buffer.
		printf("Feature Report\n   ");
		for (int i = 0; i < res; i++)
			printf("%02hhx ", buf[i]);
		printf("\n");
	}

	isInitialized = true;
	return 0;
}

ofxSpidarMouse::~ofxSpidarMouse()
{
	if( isOpened ) {
		close();
	}

	if( isInitialized ) {
		hid_close(handle);

		/* Free static HIDAPI objects. */
		hid_exit();
	}
}

int ofxSpidarMouse::open()
{
	isOpened = false;

	if( !isInitialized ) {
		return 1;
	}

	int res;
	unsigned char buf[256];
	float conf_data[4];

	// Initialize parameters

	interG_X=0.0;
	interG_Y=0.0;
	SetForce_Mag=0.0;
	SetForce_Dirunit_X=0.0;
	SetForce_Dirunit_Y=0.0;
	Max_Force=1.5;
	defaultDuration = 4; // 4ms
	duration = 0;

	forceStack.clear();
	//////////////// Start SPIDAR-mouse

	memset(buf,0,sizeof(buf));

	buf[0] = 0x00;
	buf[1] = 0x82;
	res = hid_write(handle, buf, 65);
	if (res < 0) {
		printf("Unable to write()\n");
		printf("Error: %ls\n", hid_error(handle));
		return 1;
	}

	// Read requested state. hid_read() has been set to be
	// non-blocking by the call to hid_set_nonblocking() above.
	// This loop demonstrates the non-blocking nature of hid_read().
	res = 0;
	while (res == 0) {
		res = hid_read(handle, buf, sizeof(buf));
		if (res == 0)
			printf("waiting...\n");
		if (res < 0)
			printf("Unable to read()\n");
#ifdef WIN32
		Sleep(500);
#else
		usleep(500*1000);
#endif
	}

	printf("Data read:\n   ");
	// Print out the returned buffer.
	for (int i = 0; i < res; i++)
		printf("%02hhx ", buf[i]);
	printf("\n");

	memset(buf,0,sizeof(buf));

	conf_data[0] = 0.3;
	conf_data[1] = 1.5;
	conf_data[2] = 47.9867;
	conf_data[3] = 13.1215;
	MinForce_Bytes = (unsigned char *)&conf_data[0];
	MaxForce_Bytes = (unsigned char *)&conf_data[1];
	Fun_a_Bytes = (unsigned char *)&conf_data[2];
	Fun_b_Bytes = (unsigned char *)&conf_data[3];

	buf[0] = 0;
	buf[1] = 0x80;
	buf[2] = MinForce_Bytes[0];
	buf[3] = MinForce_Bytes[1];
	buf[4] = MinForce_Bytes[2];
	buf[5] = MinForce_Bytes[3];

	buf[6] = MaxForce_Bytes[0];
	buf[7] = MaxForce_Bytes[1];
	buf[8] = MaxForce_Bytes[2];
	buf[9] = MaxForce_Bytes[3];

	buf[10] = Fun_a_Bytes[0];
	buf[11] = Fun_a_Bytes[1];
	buf[12] = Fun_a_Bytes[2];
	buf[13] = Fun_a_Bytes[3];

	buf[14] = Fun_b_Bytes[0];
	buf[15] = Fun_b_Bytes[1];
	buf[16] = Fun_b_Bytes[2];
	buf[17] = Fun_b_Bytes[3];
	res = hid_write(handle, buf, 65);
	if (res < 0) {
		printf("Unable to start SPIDAR-mouse: %ls\n", hid_error(handle));
		return 1;
	}

	setForce(0.0, 0.0);

	isOpened = true;
	return 0;
}

int ofxSpidarMouse::close()
{
	if( !isOpened ) {
		return 1;
	}

	int res;
	unsigned char buf[256];

	buf[0] = 0;
	buf[1] = 0x99;
	res = hid_write(handle, buf, 65);
	if (res < 0) {
		printf("Unable to close SPIDAR-mouse: %d %ls\n", res, hid_error(handle));
	}

	return 0;
}

int ofxSpidarMouse::update()
{
	unsigned long curTime = ofGetSystemTime();

	if( duration != 0 && (curTime - startTime) > duration ) {
		setForce(0.0, 0.0);
		duration = 0;
	}

	forceStack.push_back(ofVec2f(Force_XScale, Force_YScale));
	if( forceStack.size() > 30 ) {
		forceStack.erase(forceStack.begin());
	}

	return 0;
}

int ofxSpidarMouse::setForce(float fx, float fy)
{
	duration = 0; // infinite

	return sForce(fx, fy);
}

int ofxSpidarMouse::setForce(float fx, float fy, int d)
{
	startTime = ofGetSystemTime();

	if( d < defaultDuration ) {
		duration = defaultDuration;
	} else {
		duration = d;
	}

	return sForce(fx, fy);
}

int ofxSpidarMouse::sForce(float fx, float fy)
{
	if( fabsf(fx) > 1.0 ) {
		Force_XScale = fx / fabsf(fx);
	} else {
		Force_XScale = fx;
	}

	if( fabsf(fy) > 1.0 ) {
		Force_YScale = fy / fabsf(fy);
	} else {
		Force_YScale = fy;
	}

	if( !isOpened ) {
		return 1;
	}

	Force_X = Force_XScale * Max_Force;
	Force_Y = Force_YScale * Max_Force;
	SetForce_Mag = sqrt(Force_X * Force_X + Force_Y * Force_Y);
	if ( SetForce_Mag > 0.0 ) {
		SetForce_Dirunit_X = Force_X / SetForce_Mag;
		SetForce_Dirunit_Y = Force_Y / SetForce_Mag;
	}

	int res;
	unsigned char buf[256];

	memset(buf,0x00,sizeof(buf));

	buf[0] = 0;
	buf[1] = 0x97;
	interG_X_Bytes = (unsigned char *)&interG_X;
	interG_Y_Bytes = (unsigned char *)&interG_Y;
	Force_Mag_Bytes = (unsigned char *)&SetForce_Mag;
	Force_Dirunit_X_Bytes = (unsigned char *)&SetForce_Dirunit_X;
	Force_Dirunit_Y_Bytes = (unsigned char *)&SetForce_Dirunit_Y;

	buf[2] = interG_X_Bytes[0];
	buf[3] = interG_X_Bytes[1];
	buf[4] = interG_X_Bytes[2];
	buf[5] = interG_X_Bytes[3];

	buf[6] = interG_Y_Bytes[0];
	buf[7] = interG_Y_Bytes[1];
	buf[8] = interG_Y_Bytes[2];
	buf[9] = interG_Y_Bytes[3];

	buf[10] = Force_Mag_Bytes[0] ;
	buf[11] = Force_Mag_Bytes[1] ;
	buf[12] = Force_Mag_Bytes[2] ;
	buf[13] = Force_Mag_Bytes[3] ;

	buf[14] = Force_Dirunit_X_Bytes[0] ;
	buf[15] = Force_Dirunit_X_Bytes[1] ;
	buf[16] = Force_Dirunit_X_Bytes[2] ;
	buf[17] = Force_Dirunit_X_Bytes[3] ;

	buf[18] = Force_Dirunit_Y_Bytes[0] ;
	buf[19] = Force_Dirunit_Y_Bytes[1] ;
	buf[20] = Force_Dirunit_Y_Bytes[2] ;
	buf[21] = Force_Dirunit_Y_Bytes[3] ;
	res = hid_write(handle, buf, 65);
	if (res < 0) {
		printf("Unable to make feedback: %ls\n", hid_error(handle));
		return 1;
	}

	return 0;
}

void ofxSpidarMouse::draw(int col = 0x000000)
{
	ofVec2f circleCenter(80, 100);
	int r = 30;

	string info = "";
	info += "X Value: "+ofToString(Force_XScale, 3)+"\n";
	info += "Y Value: "+ofToString(Force_YScale, 3)+"\n\n";
 	ofSetHexColor(col);
	ofDrawBitmapString(info, 30, 30);

	ofFill();

	for( int i = 0 ; i < forceStack.size() ; i++ ) {
		ofSetColor(i * 6);
		if( fabsf(forceStack[i].x) > 0.01 || fabsf(forceStack[i].y) > 0.01 ) {
			ofPushMatrix();
			ofTranslate(circleCenter + forceStack[i] * r * i / 30);
			ofRotateZ(atan2(forceStack[i].y, forceStack[i].x)/M_PI*180);
			ofRect(-2, -4, 4, 8);
			ofPopMatrix();
		}
	}

	ofNoFill();
 	ofSetHexColor(col);
	ofCircle(circleCenter, r * 1.41);
	ofCircle(circleCenter, r * 1.41 / 2);
}<|endoftext|>


<commit_before>
// The files containing the tree of child classes of |DynamicFrame| must be
// included in the order of inheritance to avoid circular dependencies.  This
// class will end up being reincluded as part of the implementation of its
// parent.
#ifndef PRINCIPIA_PHYSICS_DYNAMIC_FRAME_HPP_
#include "physics/dynamic_frame.hpp"
#else
#ifndef PRINCIPIA_PHYSICS_BODY_CENTRED_BODY_DIRECTION_DYNAMIC_FRAME_HPP_
#define PRINCIPIA_PHYSICS_BODY_CENTRED_BODY_DIRECTION_DYNAMIC_FRAME_HPP_

#include "base/not_null.hpp"
#include "geometry/grassmann.hpp"
#include "geometry/named_quantities.hpp"
#include "geometry/rotation.hpp"
#include "physics/continuous_trajectory.hpp"
#include "physics/degrees_of_freedom.hpp"
#include "physics/dynamic_frame.hpp"
#include "physics/ephemeris.hpp"
#include "physics/massive_body.hpp"
#include "physics/rigid_motion.hpp"
#include "quantities/named_quantities.hpp"

namespace principia {
namespace physics {
namespace internal_body_centred_body_direction_dynamic_frame {

using base::not_null;
using geometry::AngularVelocity;
using geometry::Instant;
using geometry::Position;
using geometry::Rotation;
using geometry::Vector;
using quantities::Acceleration;

// The origin of the frame is the center of mass of the primary body.  The X axis
// points to the secondary.  The Y axis is in the direction of the velocity of
// the secondary with respect to the primary.  The Z axis is in the direction of
// the angular velocity of the system.  The basis has the same orientation as
// |InertialFrame|.
template<typename InertialFrame, typename ThisFrame>
class BodyCentredBodyDirectionDynamicFrame
    : public DynamicFrame<InertialFrame, ThisFrame> {
 public:
  BodyCentredBodyDirectionDynamicFrame(
      not_null<Ephemeris<InertialFrame> const*> const ephemeris,
      not_null<MassiveBody const*> const primary,
      not_null<MassiveBody const*> const secondary);

  RigidMotion<InertialFrame, ThisFrame> ToThisFrameAtTime(
      Instant const& t) const override;

  void WriteToMessage(
      not_null<serialization::DynamicFrame*> const message) const override;

  static not_null<std::unique_ptr<BodyCentredBodyDirectionDynamicFrame>>
      ReadFromMessage(
          not_null<Ephemeris<InertialFrame> const*> const ephemeris,
          serialization::BodyCentredBodyDirectionDynamicFrame const& message);

 private:
  Vector<Acceleration, InertialFrame> GravitationalAcceleration(
      Instant const& t,
      Position<InertialFrame> const& q) const override;
  AcceleratedRigidMotion<InertialFrame, ThisFrame> MotionOfThisFrame(
      Instant const& t) const override;

  // Fills |*rotation| with the rotation that maps the basis of |InertialFrame|
  // to the basis of |ThisFrame|.  Fills |*angular_frequency| with the
  // corresponding angular velocity.
  static void ComputeAngularDegreesOfFreedom(
      DegreesOfFreedom<InertialFrame> const& primary_degrees_of_freedom,
      DegreesOfFreedom<InertialFrame> const& secondary_degrees_of_freedom,
      not_null<Rotation<InertialFrame, ThisFrame>*> const rotation,
      not_null<AngularVelocity<InertialFrame>*> const angular_velocity);

  not_null<Ephemeris<InertialFrame> const*> const ephemeris_;
  not_null<MassiveBody const*> const primary_;
  not_null<MassiveBody const*> const secondary_;
  not_null<ContinuousTrajectory<InertialFrame> const*> const
      primary_trajectory_;
  not_null<ContinuousTrajectory<InertialFrame> const*> const
      secondary_trajectory_;
  mutable typename ContinuousTrajectory<InertialFrame>::Hint primary_hint_;
  mutable typename ContinuousTrajectory<InertialFrame>::Hint secondary_hint_;
};

}  // namespace internal_body_centred_body_direction_dynamic_frame

using internal_body_centred_body_direction_dynamic_frame::
    BodyCentredBodyDirectionDynamicFrame;

}  // namespace physics
}  // namespace principia

#include "physics/body_centred_body_direction_dynamic_frame_body.hpp"

#endif  // PRINCIPIA_PHYSICS_BODY_CENTRED_BODY_DIRECTION_DYNAMIC_FRAME_HPP_
#endif  // PRINCIPIA_PHYSICS_DYNAMIC_FRAME_HPP_
<commit_msg>Lint.<commit_after>
// The files containing the tree of child classes of |DynamicFrame| must be
// included in the order of inheritance to avoid circular dependencies.  This
// class will end up being reincluded as part of the implementation of its
// parent.
#ifndef PRINCIPIA_PHYSICS_DYNAMIC_FRAME_HPP_
#include "physics/dynamic_frame.hpp"
#else
#ifndef PRINCIPIA_PHYSICS_BODY_CENTRED_BODY_DIRECTION_DYNAMIC_FRAME_HPP_
#define PRINCIPIA_PHYSICS_BODY_CENTRED_BODY_DIRECTION_DYNAMIC_FRAME_HPP_

#include "base/not_null.hpp"
#include "geometry/grassmann.hpp"
#include "geometry/named_quantities.hpp"
#include "geometry/rotation.hpp"
#include "physics/continuous_trajectory.hpp"
#include "physics/degrees_of_freedom.hpp"
#include "physics/dynamic_frame.hpp"
#include "physics/ephemeris.hpp"
#include "physics/massive_body.hpp"
#include "physics/rigid_motion.hpp"
#include "quantities/named_quantities.hpp"

namespace principia {
namespace physics {
namespace internal_body_centred_body_direction_dynamic_frame {

using base::not_null;
using geometry::AngularVelocity;
using geometry::Instant;
using geometry::Position;
using geometry::Rotation;
using geometry::Vector;
using quantities::Acceleration;

// The origin of the frame is the center of mass of the primary body.  The X
// axis points to the secondary.  The Y axis is in the direction of the velocity
// of the secondary with respect to the primary.  The Z axis is in the direction
// of the angular velocity of the system.  The basis has the same orientation as
// |InertialFrame|.
template<typename InertialFrame, typename ThisFrame>
class BodyCentredBodyDirectionDynamicFrame
    : public DynamicFrame<InertialFrame, ThisFrame> {
 public:
  BodyCentredBodyDirectionDynamicFrame(
      not_null<Ephemeris<InertialFrame> const*> const ephemeris,
      not_null<MassiveBody const*> const primary,
      not_null<MassiveBody const*> const secondary);

  RigidMotion<InertialFrame, ThisFrame> ToThisFrameAtTime(
      Instant const& t) const override;

  void WriteToMessage(
      not_null<serialization::DynamicFrame*> const message) const override;

  static not_null<std::unique_ptr<BodyCentredBodyDirectionDynamicFrame>>
      ReadFromMessage(
          not_null<Ephemeris<InertialFrame> const*> const ephemeris,
          serialization::BodyCentredBodyDirectionDynamicFrame const& message);

 private:
  Vector<Acceleration, InertialFrame> GravitationalAcceleration(
      Instant const& t,
      Position<InertialFrame> const& q) const override;
  AcceleratedRigidMotion<InertialFrame, ThisFrame> MotionOfThisFrame(
      Instant const& t) const override;

  // Fills |*rotation| with the rotation that maps the basis of |InertialFrame|
  // to the basis of |ThisFrame|.  Fills |*angular_frequency| with the
  // corresponding angular velocity.
  static void ComputeAngularDegreesOfFreedom(
      DegreesOfFreedom<InertialFrame> const& primary_degrees_of_freedom,
      DegreesOfFreedom<InertialFrame> const& secondary_degrees_of_freedom,
      not_null<Rotation<InertialFrame, ThisFrame>*> const rotation,
      not_null<AngularVelocity<InertialFrame>*> const angular_velocity);

  not_null<Ephemeris<InertialFrame> const*> const ephemeris_;
  not_null<MassiveBody const*> const primary_;
  not_null<MassiveBody const*> const secondary_;
  not_null<ContinuousTrajectory<InertialFrame> const*> const
      primary_trajectory_;
  not_null<ContinuousTrajectory<InertialFrame> const*> const
      secondary_trajectory_;
  mutable typename ContinuousTrajectory<InertialFrame>::Hint primary_hint_;
  mutable typename ContinuousTrajectory<InertialFrame>::Hint secondary_hint_;
};

}  // namespace internal_body_centred_body_direction_dynamic_frame

using internal_body_centred_body_direction_dynamic_frame::
    BodyCentredBodyDirectionDynamicFrame;

}  // namespace physics
}  // namespace principia

#include "physics/body_centred_body_direction_dynamic_frame_body.hpp"

#endif  // PRINCIPIA_PHYSICS_BODY_CENTRED_BODY_DIRECTION_DYNAMIC_FRAME_HPP_
#endif  // PRINCIPIA_PHYSICS_DYNAMIC_FRAME_HPP_
<|endoftext|>


<commit_before>/*
 * AscEmu Framework based on ArcEmu MMORPG Server
 * Copyright (c) 2014-2020 AscEmu Team <http://www.ascemu.org>
 * Copyright (C) 2008-2012 ArcEmu Team <http://www.ArcEmu.org/>
 * Copyright (C) 2005-2007 Ascent Team
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"
#include "Storage/MySQLDataStore.hpp"
#include "Server/MainServerDefines.h"
#include "CellHandler.h"
#include "WorldCreator.h"

// Class Map
// Holder for all instances of each mapmgr, handles transferring players between, and template holding.
Map::Map(uint32 mapid, MySQLStructure::MapInfo const* inf)
{
    memset(spawns, 0, sizeof(CellSpawns*) * _sizeX);

    _mapInfo = inf;
    _mapId = mapid;

    //new stuff Load Spawns
    LoadSpawns(false);

    // get our name
    if (_mapInfo)
        name = _mapInfo->name;
    else
        name = "Unknown";
}

Map::~Map()
{
    LogNotice("Map : ~Map %u", this->_mapId);

    for (uint32 x = 0; x < _sizeX; x++)
    {
        if (spawns[x])
        {
            for (uint32 y = 0; y < _sizeY; y++)
            {
                if (spawns[x][y])
                {
                    CellSpawns* sp = spawns[x][y];
                    for (CreatureSpawnList::iterator i = sp->CreatureSpawns.begin(); i != sp->CreatureSpawns.end(); ++i)
                        delete(*i);
                    for (GameobjectSpawnList::iterator it = sp->GameobjectSpawns.begin(); it != sp->GameobjectSpawns.end(); ++it)
                        delete(*it);

                    delete sp;
                    spawns[x][y] = NULL;
                }
            }
            delete[] spawns[x];
        }
    }

    for (CreatureSpawnList::iterator i = staticSpawns.CreatureSpawns.begin(); i != staticSpawns.CreatureSpawns.end(); ++i)
        delete *i;
    for (GameobjectSpawnList::iterator i = staticSpawns.GameobjectSpawns.begin(); i != staticSpawns.GameobjectSpawns.end(); ++i)
        delete *i;
}

std::string Map::GetMapName()
{
    return name;
}

CellSpawns* Map::GetSpawnsList(uint32 cellx, uint32 celly)
{
    ARCEMU_ASSERT(cellx < _sizeX);
    ARCEMU_ASSERT(celly < _sizeY);
    if (spawns[cellx] == NULL)
        return NULL;
    return spawns[cellx][celly];
}

CellSpawns* Map::GetSpawnsListAndCreate(uint32 cellx, uint32 celly)
{
    ARCEMU_ASSERT(cellx < _sizeX);
    ARCEMU_ASSERT(celly < _sizeY);
    if (spawns[cellx] == NULL)
    {
        spawns[cellx] = new CellSpawns*[_sizeY];
        memset(spawns[cellx], 0, sizeof(CellSpawns*)*_sizeY);
    }

    if (spawns[cellx][celly] == 0)
        spawns[cellx][celly] = new CellSpawns;
    return spawns[cellx][celly];
}

#define CREATURESPAWNSFIELDCOUNT 27
#define GOSPAWNSFIELDCOUNT 18

void Map::LoadSpawns(bool reload)
{
    if (reload)   //perform cleanup
    {
        for (uint32 x = 0; x < _sizeX; x++)
        {
            for (uint32 y = 0; y < _sizeY; y++)
            {
                if (spawns[x][y])
                {
                    CellSpawns* sp = spawns[x][y];
                    for (CreatureSpawnList::iterator i = sp->CreatureSpawns.begin(); i != sp->CreatureSpawns.end(); ++i)
                        delete(*i);
                    for (GameobjectSpawnList::iterator it = sp->GameobjectSpawns.begin(); it != sp->GameobjectSpawns.end(); ++it)
                        delete(*it);

                    delete sp;
                    spawns[x][y] = NULL;
                }
            }
        }
    }

    CreatureSpawnCount = 0;
    for (auto cspawn : sMySQLStore._creatureSpawnsStore[this->_mapId])
    {
        uint32 cellx = CellHandler<MapMgr>::GetPosX(cspawn->x);
        uint32 celly = CellHandler<MapMgr>::GetPosY(cspawn->y);
        if (!spawns[cellx])
        {
            spawns[cellx] = new CellSpawns * [_sizeY];
            memset(spawns[cellx], 0, sizeof(CellSpawns*) * _sizeY);
        }

        if (!spawns[cellx][celly])
            spawns[cellx][celly] = new CellSpawns;

        spawns[cellx][celly]->CreatureSpawns.push_back(cspawn);
        ++CreatureSpawnCount;

    }

    GameObjectSpawnCount = 0;
    for (auto go_spawn : sMySQLStore._gameobjectSpawnsStore[this->_mapId])
    {
        if (go_spawn->overrides & GAMEOBJECT_MAPWIDE)
        {
            staticSpawns.GameobjectSpawns.push_back(go_spawn); //We already have a staticSpawns in the Map class, and it does just the right thing
            ++GameObjectSpawnCount;
        }
        else
        {
            // Zyres: transporter stuff
            if (sMySQLStore.getGameObjectProperties(go_spawn->entry)->type == 11 || sMySQLStore.getGameObjectProperties(go_spawn->entry)->type == 15)
            {
                staticSpawns.GameobjectSpawns.push_back(go_spawn);
            }
            else
            {
                uint32 cellx = CellHandler<MapMgr>::GetPosX(go_spawn->position_x);
                uint32 celly = CellHandler<MapMgr>::GetPosY(go_spawn->position_y);
                if (spawns[cellx] == NULL)
                {
                    spawns[cellx] = new CellSpawns * [_sizeY];
                    memset(spawns[cellx], 0, sizeof(CellSpawns*) * _sizeY);
                }

                if (!spawns[cellx][celly])
                    spawns[cellx][celly] = new CellSpawns;
            }

            ++GameObjectSpawnCount;
        }
    }

    LogDetail("MapMgr : %u creatures / %u gobjects on map %u cached.", CreatureSpawnCount, GameObjectSpawnCount, _mapId);
}
<commit_msg>Fix "no normal spawns on Map" @aaron02<commit_after>/*
 * AscEmu Framework based on ArcEmu MMORPG Server
 * Copyright (c) 2014-2020 AscEmu Team <http://www.ascemu.org>
 * Copyright (C) 2008-2012 ArcEmu Team <http://www.ArcEmu.org/>
 * Copyright (C) 2005-2007 Ascent Team
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"
#include "Storage/MySQLDataStore.hpp"
#include "Server/MainServerDefines.h"
#include "CellHandler.h"
#include "WorldCreator.h"

// Class Map
// Holder for all instances of each mapmgr, handles transferring players between, and template holding.
Map::Map(uint32 mapid, MySQLStructure::MapInfo const* inf)
{
    memset(spawns, 0, sizeof(CellSpawns*) * _sizeX);

    _mapInfo = inf;
    _mapId = mapid;

    //new stuff Load Spawns
    LoadSpawns(false);

    // get our name
    if (_mapInfo)
        name = _mapInfo->name;
    else
        name = "Unknown";
}

Map::~Map()
{
    LogNotice("Map : ~Map %u", this->_mapId);

    for (uint32 x = 0; x < _sizeX; x++)
    {
        if (spawns[x])
        {
            for (uint32 y = 0; y < _sizeY; y++)
            {
                if (spawns[x][y])
                {
                    CellSpawns* sp = spawns[x][y];
                    for (CreatureSpawnList::iterator i = sp->CreatureSpawns.begin(); i != sp->CreatureSpawns.end(); ++i)
                        delete(*i);
                    for (GameobjectSpawnList::iterator it = sp->GameobjectSpawns.begin(); it != sp->GameobjectSpawns.end(); ++it)
                        delete(*it);

                    delete sp;
                    spawns[x][y] = NULL;
                }
            }
            delete[] spawns[x];
        }
    }

    for (CreatureSpawnList::iterator i = staticSpawns.CreatureSpawns.begin(); i != staticSpawns.CreatureSpawns.end(); ++i)
        delete *i;
    for (GameobjectSpawnList::iterator i = staticSpawns.GameobjectSpawns.begin(); i != staticSpawns.GameobjectSpawns.end(); ++i)
        delete *i;
}

std::string Map::GetMapName()
{
    return name;
}

CellSpawns* Map::GetSpawnsList(uint32 cellx, uint32 celly)
{
    ARCEMU_ASSERT(cellx < _sizeX);
    ARCEMU_ASSERT(celly < _sizeY);
    if (spawns[cellx] == NULL)
        return NULL;
    return spawns[cellx][celly];
}

CellSpawns* Map::GetSpawnsListAndCreate(uint32 cellx, uint32 celly)
{
    ARCEMU_ASSERT(cellx < _sizeX);
    ARCEMU_ASSERT(celly < _sizeY);
    if (spawns[cellx] == NULL)
    {
        spawns[cellx] = new CellSpawns*[_sizeY];
        memset(spawns[cellx], 0, sizeof(CellSpawns*)*_sizeY);
    }

    if (spawns[cellx][celly] == 0)
        spawns[cellx][celly] = new CellSpawns;
    return spawns[cellx][celly];
}

#define CREATURESPAWNSFIELDCOUNT 27
#define GOSPAWNSFIELDCOUNT 18

void Map::LoadSpawns(bool reload)
{
    if (reload)   //perform cleanup
    {
        for (uint32 x = 0; x < _sizeX; x++)
        {
            for (uint32 y = 0; y < _sizeY; y++)
            {
                if (spawns[x][y])
                {
                    CellSpawns* sp = spawns[x][y];
                    for (CreatureSpawnList::iterator i = sp->CreatureSpawns.begin(); i != sp->CreatureSpawns.end(); ++i)
                        delete(*i);
                    for (GameobjectSpawnList::iterator it = sp->GameobjectSpawns.begin(); it != sp->GameobjectSpawns.end(); ++it)
                        delete(*it);

                    delete sp;
                    spawns[x][y] = NULL;
                }
            }
        }
    }

    CreatureSpawnCount = 0;
    for (auto cspawn : sMySQLStore._creatureSpawnsStore[this->_mapId])
    {
        uint32 cellx = CellHandler<MapMgr>::GetPosX(cspawn->x);
        uint32 celly = CellHandler<MapMgr>::GetPosY(cspawn->y);
        if (!spawns[cellx])
        {
            spawns[cellx] = new CellSpawns * [_sizeY];
            memset(spawns[cellx], 0, sizeof(CellSpawns*) * _sizeY);
        }

        if (!spawns[cellx][celly])
            spawns[cellx][celly] = new CellSpawns;

        spawns[cellx][celly]->CreatureSpawns.push_back(cspawn);
        ++CreatureSpawnCount;

    }

    GameObjectSpawnCount = 0;
    for (auto go_spawn : sMySQLStore._gameobjectSpawnsStore[this->_mapId])
    {
        if (go_spawn->overrides & GAMEOBJECT_MAPWIDE)
        {
            staticSpawns.GameobjectSpawns.push_back(go_spawn); //We already have a staticSpawns in the Map class, and it does just the right thing
            ++GameObjectSpawnCount;
        }
        else
        {
            // Zyres: transporter stuff
            if (sMySQLStore.getGameObjectProperties(go_spawn->entry)->type == 11 || sMySQLStore.getGameObjectProperties(go_spawn->entry)->type == 15)
            {
                staticSpawns.GameobjectSpawns.push_back(go_spawn);
            }
            else
            {
                uint32 cellx = CellHandler<MapMgr>::GetPosX(go_spawn->position_x);
                uint32 celly = CellHandler<MapMgr>::GetPosY(go_spawn->position_y);
                if (spawns[cellx] == NULL)
                {
                    spawns[cellx] = new CellSpawns * [_sizeY];
                    memset(spawns[cellx], 0, sizeof(CellSpawns*) * _sizeY);
                }

                if (!spawns[cellx][celly])
                    spawns[cellx][celly] = new CellSpawns;

                spawns[cellx][celly]->GameobjectSpawns.push_back(go_spawn);
            }

            ++GameObjectSpawnCount;
        }
    }

    LogDetail("MapMgr : %u creatures / %u gobjects on map %u cached.", CreatureSpawnCount, GameObjectSpawnCount, _mapId);
}
<|endoftext|>


<commit_before>/**
 *	@file		statistics.hpp
 *	@brief		An implemenation of statistics operations
 *	@author		seonho.oh@gmail.com
 *	@date		2013-07-01
 *	@version	1.0
 *
 *	@section	LICENSE
 *
 *		Copyright (c) 2007-2013, Seonho Oh
 *		All rights reserved.
 *
 *		Redistribution and use in source and binary forms, with or without
 *		modification, are permitted provided that the following conditions are
 *		met:
 *
 *		    * Redistributions of source code must retain the above copyright
 *		    notice, this list of conditions and the following disclaimer.
 *		    * Redistributions in binary form must reproduce the above copyright
 *		    notice, this list of conditions and the following disclaimer in the
 *		    documentation and/or other materials provided with the distribution.
 *		    * Neither the name of the <ORGANIZATION> nor the names of its
 *		    contributors may be used to endorse or promote products derived from
 *		    this software without specific prior written permission.
 *
 *		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 *		IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 *		TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *		PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 *		OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *		PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *		PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *		LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *		NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *		SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <armadillo>

namespace arma_ext
{
	using namespace arma;

	/**
	 *	@brief	2-D correlation coefficient
	 *	@param A
	 *	@param B
	 *	@return	the correlation coefficient between @c A and @c B, where @c A and @c B are matrices or vectors of the same size.
	 *			@c corr2 computes the correlation coefficient using
	 *			\f[
	 *				r = \frac{ \sum_{m}\sum_{n}(A_{mn}-\bar{A}) (B_{mn}-\bar{B}) }{\sqrt{ \left( \sum_{m}\sum_{n}(A_{mn}-\bar{A})^2 \right) \left( \sum_{m}\sum_{n}(B_{mn}-\bar{B})^2 \right)}}
	 *			\f]
	 *			where
	 *			\f$ \bar{A}\f$=mean2(A), and \f$\bar{B}\f$=mean2(B).
	 *	@see	http://www.mathworks.co.kr/kr/help/images/ref/corr2.html
	 */
	template <typename mat_type, typename prec_type>
	inline prec_type corr2(const mat_type& A, const mat_type& B)
	{
		typedef Mat<prec_type> tmat;
		tmat A1, B1;
		A1 = conv_to<tmat>::from(A);
		B1 = conv_to<tmat>::from(B);
		A1 -= mean2(A1);
		B1 -= mean2(B1);
		return accu(A1 % B1) / sqrt(accu(square(A1)) * accu(square(B1)));
	}

	/**
	 *	@brief	Distance metric
	 */
	enum distance_type : uword {
		euclidean,		///< Euclidean distance.
		seuclidean,		///< Standarized Eucliean distance.
		cityblock,		///< City block metric.
		minkowski,		///< Minkowski distance. The default exponent is 2.
		chebychev,		///< Chebychev distance (maximum coordinate difference).
		mahalanobis,	///< Mahalanobis distance, using the sample covariance of X.
		cosine,			///< One minus the cosine of the included angle between points(treated as vectors).
		correlation,	///< One minus the sample correlation between points (treatedas sequences of values).
		spearman,		///< One minus the sample Spearman's rank correlation betweenobservations (treated as sequences of values).
		hamming,		///< Hamming distance, which is the percentage of coordinatesthat differ.
		jaccard,		///< One minus the Jaccard coefficient, which is the percentageof nonzero coordinates that differ.
		custom
	};

	typedef double (*pdist_func)(const arma::subview_row<double>&, const arma::subview_row<double>&);

	/// Euclidean distance for pdist
	double pdist_euclidean(const arma::subview_row<double>& a, const arma::subview_row<double>& b)
	{
		return sqrt(sum(square(b - a)));
	}

	/**
	 *	@brief	Pairwise distance between pairs of objects.

	 *			Computes the distance between pairs of objects in \f$m\f$-by-\f$n\f$ data matrix \f$X\f$.
	 *			Rows of \f$X\f$ correspond to observations, and columns correspond to variables.
	 *			Output is the row vector of length \f$frac{m(m - 1)}{2}\f$, corresponding to pairs of observations in \f$X\f$.
	 *			The distances are arranged in the order \f$(2, 1), (3, 1), \cdots, (m, 1), (3, 2), \cdots, (m, 2), \cdots, (m, m - 1)\f$.
	 *			Output is commonly used as a dissimilarity matrix in clustering or multidimensional scailing.
	 *	@return	Pairwise distance.
	 */
	vec pdist(const mat& X, distance_type type = euclidean, pdist_func func_ptr = nullptr)
	{
		const uword m = X.n_rows;
		vec Y(m * (m - 1) / 2);
		double* ptr = Y.memptr();

		switch (type) {
		case euclidean:
			func_ptr = pdist_euclidean;
			break;
		case custom:
			// stub
			break;
		default:
			func_ptr = &pdist_euclidean;
		}

		uword k = 0;
		for (uword i = 0 ; i < m ; i++)
			for (uword j = i + 1 ; j < m ; j++)
				ptr[k++] = func_ptr(X.row(i), X.row(j)); //sqrt(sum(square(X.row(j) - X.row(i))));

		return Y;
	}
}<commit_msg>Update documentation<commit_after>/**
 *	@file		statistics.hpp
 *	@brief		An implemenation of statistics operations
 *	@author		seonho.oh@gmail.com
 *	@date		2013-07-01
 *	@version	1.0
 *
 *	@section	LICENSE
 *
 *		Copyright (c) 2007-2013, Seonho Oh
 *		All rights reserved.
 *
 *		Redistribution and use in source and binary forms, with or without
 *		modification, are permitted provided that the following conditions are
 *		met:
 *
 *		    * Redistributions of source code must retain the above copyright
 *		    notice, this list of conditions and the following disclaimer.
 *		    * Redistributions in binary form must reproduce the above copyright
 *		    notice, this list of conditions and the following disclaimer in the
 *		    documentation and/or other materials provided with the distribution.
 *		    * Neither the name of the <ORGANIZATION> nor the names of its
 *		    contributors may be used to endorse or promote products derived from
 *		    this software without specific prior written permission.
 *
 *		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 *		IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 *		TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *		PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 *		OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *		PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *		PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *		LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *		NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *		SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <armadillo>

namespace arma_ext
{
	using namespace arma;

	/**
	 *	@brief	2-D correlation coefficient
	 *	@param A
	 *	@param B
	 *	@return	the correlation coefficient between @c A and @c B, where @c A and @c B are matrices or vectors of the same size.
	 *			@c corr2 computes the correlation coefficient using
	 *			\f[
	 *				r = \frac{ \sum_{m}\sum_{n}(A_{mn}-\bar{A}) (B_{mn}-\bar{B}) }{\sqrt{ \left( \sum_{m}\sum_{n}(A_{mn}-\bar{A})^2 \right) \left( \sum_{m}\sum_{n}(B_{mn}-\bar{B})^2 \right)}}
	 *			\f]
	 *			where
	 *			\f$ \bar{A}\f$=mean2(A), and \f$\bar{B}\f$=mean2(B).
	 *	@see	http://www.mathworks.co.kr/kr/help/images/ref/corr2.html
	 */
	template <typename mat_type, typename prec_type>
	inline prec_type corr2(const mat_type& A, const mat_type& B)
	{
		typedef Mat<prec_type> tmat;
		tmat A1, B1;
		A1 = conv_to<tmat>::from(A);
		B1 = conv_to<tmat>::from(B);
		A1 -= mean2(A1);
		B1 -= mean2(B1);
		return accu(A1 % B1) / sqrt(accu(square(A1)) * accu(square(B1)));
	}

	/**
	 *	@brief	Distance metric
	 */
	enum distance_type : uword {
		euclidean,		///< Euclidean distance.
		seuclidean,		///< Standarized Eucliean distance.
		cityblock,		///< City block metric.
		minkowski,		///< Minkowski distance. The default exponent is 2.
		chebychev,		///< Chebychev distance (maximum coordinate difference).
		mahalanobis,	///< Mahalanobis distance, using the sample covariance of X.
		cosine,			///< One minus the cosine of the included angle between points(treated as vectors).
		correlation,	///< One minus the sample correlation between points (treatedas sequences of values).
		spearman,		///< One minus the sample Spearman's rank correlation betweenobservations (treated as sequences of values).
		hamming,		///< Hamming distance, which is the percentage of coordinatesthat differ.
		jaccard,		///< One minus the Jaccard coefficient, which is the percentageof nonzero coordinates that differ.
		custom
	};

	typedef double (*pdist_func)(const arma::subview_row<double>&, const arma::subview_row<double>&);

	/// Euclidean distance for pdist
	double pdist_euclidean(const arma::subview_row<double>& a, const arma::subview_row<double>& b)
	{
		return sqrt(sum(square(b - a)));
	}

	/**
	 *	@brief	Pairwise distance between pairs of objects.

	 *			Computes the distance between pairs of objects in \f$m\f$-by-\f$n\f$ data matrix \f$X\f$.
	 *			Rows of \f$X\f$ correspond to observations, and columns correspond to variables.
	 *			Output is the row vector of length \f$ \frac{m(m - 1)}{2} \f$, corresponding to pairs of observations in \f$X\f$.
	 *			The distances are arranged in the order \f$(2, 1), (3, 1), \cdots, (m, 1), (3, 2), \cdots, (m, 2), \cdots, (m, m - 1)\f$.
	 *			Output is commonly used as a dissimilarity matrix in clustering or multidimensional scailing.
	 *	@return	Pairwise distance.
	 */
	vec pdist(const mat& X, distance_type type = euclidean, pdist_func func_ptr = nullptr)
	{
		const uword m = X.n_rows;
		vec Y(m * (m - 1) / 2);
		double* ptr = Y.memptr();

		switch (type) {
		case euclidean:
			func_ptr = pdist_euclidean;
			break;
		case custom:
			// stub
			break;
		default:
			func_ptr = &pdist_euclidean;
		}

		uword k = 0;
		for (uword i = 0 ; i < m ; i++)
			for (uword j = i + 1 ; j < m ; j++)
				ptr[k++] = func_ptr(X.row(i), X.row(j)); //sqrt(sum(square(X.row(j) - X.row(i))));

		return Y;
	}
}<|endoftext|>


<commit_before>#include "openmc/tallies/tally_filter.h"

#include <string>

#include "openmc/constants.h"  // for MAX_LINE_LEN;
#include "openmc/tallies/tally_filter_azimuthal.h"
#include "openmc/tallies/tally_filter_cell.h"
#include "openmc/tallies/tally_filter_cellborn.h"
#include "openmc/tallies/tally_filter_cellfrom.h"
#include "openmc/tallies/tally_filter_distribcell.h"
#include "openmc/tallies/tally_filter_legendre.h"
#include "openmc/tallies/tally_filter_material.h"
#include "openmc/tallies/tally_filter_mesh.h"
#include "openmc/tallies/tally_filter_meshsurface.h"
#include "openmc/tallies/tally_filter_mu.h"
#include "openmc/tallies/tally_filter_polar.h"
#include "openmc/tallies/tally_filter_sph_harm.h"
#include "openmc/tallies/tally_filter_surface.h"
#include "openmc/tallies/tally_filter_universe.h"

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

std::vector<TallyFilterMatch> filter_matches;
std::vector<TallyFilter*> tally_filters;

//==============================================================================
// Non-member functions
//==============================================================================

void
free_memory_tally_c()
{
  #pragma omp parallel
  {
    filter_matches.clear();
  }

  for (TallyFilter* filt : tally_filters) {delete filt;}
  tally_filters.clear();
}

//==============================================================================
// Fortran compatibility functions
//==============================================================================

extern "C" {
  TallyFilterMatch* filter_match_pointer(int indx)
  {return &filter_matches[indx];}

  void
  filter_match_bins_push_back(TallyFilterMatch* match, int val)
  {match->bins.push_back(val);}

  void
  filter_match_weights_push_back(TallyFilterMatch* match, double val)
  {match->weights.push_back(val);}

  void
  filter_match_bins_clear(TallyFilterMatch* match)
  {match->bins.clear();}

  void
  filter_match_weights_clear(TallyFilterMatch* match)
  {match->weights.clear();}

  int
  filter_match_bins_size(TallyFilterMatch* match)
  {return match->bins.size();}

  int
  filter_match_bins_data(TallyFilterMatch* match, int indx)
  {return match->bins.at(indx-1);}

  double
  filter_match_weights_data(TallyFilterMatch* match, int indx)
  {return match->weights.at(indx-1);}

  void
  filter_match_bins_set_data(TallyFilterMatch* match, int indx, int val)
  {match->bins.at(indx-1) = val;}

  TallyFilter*
  allocate_filter(const char* type)
  {
    std::string type_ {type};
    if (type_ == "azimuthal") {
      tally_filters.push_back(new AzimuthalFilter());
    } else if (type_ == "cell") {
      tally_filters.push_back(new CellFilter());
    } else if (type_ == "cellborn") {
      tally_filters.push_back(new CellbornFilter());
    } else if (type_ == "cellfrom") {
      tally_filters.push_back(new CellFromFilter());
    } else if (type_ == "distribcell") {
      tally_filters.push_back(new DistribcellFilter());
    } else if (type_ == "legendre") {
      tally_filters.push_back(new LegendreFilter());
    } else if (type_ == "material") {
      tally_filters.push_back(new MaterialFilter());
    } else if (type_ == "mesh") {
      tally_filters.push_back(new MeshFilter());
    } else if (type_ == "meshsurface") {
      tally_filters.push_back(new MeshSurfaceFilter());
    } else if (type_ == "mu") {
      tally_filters.push_back(new MuFilter());
    } else if (type_ == "polar") {
      tally_filters.push_back(new PolarFilter());
    } else if (type_ == "surface") {
      tally_filters.push_back(new SurfaceFilter());
    } else if (type_ == "sphericalharmonics") {
      tally_filters.push_back(new SphericalHarmonicsFilter());
    } else if (type_ == "universe") {
      tally_filters.push_back(new UniverseFilter());
    } else {
      return nullptr;
    }
    return tally_filters.back();
  }

  void filter_from_xml(TallyFilter* filt, pugi::xml_node* node)
  {filt->from_xml(*node);}

  void
  filter_get_all_bins(TallyFilter* filt, Particle* p, int estimator,
                      TallyFilterMatch* match)
  {
    filt->get_all_bins(p, estimator, *match);
  }

  void filter_to_statepoint(TallyFilter* filt, hid_t group)
  {filt->to_statepoint(group);}

  void filter_text_label(TallyFilter* filt, int bin, char* label)
  {
    std::string label_str = filt->text_label(bin);
    int i = 0;
    for (; i < label_str.size() && i < MAX_LINE_LEN; i++)
      label[i] = label_str[i];
    label[i] = '\0';
  }

  void filter_initialize(TallyFilter* filt) {filt->initialize();}

  int filter_n_bins(TallyFilter* filt) {return filt->n_bins_;}

  void
  cell_filter_get_bins(CellFilter* filt, int32_t** cells, int32_t* n)
  {
    *cells = filt->cells_.data();
    *n = filt->cells_.size();
  }

  int legendre_filter_get_order(LegendreFilter* filt)
  {return filt->order_;}

  void legendre_filter_set_order(LegendreFilter* filt, int order)
  {filt->order_ = order;}

  void
  material_filter_get_bins(MaterialFilter* filt, int32_t** bins, int32_t* n)
  {
    *bins = filt->materials_.data();
    *n = filt->materials_.size();
  }

  void
  material_filter_set_bins(MaterialFilter* filt, int32_t n, int32_t* bins)
  {
    filt->materials_.clear();
    filt->materials_.resize(n);
    for (int i = 0; i < n; i++) filt->materials_[i] = bins[i];
    filt->n_bins_ = filt->materials_.size();
    filt->map_.clear();
    for (int i = 0; i < n; i++) filt->map_[filt->materials_[i]] = i;
  }

  int mesh_filter_get_mesh(MeshFilter* filt) {return filt->mesh_;}

  void
  mesh_filter_set_mesh(MeshFilter* filt, int mesh)
  {
    filt->mesh_ = mesh;
    filt->n_bins_ = 1;
    for (auto dim : meshes[mesh]->shape_) filt->n_bins_ *= dim;
  }

  int meshsurface_filter_get_mesh(MeshSurfaceFilter* filt) {return filt->mesh_;}

  void
  meshsurface_filter_set_mesh(MeshSurfaceFilter* filt, int mesh)
  {
    filt->mesh_ = mesh;
    filt->n_bins_ = 4 * meshes[mesh]->n_dimension_;
    for (auto dim : meshes[mesh]->shape_) filt->n_bins_ *= dim;
  }

  int sphharm_filter_get_order(SphericalHarmonicsFilter* filt)
  {return filt->order_;}

  int sphharm_filter_get_cosine(SphericalHarmonicsFilter* filt)
  {return static_cast<int>(filt->cosine_);}

  void
  sphharm_filter_set_order(SphericalHarmonicsFilter* filt, int order)
  {
    filt->order_ = order;
    filt->n_bins_ = (order + 1) * (order + 1);
  }

  void sphharm_filter_set_cosine(SphericalHarmonicsFilter* filt, int cosine)
  {filt->cosine_ = static_cast<SphericalHarmonicsCosine>(cosine);}
}

} // namespace openmc
<commit_msg>Fix legendre_filter_set_order<commit_after>#include "openmc/tallies/tally_filter.h"

#include <string>

#include "openmc/constants.h"  // for MAX_LINE_LEN;
#include "openmc/tallies/tally_filter_azimuthal.h"
#include "openmc/tallies/tally_filter_cell.h"
#include "openmc/tallies/tally_filter_cellborn.h"
#include "openmc/tallies/tally_filter_cellfrom.h"
#include "openmc/tallies/tally_filter_distribcell.h"
#include "openmc/tallies/tally_filter_legendre.h"
#include "openmc/tallies/tally_filter_material.h"
#include "openmc/tallies/tally_filter_mesh.h"
#include "openmc/tallies/tally_filter_meshsurface.h"
#include "openmc/tallies/tally_filter_mu.h"
#include "openmc/tallies/tally_filter_polar.h"
#include "openmc/tallies/tally_filter_sph_harm.h"
#include "openmc/tallies/tally_filter_surface.h"
#include "openmc/tallies/tally_filter_universe.h"

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

std::vector<TallyFilterMatch> filter_matches;
std::vector<TallyFilter*> tally_filters;

//==============================================================================
// Non-member functions
//==============================================================================

void
free_memory_tally_c()
{
  #pragma omp parallel
  {
    filter_matches.clear();
  }

  for (TallyFilter* filt : tally_filters) {delete filt;}
  tally_filters.clear();
}

//==============================================================================
// Fortran compatibility functions
//==============================================================================

extern "C" {
  TallyFilterMatch* filter_match_pointer(int indx)
  {return &filter_matches[indx];}

  void
  filter_match_bins_push_back(TallyFilterMatch* match, int val)
  {match->bins.push_back(val);}

  void
  filter_match_weights_push_back(TallyFilterMatch* match, double val)
  {match->weights.push_back(val);}

  void
  filter_match_bins_clear(TallyFilterMatch* match)
  {match->bins.clear();}

  void
  filter_match_weights_clear(TallyFilterMatch* match)
  {match->weights.clear();}

  int
  filter_match_bins_size(TallyFilterMatch* match)
  {return match->bins.size();}

  int
  filter_match_bins_data(TallyFilterMatch* match, int indx)
  {return match->bins.at(indx-1);}

  double
  filter_match_weights_data(TallyFilterMatch* match, int indx)
  {return match->weights.at(indx-1);}

  void
  filter_match_bins_set_data(TallyFilterMatch* match, int indx, int val)
  {match->bins.at(indx-1) = val;}

  TallyFilter*
  allocate_filter(const char* type)
  {
    std::string type_ {type};
    if (type_ == "azimuthal") {
      tally_filters.push_back(new AzimuthalFilter());
    } else if (type_ == "cell") {
      tally_filters.push_back(new CellFilter());
    } else if (type_ == "cellborn") {
      tally_filters.push_back(new CellbornFilter());
    } else if (type_ == "cellfrom") {
      tally_filters.push_back(new CellFromFilter());
    } else if (type_ == "distribcell") {
      tally_filters.push_back(new DistribcellFilter());
    } else if (type_ == "legendre") {
      tally_filters.push_back(new LegendreFilter());
    } else if (type_ == "material") {
      tally_filters.push_back(new MaterialFilter());
    } else if (type_ == "mesh") {
      tally_filters.push_back(new MeshFilter());
    } else if (type_ == "meshsurface") {
      tally_filters.push_back(new MeshSurfaceFilter());
    } else if (type_ == "mu") {
      tally_filters.push_back(new MuFilter());
    } else if (type_ == "polar") {
      tally_filters.push_back(new PolarFilter());
    } else if (type_ == "surface") {
      tally_filters.push_back(new SurfaceFilter());
    } else if (type_ == "sphericalharmonics") {
      tally_filters.push_back(new SphericalHarmonicsFilter());
    } else if (type_ == "universe") {
      tally_filters.push_back(new UniverseFilter());
    } else {
      return nullptr;
    }
    return tally_filters.back();
  }

  void filter_from_xml(TallyFilter* filt, pugi::xml_node* node)
  {filt->from_xml(*node);}

  void
  filter_get_all_bins(TallyFilter* filt, Particle* p, int estimator,
                      TallyFilterMatch* match)
  {
    filt->get_all_bins(p, estimator, *match);
  }

  void filter_to_statepoint(TallyFilter* filt, hid_t group)
  {filt->to_statepoint(group);}

  void filter_text_label(TallyFilter* filt, int bin, char* label)
  {
    std::string label_str = filt->text_label(bin);
    int i = 0;
    for (; i < label_str.size() && i < MAX_LINE_LEN; i++)
      label[i] = label_str[i];
    label[i] = '\0';
  }

  void filter_initialize(TallyFilter* filt) {filt->initialize();}

  int filter_n_bins(TallyFilter* filt) {return filt->n_bins_;}

  void
  cell_filter_get_bins(CellFilter* filt, int32_t** cells, int32_t* n)
  {
    *cells = filt->cells_.data();
    *n = filt->cells_.size();
  }

  int legendre_filter_get_order(LegendreFilter* filt)
  {return filt->order_;}

  void
  legendre_filter_set_order(LegendreFilter* filt, int order)
  {
    filt->order_ = order;
    filt->n_bins_ = order + 1;
  }

  void
  material_filter_get_bins(MaterialFilter* filt, int32_t** bins, int32_t* n)
  {
    *bins = filt->materials_.data();
    *n = filt->materials_.size();
  }

  void
  material_filter_set_bins(MaterialFilter* filt, int32_t n, int32_t* bins)
  {
    filt->materials_.clear();
    filt->materials_.resize(n);
    for (int i = 0; i < n; i++) filt->materials_[i] = bins[i];
    filt->n_bins_ = filt->materials_.size();
    filt->map_.clear();
    for (int i = 0; i < n; i++) filt->map_[filt->materials_[i]] = i;
  }

  int mesh_filter_get_mesh(MeshFilter* filt) {return filt->mesh_;}

  void
  mesh_filter_set_mesh(MeshFilter* filt, int mesh)
  {
    filt->mesh_ = mesh;
    filt->n_bins_ = 1;
    for (auto dim : meshes[mesh]->shape_) filt->n_bins_ *= dim;
  }

  int meshsurface_filter_get_mesh(MeshSurfaceFilter* filt) {return filt->mesh_;}

  void
  meshsurface_filter_set_mesh(MeshSurfaceFilter* filt, int mesh)
  {
    filt->mesh_ = mesh;
    filt->n_bins_ = 4 * meshes[mesh]->n_dimension_;
    for (auto dim : meshes[mesh]->shape_) filt->n_bins_ *= dim;
  }

  int sphharm_filter_get_order(SphericalHarmonicsFilter* filt)
  {return filt->order_;}

  int sphharm_filter_get_cosine(SphericalHarmonicsFilter* filt)
  {return static_cast<int>(filt->cosine_);}

  void
  sphharm_filter_set_order(SphericalHarmonicsFilter* filt, int order)
  {
    filt->order_ = order;
    filt->n_bins_ = (order + 1) * (order + 1);
  }

  void sphharm_filter_set_cosine(SphericalHarmonicsFilter* filt, int cosine)
  {filt->cosine_ = static_cast<SphericalHarmonicsCosine>(cosine);}
}

} // namespace openmc
<|endoftext|>


<commit_before>#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdlib>
#include <vector>

#include "../slitherlink/SlitherlinkDatabase.h"
#include "../slitherlink/SlitherlinkDatabaseMethod.hpp"
#include "../slitherlink/SlitherlinkField.h"
#include "../slitherlink/SlitherlinkProblem.h"
#include "Test.h"

namespace Penciloid
{
void PenciloidTest::SlitherlinkClueTest(int height, int width, std::vector<const char*> board, int expected_status, int test_id = -1)
{
	SlitherlinkField field;
	field.Init(height, width);

	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			char clue = board[y * 2 + 1][x * 2 + 1];
			if ('0' <= clue && clue <= '3') field.SetClue(y, x, clue - '0');
		}
	}

	field.CheckAll();

	bool is_status_ok = true;
	if (expected_status == SolverStatus::NORMAL && field.GetStatus() != expected_status) is_status_ok = false;
	if (expected_status == SolverStatus::SUCCESS && field.GetStatus() != expected_status) is_status_ok = false;
	if (expected_status == SolverStatus::INCONSISTENT && (field.GetStatus() & SolverStatus::INCONSISTENT) == 0) is_status_ok = false;

	if (!is_status_ok) {
		std::cerr << "SlitherlinkClueTest failed in test #" << test_id << std::endl;
		std::cerr << "expected: " << expected_status << ", actual: " << field.GetStatus() << " (field status)" << std::endl;
	}

	if (expected_status == SolverStatus::INCONSISTENT) return;

	for (int y = 0; y <= height * 2; ++y) {
		for (int x = 0; x <= width * 2; ++x) {
			if (y % 2 == x % 2) continue; // this is not a segment

			int expected =
				board[y][x] == ' ' ? SlitherlinkField::LOOP_UNDECIDED :
				board[y][x] == 'x' ? SlitherlinkField::LOOP_BLANK : SlitherlinkField::LOOP_LINE;

			if (field.GetSegmentStyle(y, x) != expected) {
				std::cerr << "SlitherlinkClueTest failed in test #" << test_id << std::endl;
				std::cerr << "expected: " << expected << ", actual: " << field.GetSegmentStyle(y, x) << " at (" << y << "," << x << ")" << std::endl;
				exit(1);
			}
		}
	}
}

bool PenciloidTest::SlitherlinkCheckGrid(SlitherlinkField &field, const int *expected)
{
	int height = field.GetHeight() * 2 + 1, width = field.GetWidth() * 2 + 1;

	for (int i = 0; i < height; ++i) {
		for (int j = 0; j < width; ++j) {
			if (i % 2 != j % 2) {
				int expected_style = (expected[i * width + j] == 1) ? SlitherlinkField::LOOP_LINE : SlitherlinkField::LOOP_BLANK;
				if (field.GetSegmentStyle(i, j) != expected_style) return false;
			}
		}
	}

	return true;
}

void PenciloidTest::SlitherlinkFieldTestByProblems()
{
	for (int t = 0; t < 2; ++t) {
		// t: enable database or not
		// t is specified in test_id by adding t * 1000

		if (t == 0) {
			if (SlitherlinkDatabase::IsCreated()) SlitherlinkDatabase::ReleaseDatabase();
		} else if (t == 1) {
			if (!SlitherlinkDatabase::IsCreated()) SlitherlinkDatabase::CreateDatabase();
		}

		SlitherlinkClueTest(3, 3, {
			"+x+x+-+",
			"x0x2| |",
			"+x+-+x+",
			"x | x |",
			"+-+x+x+",
			"|3x1x |",
			"+-+-+-+",
		}, SolverStatus::SUCCESS, t * 1000 + 0);

		SlitherlinkClueTest(3, 3, {
			"+-+-+-+",
			"| x x |",
			"+x+-+x+",
			"|3|3| |",
			"+-+x+x+",
			"x x |3|",
			"+x+x+-+",
		}, SolverStatus::SUCCESS, t * 1000 + 1);

		// 2: closed loop test
		SlitherlinkClueTest(5, 3, {
			"+-+x+-+",
			"|3|3|3|",
			"+x+-+x+",
			"|2x2x2|",
			"+-+-+-+",
			"x x1x x",
			"+x+x+x+",
			"x x x x",
			"+x+x+x+",
			"x x x x",
			"+x+x+x+",
		}, SolverStatus::SUCCESS, t * 1000 + 2);

		// 3: closed loop (inconsistent) test
		SlitherlinkClueTest(5, 3, {
			"+ + + +",
			" 3 3 3 ",
			"+ + + +",
			" 2 2 2 ",
			"+ + + +",
			"       ",
			"+ + + +",
			"     2 ",
			"+ + + +",
			"       ",
			"+ + + +",
		}, SolverStatus::INCONSISTENT, t * 1000 + 3);

		// 1xx: diagonal chain test
		SlitherlinkClueTest(4, 4, {
			"+x+x+ + +",
			"x0x      ",
			"+x+ + + +",
			"x  2     ",
			"+ + +x+ +",
			"    x1   ",
			"+ + + + +",
			"         ",
			"+ + + + +",
		}, SolverStatus::NORMAL, t * 1000 + 100);

		SlitherlinkClueTest(4, 4, {
			"+x+x+ + +",
			"x0x      ",
			"+x+-+ + +",
			"x |2x    ",
			"+ +x+-+ +",
			"    |3   ",
			"+ + + + +",
			"         ",
			"+ + + + +",
		}, SolverStatus::NORMAL, t * 1000 + 101);

		if (t == 1) SlitherlinkDatabase::ReleaseDatabase();
	}
}

void PenciloidTest::SlitherlinkReducedDatabaseTest()
{
	if (SlitherlinkDatabase::IsCreated()) SlitherlinkDatabase::ReleaseDatabase();
	SlitherlinkDatabase::CreateReducedDatabase(SlitherlinkDatabaseMethod());

	SlitherlinkClueTest(4, 4, {
		"+x+ + + +",
		"x1       ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
	}, SolverStatus::NORMAL, 2000);

	SlitherlinkClueTest(4, 4, {
		"+ +-+ + +",
		" 2       ",
		"+ + + + +",
		"|        ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
	}, SolverStatus::NORMAL, 2001);

	SlitherlinkClueTest(4, 4, {
		"+-+ + + +",
		"|3       ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
	}, SolverStatus::NORMAL, 2002);

	SlitherlinkDatabase::ReleaseDatabase();
}
}<commit_msg>Add a test for line to 3<commit_after>#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdlib>
#include <vector>

#include "../slitherlink/SlitherlinkDatabase.h"
#include "../slitherlink/SlitherlinkDatabaseMethod.hpp"
#include "../slitherlink/SlitherlinkField.h"
#include "../slitherlink/SlitherlinkProblem.h"
#include "Test.h"

namespace Penciloid
{
void PenciloidTest::SlitherlinkClueTest(int height, int width, std::vector<const char*> board, int expected_status, int test_id = -1)
{
	SlitherlinkField field;
	field.Init(height, width);

	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			char clue = board[y * 2 + 1][x * 2 + 1];
			if ('0' <= clue && clue <= '3') field.SetClue(y, x, clue - '0');
		}
	}

	field.CheckAll();

	bool is_status_ok = true;
	if (expected_status == SolverStatus::NORMAL && field.GetStatus() != expected_status) is_status_ok = false;
	if (expected_status == SolverStatus::SUCCESS && field.GetStatus() != expected_status) is_status_ok = false;
	if (expected_status == SolverStatus::INCONSISTENT && (field.GetStatus() & SolverStatus::INCONSISTENT) == 0) is_status_ok = false;

	if (!is_status_ok) {
		std::cerr << "SlitherlinkClueTest failed in test #" << test_id << std::endl;
		std::cerr << "expected: " << expected_status << ", actual: " << field.GetStatus() << " (field status)" << std::endl;
	}

	if (expected_status == SolverStatus::INCONSISTENT) return;

	for (int y = 0; y <= height * 2; ++y) {
		for (int x = 0; x <= width * 2; ++x) {
			if (y % 2 == x % 2) continue; // this is not a segment

			int expected =
				board[y][x] == ' ' ? SlitherlinkField::LOOP_UNDECIDED :
				board[y][x] == 'x' ? SlitherlinkField::LOOP_BLANK : SlitherlinkField::LOOP_LINE;

			if (field.GetSegmentStyle(y, x) != expected) {
				std::cerr << "SlitherlinkClueTest failed in test #" << test_id << std::endl;
				std::cerr << "expected: " << expected << ", actual: " << field.GetSegmentStyle(y, x) << " at (" << y << "," << x << ")" << std::endl;
				exit(1);
			}
		}
	}
}

bool PenciloidTest::SlitherlinkCheckGrid(SlitherlinkField &field, const int *expected)
{
	int height = field.GetHeight() * 2 + 1, width = field.GetWidth() * 2 + 1;

	for (int i = 0; i < height; ++i) {
		for (int j = 0; j < width; ++j) {
			if (i % 2 != j % 2) {
				int expected_style = (expected[i * width + j] == 1) ? SlitherlinkField::LOOP_LINE : SlitherlinkField::LOOP_BLANK;
				if (field.GetSegmentStyle(i, j) != expected_style) return false;
			}
		}
	}

	return true;
}

void PenciloidTest::SlitherlinkFieldTestByProblems()
{
	for (int t = 0; t < 2; ++t) {
		// t: enable database or not
		// t is specified in test_id by adding t * 1000

		if (t == 0) {
			if (SlitherlinkDatabase::IsCreated()) SlitherlinkDatabase::ReleaseDatabase();
		} else if (t == 1) {
			if (!SlitherlinkDatabase::IsCreated()) SlitherlinkDatabase::CreateDatabase();
		}

		SlitherlinkClueTest(3, 3, {
			"+x+x+-+",
			"x0x2| |",
			"+x+-+x+",
			"x | x |",
			"+-+x+x+",
			"|3x1x |",
			"+-+-+-+",
		}, SolverStatus::SUCCESS, t * 1000 + 0);

		SlitherlinkClueTest(3, 3, {
			"+-+-+-+",
			"| x x |",
			"+x+-+x+",
			"|3|3| |",
			"+-+x+x+",
			"x x |3|",
			"+x+x+-+",
		}, SolverStatus::SUCCESS, t * 1000 + 1);

		// 2: closed loop test
		SlitherlinkClueTest(5, 3, {
			"+-+x+-+",
			"|3|3|3|",
			"+x+-+x+",
			"|2x2x2|",
			"+-+-+-+",
			"x x1x x",
			"+x+x+x+",
			"x x x x",
			"+x+x+x+",
			"x x x x",
			"+x+x+x+",
		}, SolverStatus::SUCCESS, t * 1000 + 2);

		// 3: closed loop (inconsistent) test
		SlitherlinkClueTest(5, 3, {
			"+ + + +",
			" 3 3 3 ",
			"+ + + +",
			" 2 2 2 ",
			"+ + + +",
			"       ",
			"+ + + +",
			"     2 ",
			"+ + + +",
			"       ",
			"+ + + +",
		}, SolverStatus::INCONSISTENT, t * 1000 + 3);

		// 1xx: diagonal chain test
		SlitherlinkClueTest(4, 4, {
			"+x+x+ + +",
			"x0x      ",
			"+x+ + + +",
			"x  2     ",
			"+ + +x+ +",
			"    x1   ",
			"+ + + + +",
			"         ",
			"+ + + + +",
		}, SolverStatus::NORMAL, t * 1000 + 100);

		SlitherlinkClueTest(4, 4, {
			"+x+x+ + +",
			"x0x      ",
			"+x+-+ + +",
			"x |2x    ",
			"+ +x+-+ +",
			"    |3   ",
			"+ + + + +",
			"         ",
			"+ + + + +",
		}, SolverStatus::NORMAL, t * 1000 + 101);

		if (t == 1) SlitherlinkDatabase::ReleaseDatabase();
	}
}

void PenciloidTest::SlitherlinkReducedDatabaseTest()
{
	if (SlitherlinkDatabase::IsCreated()) SlitherlinkDatabase::ReleaseDatabase();
	SlitherlinkDatabase::CreateReducedDatabase(SlitherlinkDatabaseMethod());

	SlitherlinkClueTest(4, 4, {
		"+x+ + + +",
		"x1       ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
	}, SolverStatus::NORMAL, 2000);

	SlitherlinkClueTest(4, 4, {
		"+ +-+ + +",
		" 2       ",
		"+ + + + +",
		"|        ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
	}, SolverStatus::NORMAL, 2001);

	SlitherlinkClueTest(4, 4, {
		"+-+ + + +",
		"|3       ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
		"         ",
		"+ + + + +",
	}, SolverStatus::NORMAL, 2002);

	SlitherlinkClueTest(4, 4, {
		"+x+x+-+ +",
		"x0x2|    ",
		"+x+-+x+ +",
		"x | x    ",
		"+x+ + + +",
		"x  3|    ",
		"+ +-+x+ +",
		"    x    ",
		"+ + + + +",
	}, SolverStatus::NORMAL, 2002);

	SlitherlinkDatabase::ReleaseDatabase();
}
}<|endoftext|>