<commit_before>#include <boost/thread/thread.hpp>

#include "tcp_session_stream_model.h"

namespace l7vs{

	//! construcor
	tcp_session_stream_model::tcp_session_stream_model(boost::asio::io_service& io,boost::asio::ip::tcp::endpoint rs_endpoint):
		cl_socket(io),
                rs_socket(io),
                threadA_state(0),
                threadB_state(0),
                realserver_endpoint(rs_endpoint),
                exit_flag(false){
	}

	//! destructor
	tcp_session_stream_model::~tcp_session_stream_model(){
	}

        boost::asio::ip::tcp::socket& tcp_session_stream_model::get_cl_socket(){
                return cl_socket;
        }

        void tcp_session_stream_model::Run_up(){
                boost::array< char , 65535> buff;
                boost::system::error_code ec;

                {
                        rw_scoped_lock scope_lock(threadA_state_mutex);
                        threadA_state = 1;
                }

                //DWスレッド待機
                while(true){
                        {
                                rd_scoped_lock scope_lock(threadB_state_mutex);
                                if(threadB_state == 1){
                                        break;
                                }
                        }
                        boost::this_thread::yield();
                }

                // ノンブロッキングに設定
                boost::asio::socket_base::non_blocking_io cmd(true);
                cl_socket.io_control(cmd,ec);
                if(ec){
                        //ノンブロッキング設定失敗 -> 終了のお知らせ
                        rw_scoped_lock scope_lock(exit_flag_update_mutex);
                        exit_flag = true;
                }

                while(true){// UPスレッドメインループ
                        {
				rd_scoped_lock scope_lock(exit_flag_update_mutex);
                                if(exit_flag){
                                        //終了のお知らせ
                                        break;
                                }
                        }

                        boost::this_thread::yield();
                        // 受信
                        size_t recv_size = 0;
                        {
                                rd_scoped_lock scope_lock(cl_close_mutex);
                                recv_size = cl_socket.read_some(boost::asio::buffer(buff.data(),65535), ec);
                        }
                        if(ec){
                                // 受信エラー
                                if(ec == boost::asio::error::try_again){
                                        continue;
                                }else{
                                        //受信失敗終了のお知らせ
                                        rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                        exit_flag = true;
                                        break;
                                }
                        }

                        // RS接続チェック
                        if(!rs_socket.is_open()){
                                //RS接続
                                {
                                        rw_scoped_lock scope_lock(rs_close_mutex);
                                        if(!rs_socket.connect(realserver_endpoint,ec)){
                                                //接続失敗 -> 終了のお知らせ
                                                rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                                exit_flag = true;
                                                break;
                                        }
                                }
                                // ノンブロッキングに設定
                                boost::asio::socket_base::non_blocking_io cmd(true);
                                rs_socket.io_control(cmd,ec);
                                if(ec){
                                        //ノンブロッキング設定失敗 -> 終了のお知らせ
                                        rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                        exit_flag = true;
                                        break;
                                }
                        }

                        // 送信
                        size_t send_size = 0;
                        while(send_size < recv_size){
                                size_t ret_size = 0;
                                {
                                        rd_scoped_lock scope_lock(rs_close_mutex);
                                        ret_size = rs_socket.write_some(boost::asio::buffer(buff.data() + send_size,recv_size - send_size), ec);
                                }
                                if(!ec){
                                // 送信成功
                                        send_size += ret_size;
                                }else{
                                        if( ec != boost::asio::error::try_again ){
                                                //送信失敗 -> 終了のお知らせ
                                                rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                                exit_flag = true;
                                                break;
                                        }
                                }
                                boost::this_thread::yield();
                        }
                }

                // クローズ
                {
                        rw_scoped_lock scope_lock(cl_close_mutex);
                        cl_socket.close(ec);
                }

                //DWスレッド待機
               while(true){
                        {
                                rd_scoped_lock scope_lock(threadB_state_mutex);
                                if(threadB_state == 0){
                                        break;
                                }
                        }
                        boost::this_thread::yield();
                }
                exit_flag = false;
        }

        void tcp_session_stream_model::Run_dw(){
                boost::array< char , 65535> buff;
                boost::system::error_code ec;

                {
                        rw_scoped_lock scope_lock(threadB_state_mutex);
                        threadB_state = 1;
                }
                //UPスレッド待機
                while(true){
                        {
                                rd_scoped_lock scope_lock(threadA_state_mutex);
                                if(threadA_state == 1){
                                        break;
                                }
                        }
                        boost::this_thread::yield();
                }

                while(true){// DWスレッドメインループ
                        {
				rd_scoped_lock scope_lock(exit_flag_update_mutex);
                                if(exit_flag){
                                        //終了のお知らせ
                                        break;
                                }
                        }
                        boost::this_thread::yield();

                        // RS接続チェック
                        if(!rs_socket.is_open()){
                                continue;
                        }

                        // RS受信
                        size_t recv_size = 0;
                        {
                                rd_scoped_lock scope_lock(rs_close_mutex);
                                recv_size = rs_socket.read_some(boost::asio::buffer(buff.data(),65535), ec);
                        }
                        if(ec){
                                // 受信エラー
                                if(ec == boost::asio::error::try_again){
                                        continue;
                                }else{
                                        //受信失敗終了のお知らせ
                                        rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                        exit_flag = true;
                                        break;
                                }
                        }

                        // CL送信
                        size_t send_size = 0;
                        while(send_size < recv_size){
                                size_t ret_size = 0;
                                {
                                        rd_scoped_lock scope_lock(cl_close_mutex);
                                        ret_size = cl_socket.write_some(boost::asio::buffer(buff.data() + send_size,recv_size - send_size), ec);
                                }
                                if(!ec){
                                // 送信成功
                                        send_size += ret_size;
                                }else{
                                        if( ec != boost::asio::error::try_again ){
                                                //送信失敗 -> 終了のお知らせ
                                                rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                                exit_flag = true;
                                                break;
                                        }
                                }
                                boost::this_thread::yield();
                        }
                }

                // クローズ
                {
                        rw_scoped_lock scope_lock(rs_close_mutex);
                        rs_socket.close(ec);
                }
                {
                        rw_scoped_lock scope_lock(threadB_state_mutex);
                        threadB_state = 0;
                }

        }
}
<commit_msg>バグ修正<commit_after>#include <boost/thread/thread.hpp>

#include "tcp_session_stream_model.h"

namespace l7vs{

	//! construcor
	tcp_session_stream_model::tcp_session_stream_model(boost::asio::io_service& io,boost::asio::ip::tcp::endpoint rs_endpoint):
		cl_socket(io),
                rs_socket(io),
                threadA_state(0),
                threadB_state(0),
                realserver_endpoint(rs_endpoint),
                exit_flag(false){
	}

	//! destructor
	tcp_session_stream_model::~tcp_session_stream_model(){
	}

        boost::asio::ip::tcp::socket& tcp_session_stream_model::get_cl_socket(){
                return cl_socket;
        }

        void tcp_session_stream_model::Run_up(){

                boost::array< char , 65535> buff;
                boost::system::error_code ec;

                {
                        rw_scoped_lock scope_lock(threadA_state_mutex);
                        threadA_state = 1;
                }

                //DWスレッド待機
                while(true){
                        {
                                rd_scoped_lock scope_lock(threadB_state_mutex);
                                if(threadB_state == 1){
                                        break;
                                }
                        }
                        boost::this_thread::yield();
                }

                // ノンブロッキングに設定
                boost::asio::socket_base::non_blocking_io cmd(true);
                cl_socket.io_control(cmd,ec);
                if(ec){
                        //ノンブロッキング設定失敗 -> 終了のお知らせ
                        rw_scoped_lock scope_lock(exit_flag_update_mutex);
                        exit_flag = true;
                }

                while(true){// UPスレッドメインループ
                        boost::this_thread::yield();
                        {
				rd_scoped_lock scope_lock(exit_flag_update_mutex);
                                if(exit_flag){
                                        //終了のお知らせ
                                        break;
                                }
                        }

                        // 受信
                        size_t recv_size = 0;
                        {
                                rd_scoped_lock scope_lock(cl_close_mutex);
                                recv_size = cl_socket.read_some(boost::asio::buffer(buff.data(),65535), ec);
                        }
                        if(ec){
                                // 受信エラー
                                if(ec == boost::asio::error::try_again){
                                        continue;
                                }else{
                                        //受信失敗終了のお知らせ
                                        rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                        exit_flag = true;
                                        break;
                                }
                        }

                        // RS接続チェック
                        if(!rs_socket.is_open()){
                                //RS接続
                                {
                                        rw_scoped_lock scope_lock(rs_close_mutex);
                                        rs_socket.connect(realserver_endpoint,ec);
                                        if(ec){
                                                //接続失敗 -> 終了のお知らせ
                                                rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                                exit_flag = true;
                                                break;
                                        }
                                }
                                // ノンブロッキングに設定
                                boost::asio::socket_base::non_blocking_io cmd(true);
                                rs_socket.io_control(cmd,ec);
                                if(ec){
                                        //ノンブロッキング設定失敗 -> 終了のお知らせ
                                        rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                        exit_flag = true;
                                        break;
                                }

                        }

                        // 送信
                        size_t send_size = 0;
                        while(send_size < recv_size){
                                size_t ret_size = 0;
                                {
                                        rd_scoped_lock scope_lock(rs_close_mutex);
                                        ret_size = rs_socket.write_some(boost::asio::buffer(buff.data() + send_size,recv_size - send_size), ec);
                                }
                                if(!ec){
                                // 送信成功
                                        send_size += ret_size;
                                }else{
                                        if( ec != boost::asio::error::try_again ){
                                                //送信失敗 -> 終了のお知らせ
                                                rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                                exit_flag = true;
                                                break;
                                        }
                                }
                                boost::this_thread::yield();
                        }
                }

                // クローズ
                {
                        rw_scoped_lock scope_lock(cl_close_mutex);
                        cl_socket.close(ec);
                }

                //DWスレッド待機
               while(true){
                        {
                                rd_scoped_lock scope_lock(threadB_state_mutex);
                                if(threadB_state == 0){
                                        break;
                                }
                        }
                        boost::this_thread::yield();
                }
                exit_flag = false;
        }

        void tcp_session_stream_model::Run_dw(){
                boost::array< char , 65535> buff;
                boost::system::error_code ec;

                {
                        rw_scoped_lock scope_lock(threadB_state_mutex);
                        threadB_state = 1;
                }
                //UPスレッド待機
                while(true){
                        {
                                rd_scoped_lock scope_lock(threadA_state_mutex);
                                if(threadA_state == 1){
                                        break;
                                }
                        }
                        boost::this_thread::yield();
                }
                while(true){// DWスレッドメインループ
                        boost::this_thread::yield();
                        {
				rd_scoped_lock scope_lock(exit_flag_update_mutex);
                                if(exit_flag == true){
                                        //終了のお知らせ
                                        break;
                                }
                        }

                        // RS接続チェック
                        if(!rs_socket.is_open()){
                                continue;
                        }
                        // RS受信
                        size_t recv_size = 0;
                        {
                                rd_scoped_lock scope_lock(rs_close_mutex);
                                recv_size = rs_socket.read_some(boost::asio::buffer(buff.data(),65535), ec);
                        }
                        if(ec){
                                // 受信エラー
                                if(ec == boost::asio::error::try_again){
                                        continue;
                                }else{
                                        //受信失敗終了のお知らせ
                                        rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                        exit_flag = true;
                                        break;
                                }
                        }
                        // CL送信
                        size_t send_size = 0;
                        while(send_size < recv_size){
                                size_t ret_size = 0;
                                {
                                        rd_scoped_lock scope_lock(cl_close_mutex);
                                        ret_size = cl_socket.write_some(boost::asio::buffer(buff.data() + send_size,recv_size - send_size), ec);
                                }
                                if(!ec){
                                // 送信成功
                                        send_size += ret_size;
                                }else{
                                        if( ec != boost::asio::error::try_again ){
                                                //送信失敗 -> 終了のお知らせ
                                                rw_scoped_lock scope_lock(exit_flag_update_mutex);
                                                exit_flag = true;
                                                break;
                                        }
                                }
                                boost::this_thread::yield();
                        }
                }

                // クローズ
                {
                        rw_scoped_lock scope_lock(rs_close_mutex);
                        rs_socket.close(ec);
                }
                {
                        rw_scoped_lock scope_lock(threadB_state_mutex);
                        threadB_state = 0;
                }
        }
}
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/java/src/main/native/server_jni.h"
#include "tensorflow/c/c_api.h"
#include "tensorflow/java/src/main/native/exception_jni.h"
#include "tensorflow/java/src/main/native/utils_jni.h"

namespace {
TF_Server* requireHandle(JNIEnv* env, jlong handle) {
  static_assert(sizeof(jlong) >= sizeof(TF_Server*),
                "Cannot package C object pointers as a Java long");
  if (handle == 0) {
    throwException(env, kIllegalStateException,
                   "close() has been called on the Server");
    return nullptr;
  }

  return reinterpret_cast<TF_Server*>(handle);
}

}  // namespace

JNIEXPORT jlong JNICALL Java_org_tensorflow_Server_allocate(
    JNIEnv* env, jclass clazz, jbyteArray server_def) {
  TF_Status* status = TF_NewStatus();

  jbyte* server_def_ptr = env->GetByteArrayElements(server_def, nullptr);

  TF_Server* server = TF_NewServer(
      server_def_ptr, static_cast<size_t>(env->GetArrayLength(server_def)),
      status);

  env->ReleaseByteArrayElements(server_def, server_def_ptr, JNI_ABORT);
  bool ok = throwExceptionIfNotOK(env, status);

  TF_DeleteStatus(status);

  return ok ? reinterpret_cast<jlong>(server) : 0;
}

JNIEXPORT void JNICALL Java_org_tensorflow_Server_start(JNIEnv* env,
                                                        jclass clazz,
                                                        jlong handle) {
  TF_Status* status = TF_NewStatus();
  TF_Server* server = requireHandle(env, handle);
  if (server == nullptr) return;

  TF_ServerStart(server, status);
  throwExceptionIfNotOK(env, status);

  TF_DeleteStatus(status);
}

JNIEXPORT void JNICALL Java_org_tensorflow_Server_stop(JNIEnv* env,
                                                       jclass clazz,
                                                       jlong handle) {
  TF_Status* status = TF_NewStatus();
  TF_Server* server = requireHandle(env, handle);
  if (server == nullptr) return;

  TF_ServerStop(server, status);
  throwExceptionIfNotOK(env, status);

  TF_DeleteStatus(status);
}

JNIEXPORT void JNICALL Java_org_tensorflow_Server_join(JNIEnv* env,
                                                       jclass clazz,
                                                       jlong handle) {
  TF_Status* status = TF_NewStatus();
  TF_Server* server = requireHandle(env, handle);
  if (server == nullptr) return;

  TF_ServerJoin(server, status);
  throwExceptionIfNotOK(env, status);

  TF_DeleteStatus(status);
}

JNIEXPORT void JNICALL Java_org_tensorflow_Server_delete(JNIEnv* env,
                                                         jclass clazz,
                                                         jlong handle) {
  TF_Server* server = requireHandle(env, handle);
  if (server == nullptr) return;

  TF_DeleteServer(server);
}
<commit_msg>Update after review.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/java/src/main/native/server_jni.h"
#include "tensorflow/c/c_api.h"
#include "tensorflow/java/src/main/native/exception_jni.h"
#include "tensorflow/java/src/main/native/utils_jni.h"

namespace {
TF_Server* requireHandle(JNIEnv* env, jlong handle) {
  static_assert(sizeof(jlong) >= sizeof(TF_Server*),
                "Cannot package C object pointers as a Java long");
  if (handle == 0) {
    throwException(env, kIllegalStateException,
                   "close() has been called on the Server");
    return nullptr;
  }

  return reinterpret_cast<TF_Server*>(handle);
}

}  // namespace

JNIEXPORT jlong JNICALL Java_org_tensorflow_Server_allocate(
    JNIEnv* env, jclass clazz, jbyteArray server_def) {
  TF_Status* status = TF_NewStatus();

  jbyte* server_def_ptr = env->GetByteArrayElements(server_def, nullptr);

  TF_Server* server = TF_NewServer(
      server_def_ptr, static_cast<size_t>(env->GetArrayLength(server_def)),
      status);

  env->ReleaseByteArrayElements(server_def, server_def_ptr, JNI_ABORT);
  bool ok = throwExceptionIfNotOK(env, status);

  TF_DeleteStatus(status);

  return ok ? reinterpret_cast<jlong>(server) : 0;
}

JNIEXPORT void JNICALL Java_org_tensorflow_Server_start(JNIEnv* env,
                                                        jclass clazz,
                                                        jlong handle) {
  TF_Server* server = requireHandle(env, handle);
  if (server == nullptr) return;

  TF_Status* status = TF_NewStatus();

  TF_ServerStart(server, status);
  throwExceptionIfNotOK(env, status);

  TF_DeleteStatus(status);
}

JNIEXPORT void JNICALL Java_org_tensorflow_Server_stop(JNIEnv* env,
                                                       jclass clazz,
                                                       jlong handle) {
  TF_Server* server = requireHandle(env, handle);
  if (server == nullptr) return;

  TF_Status* status = TF_NewStatus();

  TF_ServerStop(server, status);
  throwExceptionIfNotOK(env, status);

  TF_DeleteStatus(status);
}

JNIEXPORT void JNICALL Java_org_tensorflow_Server_join(JNIEnv* env,
                                                       jclass clazz,
                                                       jlong handle) {
  TF_Server* server = requireHandle(env, handle);
  if (server == nullptr) return;

  TF_Status* status = TF_NewStatus();

  TF_ServerJoin(server, status);
  throwExceptionIfNotOK(env, status);

  TF_DeleteStatus(status);
}

JNIEXPORT void JNICALL Java_org_tensorflow_Server_delete(JNIEnv* env,
                                                         jclass clazz,
                                                         jlong handle) {
  TF_Server* server = requireHandle(env, handle);
  if (server == nullptr) return;

  TF_DeleteServer(server);
}
<|endoftext|>


<commit_before>#include "GraphML.h"

#include "UndirectedGraph.h"

#include <tinyxml2.h>
#include <Table.h>

#include <cassert>
#include <iostream>

using namespace std;
using namespace tinyxml2;

GraphML::GraphML() : FileTypeHandler("GraphML", true) {
  addExtension("graphml");
}

static void createColumn(table::Table & table, const char * type, const char * id) {
  if (strcmp(type, "string") == 0) {
    table.addCompressedTextColumn(id ? id : "");
  } else if (strcmp(type, "double") == 0 || strcmp(type, "float") == 0) {
    table.addDoubleColumn(id ? id : "");
  } else if (strcmp(type, "int") == 0) {
    table.addIntColumn(id ? id : "");
  } else {
    assert(0);
  }
}

std::shared_ptr<Graph>
GraphML::openGraph(const char * filename, const std::shared_ptr<NodeArray> & initial_nodes) {
  RenderMode mode = RENDERMODE_3D;

  XMLDocument doc;
  doc.LoadFile(filename);

  XMLElement * graphml_element = doc.FirstChildElement("graphml");
  assert(graphml_element);

  XMLElement * graph_element = graphml_element->FirstChildElement("graph");
  assert(graph_element);

  unordered_map<string, int> nodes_by_id;

  const char * edgedefault = graph_element->Attribute("edgedefault");
  bool directed = true;
  if (edgedefault && strcmp(edgedefault, "undirected") == 0) {
    directed = false;
  }
  std::shared_ptr<Graph> graph;
  if (directed) {
    graph = std::make_shared<Graph>();
    graph->setNodeArray(initial_nodes);
    graph->getNodeArray().setNodeSizeMethod(SizeMethod(SizeMethod::SIZE_FROM_INDEGREE));
  } else {
    graph = std::make_shared<UndirectedGraph>();
    graph->setNodeArray(initial_nodes);
    graph->getNodeArray().setNodeSizeMethod(SizeMethod(SizeMethod::SIZE_FROM_DEGREE));
  }
  graph->getNodeArray().setDynamic(true);
  graph->getNodeArray().setFlattenHierarchy(true);

  auto & node_table = graph->getNodeArray().getTable();
  auto & edge_table = graph->getFaceData();

  XMLElement * key_element = graphml_element->FirstChildElement("key");
  for ( ; key_element ; key_element = key_element->NextSiblingElement("key") ) {
    const char * key_type = key_element->Attribute("attr.type");
    const char * key_id = key_element->Attribute("id");
    const char * for_type = key_element->Attribute("for");
    // const char * name = key_element->Attribute("attr.name");

    assert(key_type && key_id && for_type);

    if (strcmp(for_type, "node") == 0) {
      createColumn(node_table, key_type, key_id);
    } else if (strcmp(for_type, "edge") == 0) {
      createColumn(edge_table, key_type, key_id);
    } else {
      assert(0);
    }
  }

  createGraphFromElement(*graph, *graphml_element, *graph_element, nodes_by_id, directed);

  graph->randomizeGeometry();
  // graph->setComplexGraph(is_complex);
  // graph->setHasSubGraphs(is_complex);

  return graph;
}

void
GraphML::createGraphFromElement(Graph & graph, XMLElement & graphml_element, XMLElement & graph_element, unordered_map<string, int> & nodes_by_id, bool is_directed, int parent_node_id) const {
  auto & node_table = graph.getNodeArray().getTable();
  auto & edge_table = graph.getFaceData();

  auto & node_id_column = node_table.addTextColumn("id");
  auto & edge_id_column = edge_table.addTextColumn("id");

  XMLElement * node_element = graph_element.FirstChildElement("node");
  for ( ; node_element ; node_element = node_element->NextSiblingElement("node") ) {
    const char * node_id_text = node_element->Attribute("id");
    assert(node_id_text);

    int node_id = graph.getNodeArray().add();
    node_id_column.pushValue(node_id_text);
    nodes_by_id[node_id_text] = node_id + 1;

    if (parent_node_id != -1) graph.addChild(parent_node_id, node_id);

    XMLElement * data_element = node_element->FirstChildElement("data");
    for ( ; data_element ; data_element = data_element->NextSiblingElement("data") ) {
      const char * key = data_element->Attribute("key");
      assert(key);
      const char * text = data_element->GetText();
      if (text) {
	node_table[key].setValue(node_id, text);
      }
    }

    XMLElement * nested_graph_element = node_element->FirstChildElement("graph");
    if (nested_graph_element) {
      createGraphFromElement(graph, graphml_element, *nested_graph_element, nodes_by_id, is_directed, node_id);
    }
  }

  XMLElement * edge_element = graph_element.FirstChildElement("edge");
  for ( ; edge_element ; edge_element = edge_element->NextSiblingElement("edge") ) {
    const char * edge_id_text = edge_element->Attribute("id");
    const char * source = edge_element->Attribute("source");
    const char * target = edge_element->Attribute("target");
    assert(source && target);

    if (strcmp(source, target) == 0) {
      cerr << "GraphML: skipping self link for " << source << endl;
      continue;
    }

    int source_node = nodes_by_id[source];
    int target_node = nodes_by_id[target];

    if (source_node && target_node) {
      int face_id = graph.addFace(-1);
      int edge_id1 = graph.addEdge(source_node - 1, target_node - 1, face_id);
      if (!is_directed) {
	int edge_id2 = graph.addEdge(target_node - 1, source_node - 1, face_id);
	graph.connectEdgePair(edge_id1, edge_id2);
      }

      if (edge_id_text && strlen(edge_id_text) != 0) {
	edge_id_column.setValue(face_id, edge_id_text);
      }

      XMLElement * data_element = edge_element->FirstChildElement("data");

      for ( ; data_element ; data_element = data_element->NextSiblingElement("data") ) {
	const char * key = data_element->Attribute("key");
	assert(key);
	const char * text = data_element->GetText();
	if (text) {
	  edge_table[key].setValue(face_id, text);
	}
      }
    } else {
      if (!source_node) {
	// cerr << "cannot find node " << source << endl;
      }
      if (!target_node) {
	// cerr << "cannot find node " << target << endl;
      }
    }
  }
}

bool
GraphML::saveGraph(const Graph & graph, const std::string & filename) {
  XMLDocument doc;
  doc.LinkEndChild(doc.NewDeclaration());

  XMLElement * graphml_element = doc.NewElement("graphml");
  graphml_element->SetAttribute("xmlns", "http://graphml.graphdrawing.org/xmlns");

  bool directed = graph.isDirected();
  auto & node_table = graph.getNodeArray().getTable();
  auto & edge_table = graph.getFaceData();

  for (auto & col : node_table.getColumns()) {
    XMLElement * key_element = doc.NewElement("key");
    key_element->SetAttribute("attr.name", col.first.c_str());
    key_element->SetAttribute("id", col.first.c_str());
    key_element->SetAttribute("attr.type", col.second->getTypeText());
    key_element->SetAttribute("for", "node");
    graphml_element->LinkEndChild(key_element);
  }

  for (auto & col : edge_table.getColumns()) {
    XMLElement * key_element = doc.NewElement("key");
    key_element->SetAttribute("attr.name", col.first.c_str());
    key_element->SetAttribute("id", col.first.c_str());
    key_element->SetAttribute("attr.type", col.second->getTypeText());
    key_element->SetAttribute("for", "edge");
    graphml_element->LinkEndChild(key_element);
  }

  XMLElement * graph_element = doc.NewElement("graph");
  graphml_element->LinkEndChild(graph_element);

  if (!directed) {
    graph_element->SetAttribute("edgedefault", "undirected");
  }

  for (unsigned int i = 0; i < graph.getNodeArray().size(); i++) {
    XMLElement * node_element = doc.NewElement("node");
    string node_id = "n" + to_string(i);
    node_element->SetAttribute("id", node_id.c_str());

    for (auto & col : node_table.getColumns()) {
      XMLElement * data_element = doc.NewElement("data");
      data_element->SetAttribute("key", col.first.c_str());
      data_element->LinkEndChild(doc.NewText(col.second->getText(i).c_str()));
      node_element->LinkEndChild(data_element);
    }

    graph_element->LinkEndChild(node_element);
  }

  for (unsigned int i = 0; i < graph.getFaceCount(); i++) {
    XMLElement * edge_element = doc.NewElement("edge");

#if 0
    auto edge = graph.getEdgeAttributes(i);
    string node_id1 = "n" + to_string(edge.tail);
    string node_id2 = "n" + to_string(edge.head);

    // timestamp, sentiment

    edge_element->SetAttribute("source", node_id1.c_str());
    edge_element->SetAttribute("target", node_id2.c_str());
#endif

    for (auto & col : edge_table.getColumns()) {
      XMLElement * data_element = doc.NewElement("data");
      data_element->SetAttribute("key", col.first.c_str());
      data_element->LinkEndChild(doc.NewText(col.second->getText(i).c_str()));
      edge_element->LinkEndChild(data_element);
    }

    graph_element->LinkEndChild(edge_element);
  }

  doc.LinkEndChild(graphml_element);
  doc.SaveFile(filename.c_str());

  return true;
}
<commit_msg>add fixed type<commit_after>#include "GraphML.h"

#include "UndirectedGraph.h"

#include <tinyxml2.h>
#include <Table.h>

#include <cassert>
#include <iostream>

using namespace std;
using namespace tinyxml2;

GraphML::GraphML() : FileTypeHandler("GraphML", true) {
  addExtension("graphml");
}

static void createColumn(table::Table & table, const char * type, const char * id) {
  if (strcmp(type, "string") == 0) {
    table.addCompressedTextColumn(id ? id : "");
  } else if (strcmp(type, "double") == 0 || strcmp(type, "float") == 0) {
    table.addDoubleColumn(id ? id : "");
  } else if (strcmp(type, "int") == 0) {
    table.addIntColumn(id ? id : "");
  } else {
    assert(0);
  }
}

std::shared_ptr<Graph>
GraphML::openGraph(const char * filename, const std::shared_ptr<NodeArray> & initial_nodes) {
  RenderMode mode = RENDERMODE_3D;

  XMLDocument doc;
  doc.LoadFile(filename);

  XMLElement * graphml_element = doc.FirstChildElement("graphml");
  assert(graphml_element);

  XMLElement * graph_element = graphml_element->FirstChildElement("graph");
  assert(graph_element);

  unordered_map<string, int> nodes_by_id;

  const char * edgedefault = graph_element->Attribute("edgedefault");
  bool directed = true;
  if (edgedefault && strcmp(edgedefault, "undirected") == 0) {
    directed = false;
  }
  std::shared_ptr<Graph> graph;
  if (directed) {
    graph = std::make_shared<Graph>();
    graph->setNodeArray(initial_nodes);
    graph->getNodeArray().setNodeSizeMethod(SizeMethod(SizeMethod::SIZE_FROM_INDEGREE));
  } else {
    graph = std::make_shared<UndirectedGraph>();
    graph->setNodeArray(initial_nodes);
    graph->getNodeArray().setNodeSizeMethod(SizeMethod(SizeMethod::SIZE_FROM_DEGREE));
  }
  graph->getNodeArray().setDynamic(true);
  graph->getNodeArray().setFlattenHierarchy(true);

  auto & node_table = graph->getNodeArray().getTable();
  auto & edge_table = graph->getFaceData();

  XMLElement * key_element = graphml_element->FirstChildElement("key");
  for ( ; key_element ; key_element = key_element->NextSiblingElement("key") ) {
    const char * key_type = key_element->Attribute("attr.type");
    const char * key_id = key_element->Attribute("id");
    const char * for_type = key_element->Attribute("for");
    // const char * name = key_element->Attribute("attr.name");

    assert(key_type && key_id && for_type);

    if (strcmp(for_type, "node") == 0) {
      createColumn(node_table, key_type, key_id);
    } else if (strcmp(for_type, "edge") == 0) {
      createColumn(edge_table, key_type, key_id);
    } else {
      assert(0);
    }
  }

  createGraphFromElement(*graph, *graphml_element, *graph_element, nodes_by_id, directed);

  graph->randomizeGeometry();
  // graph->setComplexGraph(is_complex);
  // graph->setHasSubGraphs(is_complex);

  return graph;
}

void
GraphML::createGraphFromElement(Graph & graph, XMLElement & graphml_element, XMLElement & graph_element, unordered_map<string, int> & nodes_by_id, bool is_directed, int parent_node_id) const {
  auto & node_table = graph.getNodeArray().getTable();
  auto & edge_table = graph.getFaceData();

  auto & node_id_column = node_table.addTextColumn("id");
  auto & edge_id_column = edge_table.addTextColumn("id");

  XMLElement * node_element = graph_element.FirstChildElement("node");
  for ( ; node_element ; node_element = node_element->NextSiblingElement("node") ) {
    const char * node_id_text = node_element->Attribute("id");
    assert(node_id_text);

    int node_id = graph.getNodeArray().add();
    node_id_column.pushValue(node_id_text);
    nodes_by_id[node_id_text] = node_id + 1;

    if (parent_node_id != -1) graph.addChild(parent_node_id, node_id);

    XMLElement * data_element = node_element->FirstChildElement("data");
    for ( ; data_element ; data_element = data_element->NextSiblingElement("data") ) {
      const char * key = data_element->Attribute("key");
      assert(key);
      const char * text = data_element->GetText();
      if (text) {
	node_table[key].setValue(node_id, text);
      }
    }

    XMLElement * nested_graph_element = node_element->FirstChildElement("graph");
    if (nested_graph_element) {
      createGraphFromElement(graph, graphml_element, *nested_graph_element, nodes_by_id, is_directed, node_id);
    }
  }

  XMLElement * edge_element = graph_element.FirstChildElement("edge");
  for ( ; edge_element ; edge_element = edge_element->NextSiblingElement("edge") ) {
    const char * edge_id_text = edge_element->Attribute("id");
    const char * source = edge_element->Attribute("source");
    const char * target = edge_element->Attribute("target");
    assert(source && target);

    if (strcmp(source, target) == 0) {
      cerr << "GraphML: skipping self link for " << source << endl;
      continue;
    }

    int source_node = nodes_by_id[source];
    int target_node = nodes_by_id[target];

    if (source_node && target_node) {
      int face_id = graph.addFace(-1);
      int edge_id1 = graph.addEdge(source_node - 1, target_node - 1, face_id);
      if (!is_directed) {
	int edge_id2 = graph.addEdge(target_node - 1, source_node - 1, face_id);
	graph.connectEdgePair(edge_id1, edge_id2);
      }

      if (edge_id_text && strlen(edge_id_text) != 0) {
	edge_id_column.setValue(face_id, edge_id_text);
      }

      XMLElement * data_element = edge_element->FirstChildElement("data");

      for ( ; data_element ; data_element = data_element->NextSiblingElement("data") ) {
	const char * key = data_element->Attribute("key");
	assert(key);
	const char * text = data_element->GetText();
	if (text) {
	  edge_table[key].setValue(face_id, text);
	}
      }
    } else {
      if (!source_node) {
	// cerr << "cannot find node " << source << endl;
      }
      if (!target_node) {
	// cerr << "cannot find node " << target << endl;
      }
    }
  }
}

bool
GraphML::saveGraph(const Graph & graph, const std::string & filename) {
  XMLDocument doc;
  doc.LinkEndChild(doc.NewDeclaration());

  XMLElement * graphml_element = doc.NewElement("graphml");
  graphml_element->SetAttribute("xmlns", "http://graphml.graphdrawing.org/xmlns");

  bool directed = graph.isDirected();
  auto & node_table = graph.getNodeArray().getTable();
  auto & edge_table = graph.getFaceData();

  for (auto & col : node_table.getColumns()) {
    XMLElement * key_element = doc.NewElement("key");
    key_element->SetAttribute("attr.name", col.first.c_str());
    key_element->SetAttribute("id", col.first.c_str());
    key_element->SetAttribute("attr.type", "text"); // col.second->getTypeText());
    key_element->SetAttribute("for", "node");
    graphml_element->LinkEndChild(key_element);
  }

  for (auto & col : edge_table.getColumns()) {
    XMLElement * key_element = doc.NewElement("key");
    key_element->SetAttribute("attr.name", col.first.c_str());
    key_element->SetAttribute("id", col.first.c_str());
    key_element->SetAttribute("attr.type", "text"); // col.second->getTypeText());
    key_element->SetAttribute("for", "edge");
    graphml_element->LinkEndChild(key_element);
  }

  XMLElement * graph_element = doc.NewElement("graph");
  graphml_element->LinkEndChild(graph_element);

  if (!directed) {
    graph_element->SetAttribute("edgedefault", "undirected");
  }

  for (unsigned int i = 0; i < graph.getNodeArray().size(); i++) {
    XMLElement * node_element = doc.NewElement("node");
    string node_id = "n" + to_string(i);
    node_element->SetAttribute("id", node_id.c_str());

    for (auto & col : node_table.getColumns()) {
      XMLElement * data_element = doc.NewElement("data");
      data_element->SetAttribute("key", col.first.c_str());
      data_element->LinkEndChild(doc.NewText(col.second->getText(i).c_str()));
      node_element->LinkEndChild(data_element);
    }

    graph_element->LinkEndChild(node_element);
  }

  for (unsigned int i = 0; i < graph.getFaceCount(); i++) {
    XMLElement * edge_element = doc.NewElement("edge");

#if 0
    auto edge = graph.getEdgeAttributes(i);
    string node_id1 = "n" + to_string(edge.tail);
    string node_id2 = "n" + to_string(edge.head);

    // timestamp, sentiment

    edge_element->SetAttribute("source", node_id1.c_str());
    edge_element->SetAttribute("target", node_id2.c_str());
#endif

    for (auto & col : edge_table.getColumns()) {
      XMLElement * data_element = doc.NewElement("data");
      data_element->SetAttribute("key", col.first.c_str());
      data_element->LinkEndChild(doc.NewText(col.second->getText(i).c_str()));
      edge_element->LinkEndChild(data_element);
    }

    graph_element->LinkEndChild(edge_element);
  }

  doc.LinkEndChild(graphml_element);
  doc.SaveFile(filename.c_str());

  return true;
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_PRODUCT_INTERFACES_HH
#define DUNE_GDT_PRODUCT_INTERFACES_HH

#include <type_traits>

#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/functions/interfaces.hh>
#include <dune/stuff/la/container/interfaces.hh>

#include <dune/gdt/space/interface.hh>
#include <dune/gdt/discretefunction/default.hh>

namespace Dune {
namespace GDT {

template <class Traits>
class ProductInterface : protected Stuff::CRTPInterface<ProductInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;
  typedef typename Traits::GridViewType GridViewType;
  typedef typename Traits::FieldType FieldType;

  const GridViewType& grid_view() const
  {
    CHECK_CRTP(this->as_imp(*this).grid_view());
    return this->as_imp(*this).grid_view();
  }

  template <class RangeType, class SourceType>
  FieldType apply2(const RangeType& range, const SourceType& source) const
  {
    CHECK_CRTP(this->as_imp(*this).apply2(range, source));
    return this->as_imp(*this).apply2(range, source);
  }
}; // class ProductInterface

template <class Traits>
class LocalizableProductInterface : protected Stuff::CRTPInterface<LocalizableProductInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;
  typedef typename Traits::GridViewType GridViewType;
  typedef typename Traits::RangeType RangeType;
  typedef typename Traits::SourceType SourceType;
  typedef typename Traits::FieldType FieldType;

  typedef typename GridViewType::template Codim<0>::Entity EntityType;
  typedef typename GridViewType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridViewType::dimension;

private:
  static_assert(std::is_base_of<Stuff::IsLocalizableFunction, SourceType>::value,
                "SourceType has to be derived from Stuff::IsLocalizableFunction!");
  static_assert(std::is_base_of<Stuff::IsLocalizableFunction, RangeType>::value,
                "RangeType has to be derived from Stuff::IsLocalizableFunction!");
  static_assert(std::is_same<typename SourceType::EntityType, EntityType>::value,
                "The EntityType of SourceType and GridViewType have to match!");
  static_assert(std::is_same<typename RangeType::EntityType, EntityType>::value,
                "The EntityType of RangeType and GridViewType have to match!");
  static_assert(std::is_same<typename SourceType::DomainFieldType, DomainFieldType>::value,
                "The DomainFieldType of SourceType and GridViewType have to match!");
  static_assert(std::is_same<typename RangeType::DomainFieldType, DomainFieldType>::value,
                "The DomainFieldType of RangeType and GridViewType have to match!");
  static_assert(SourceType::dimDomain == dimDomain, "The dimDomain of SourceType and GridViewType have to match!");
  static_assert(RangeType::dimDomain == dimDomain, "The dimDomain of RangeType and GridViewType have to match!");

public:
  const GridViewType& grid_view() const
  {
    CHECK_CRTP(this->as_imp(*this).grid_view());
    return this->as_imp(*this).grid_view();
  }

  const RangeType& range() const
  {
    CHECK_CRTP(this->as_imp(*this).range());
    return this->as_imp(*this).range();
  }

  const SourceType& source() const
  {
    CHECK_CRTP(this->as_imp(*this).source());
    return this->as_imp(*this).source();
  }

  FieldType apply2()
  {
    CHECK_CRTP(this->as_imp(*this).apply2());
    return this->as_imp(*this).apply2();
  }
}; // class LocalizableProductInterface

template <class Traits>
class AssemblableProductInterface : protected Stuff::CRTPInterface<AssemblableProductInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;
  typedef typename Traits::GridViewType GridViewType;
  typedef typename Traits::RangeSpaceType RangeSpaceType;
  typedef typename Traits::SourceSpaceType SourceSpaceType;
  typedef typename Traits::MatrixType MatrixType;

  typedef typename MatrixType::ScalarType FieldType;
  typedef typename GridViewType::template Codim<0>::Entity EntityType;
  typedef typename GridViewType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridViewType::dimension;

  typedef Stuff::LA::SparsityPatternDefault PatternType;

private:
  static_assert(std::is_base_of<SpaceInterface<typename RangeSpaceType::Traits>, RangeSpaceType>::value,
                "RangeSpaceType has to be derived from SpaceInterface!");
  static_assert(std::is_base_of<SpaceInterface<typename SourceSpaceType::Traits>, SourceSpaceType>::value,
                "SourceSpaceType has to be derived from SpaceInterface!");
  static_assert(std::is_same<typename RangeSpaceType::GridViewType, GridViewType>::value,
                "The GridViewType of RangeSpaceType and GridViewType have to match!");
  static_assert(std::is_same<typename SourceSpaceType::GridViewType, GridViewType>::value,
                "The GridViewType of SourceSpaceType and GridViewType have to match!");
  static_assert(std::is_base_of<Stuff::LA::MatrixInterface<typename MatrixType::Traits>, MatrixType>::value,
                "MatrixType has to be derived from Stuff::LA::MatrixInterface!");

public:
  static PatternType pattern(const RangeSpaceType& range_space)
  {
    return pattern(range_space, range_space);
  }

  static PatternType pattern(const RangeSpaceType& range_space, const SourceSpaceType& source_space)
  {
    return pattern(range_space, source_space, *(range_space.grid_view()));
  }

  static PatternType pattern(const RangeSpaceType& range_space, const SourceSpaceType& source_space,
                             const GridViewType& grid_view)
  {
    return derived_type::pattern(range_space, source_space, grid_view);
  }

  const GridViewType& grid_view() const
  {
    CHECK_CRTP(this->as_imp(*this).grid_view());
    return this->as_imp(*this).grid_view();
  }

  const RangeSpaceType& range_space() const
  {
    CHECK_CRTP(this->as_imp(*this).range_space());
    return this->as_imp(*this).range_space();
  }

  const SourceSpaceType& source_space() const
  {
    CHECK_CRTP(this->as_imp(*this).source_space());
    return this->as_imp(*this).source_space();
  }

  void assemble()
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).assemble());
  }

  MatrixType& matrix()
  {
    CHECK_CRTP(this->as_imp(*this).matrix());
    return this->as_imp(*this).matrix();
  }

  const MatrixType& matrix() const
  {
    CHECK_CRTP(this->as_imp(*this).matrix());
    return this->as_imp(*this).matrix();
  }

  template <class R, class S>
  FieldType apply2(const Stuff::LA::VectorInterface<R>& range, const Stuff::LA::VectorInterface<S>& source)
  {
    typedef typename R::derived_type RangeType;
    typedef typename S::derived_type SourceType;
    assert(range.size() == matrix().rows());
    assert(source.size() == matrix().cols());
    assemble();
    auto tmp = range.copy();
    matrix().mv(static_cast<const SourceType&>(source), tmp);
    return static_cast<const RangeType&>(range).dot(tmp);
  } // ... apply2(...)

  template <class R, class S>
  FieldType apply2(const ConstDiscreteFunction<RangeSpaceType, R>& range,
                   const ConstDiscreteFunction<SourceSpaceType, S>& source)
  {
    return apply2(range.vector(), source.vector());
  }
}; // class AssemblableProductInterface

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PRODUCT_INTERFACES_HH
<commit_msg>[product.interfaces] simplify apply2() for vectors<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_PRODUCT_INTERFACES_HH
#define DUNE_GDT_PRODUCT_INTERFACES_HH

#include <type_traits>

#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/functions/interfaces.hh>
#include <dune/stuff/la/container/interfaces.hh>

#include <dune/gdt/space/interface.hh>
#include <dune/gdt/discretefunction/default.hh>

namespace Dune {
namespace GDT {

template <class Traits>
class ProductInterface : protected Stuff::CRTPInterface<ProductInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;
  typedef typename Traits::GridViewType GridViewType;
  typedef typename Traits::FieldType FieldType;

  const GridViewType& grid_view() const
  {
    CHECK_CRTP(this->as_imp(*this).grid_view());
    return this->as_imp(*this).grid_view();
  }

  template <class RangeType, class SourceType>
  FieldType apply2(const RangeType& range, const SourceType& source) const
  {
    CHECK_CRTP(this->as_imp(*this).apply2(range, source));
    return this->as_imp(*this).apply2(range, source);
  }
}; // class ProductInterface

template <class Traits>
class LocalizableProductInterface : protected Stuff::CRTPInterface<LocalizableProductInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;
  typedef typename Traits::GridViewType GridViewType;
  typedef typename Traits::RangeType RangeType;
  typedef typename Traits::SourceType SourceType;
  typedef typename Traits::FieldType FieldType;

  typedef typename GridViewType::template Codim<0>::Entity EntityType;
  typedef typename GridViewType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridViewType::dimension;

private:
  static_assert(std::is_base_of<Stuff::IsLocalizableFunction, SourceType>::value,
                "SourceType has to be derived from Stuff::IsLocalizableFunction!");
  static_assert(std::is_base_of<Stuff::IsLocalizableFunction, RangeType>::value,
                "RangeType has to be derived from Stuff::IsLocalizableFunction!");
  static_assert(std::is_same<typename SourceType::EntityType, EntityType>::value,
                "The EntityType of SourceType and GridViewType have to match!");
  static_assert(std::is_same<typename RangeType::EntityType, EntityType>::value,
                "The EntityType of RangeType and GridViewType have to match!");
  static_assert(std::is_same<typename SourceType::DomainFieldType, DomainFieldType>::value,
                "The DomainFieldType of SourceType and GridViewType have to match!");
  static_assert(std::is_same<typename RangeType::DomainFieldType, DomainFieldType>::value,
                "The DomainFieldType of RangeType and GridViewType have to match!");
  static_assert(SourceType::dimDomain == dimDomain, "The dimDomain of SourceType and GridViewType have to match!");
  static_assert(RangeType::dimDomain == dimDomain, "The dimDomain of RangeType and GridViewType have to match!");

public:
  const GridViewType& grid_view() const
  {
    CHECK_CRTP(this->as_imp(*this).grid_view());
    return this->as_imp(*this).grid_view();
  }

  const RangeType& range() const
  {
    CHECK_CRTP(this->as_imp(*this).range());
    return this->as_imp(*this).range();
  }

  const SourceType& source() const
  {
    CHECK_CRTP(this->as_imp(*this).source());
    return this->as_imp(*this).source();
  }

  FieldType apply2()
  {
    CHECK_CRTP(this->as_imp(*this).apply2());
    return this->as_imp(*this).apply2();
  }
}; // class LocalizableProductInterface

template <class Traits>
class AssemblableProductInterface : protected Stuff::CRTPInterface<AssemblableProductInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;
  typedef typename Traits::GridViewType GridViewType;
  typedef typename Traits::RangeSpaceType RangeSpaceType;
  typedef typename Traits::SourceSpaceType SourceSpaceType;
  typedef typename Traits::MatrixType MatrixType;

  typedef typename MatrixType::ScalarType FieldType;
  typedef typename GridViewType::template Codim<0>::Entity EntityType;
  typedef typename GridViewType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridViewType::dimension;

  typedef Stuff::LA::SparsityPatternDefault PatternType;

private:
  static_assert(std::is_base_of<SpaceInterface<typename RangeSpaceType::Traits>, RangeSpaceType>::value,
                "RangeSpaceType has to be derived from SpaceInterface!");
  static_assert(std::is_base_of<SpaceInterface<typename SourceSpaceType::Traits>, SourceSpaceType>::value,
                "SourceSpaceType has to be derived from SpaceInterface!");
  static_assert(std::is_same<typename RangeSpaceType::GridViewType, GridViewType>::value,
                "The GridViewType of RangeSpaceType and GridViewType have to match!");
  static_assert(std::is_same<typename SourceSpaceType::GridViewType, GridViewType>::value,
                "The GridViewType of SourceSpaceType and GridViewType have to match!");
  static_assert(std::is_base_of<Stuff::LA::MatrixInterface<typename MatrixType::Traits>, MatrixType>::value,
                "MatrixType has to be derived from Stuff::LA::MatrixInterface!");

public:
  static PatternType pattern(const RangeSpaceType& range_space)
  {
    return pattern(range_space, range_space);
  }

  static PatternType pattern(const RangeSpaceType& range_space, const SourceSpaceType& source_space)
  {
    return pattern(range_space, source_space, *(range_space.grid_view()));
  }

  static PatternType pattern(const RangeSpaceType& range_space, const SourceSpaceType& source_space,
                             const GridViewType& grid_view)
  {
    return derived_type::pattern(range_space, source_space, grid_view);
  }

  const GridViewType& grid_view() const
  {
    CHECK_CRTP(this->as_imp(*this).grid_view());
    return this->as_imp(*this).grid_view();
  }

  const RangeSpaceType& range_space() const
  {
    CHECK_CRTP(this->as_imp(*this).range_space());
    return this->as_imp(*this).range_space();
  }

  const SourceSpaceType& source_space() const
  {
    CHECK_CRTP(this->as_imp(*this).source_space());
    return this->as_imp(*this).source_space();
  }

  void assemble()
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).assemble());
  }

  MatrixType& matrix()
  {
    CHECK_CRTP(this->as_imp(*this).matrix());
    return this->as_imp(*this).matrix();
  }

  const MatrixType& matrix() const
  {
    CHECK_CRTP(this->as_imp(*this).matrix());
    return this->as_imp(*this).matrix();
  }

  template <class R, class S>
  FieldType apply2(const Stuff::LA::VectorInterface<R>& range, const Stuff::LA::VectorInterface<S>& source)
  {
    assemble();
    assert(range.size() == matrix().rows());
    assert(source.size() == matrix().cols());
    auto tmp = range.copy();
    matrix().mv(source.as_imp(source), tmp);
    return range.dot(tmp);
  } // ... apply2(...)

  template <class R, class S>
  FieldType apply2(const ConstDiscreteFunction<RangeSpaceType, R>& range,
                   const ConstDiscreteFunction<SourceSpaceType, S>& source)
  {
    return apply2(range.vector(), source.vector());
  }
}; // class AssemblableProductInterface

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PRODUCT_INTERFACES_HH
<|endoftext|>


<commit_before>/**
 * @file Machine.hpp
 * @author Duncan Campbell
 * @version 1.0
 *
 * @section LICENSE
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Duncan Campbell
 *
 * 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.
 *
 * @section DESCRIPTION
 *
 * This class represents a finite state machine.  It is responsible for managing
 * the machine and controlling the transition between states.
 */
<commit_msg>Add in the inital class to represent a finite state machine<commit_after>/**
 * @file Machine.hpp
 * @author Duncan Campbell
 * @version 1.0
 *
 * @section LICENSE
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Duncan Campbell
 *
 * 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.
 *
 * @section DESCRIPTION
 *
 * This class represents a finite state machine.  It is responsible for managing
 * the machine and controlling the transition between states.
 */

#include <string>
#include <map>

#include "States.hpp"

namespace StateTrans
{
    class Machine
    {
        public:
            Machine();
            Machine(std::map<std::string, State>, std::string);
            ~Machine();

        private:
            std::map<std::string> states;

    };
}
<|endoftext|>


<commit_before><commit_msg>Changed name of "imgRef" variable to "imgRefPoint."<commit_after><|endoftext|>


<commit_before>#include <Arduino.h>
#include <NBHX711.h>

#if ARDUINO_VERSION <= 106
    // "yield" is not implemented in older Arduino Core releases-
    void yield(void) {};
#endif

NBHX711::NBHX711(byte data, byte clock, byte depth, byte gain) :
	dataPin(data),
	clockPin(clock),
	offset(0),
	scaleFactor(1.0),
	histSize(0),
	histBuffer(NULL),
	curr(0)
{
	histSize = 3 * min(max(depth, 6), 255/3);
	histBuffer = new byte[histSize];
	if (!histBuffer) {
		histSize = 0;
	} else {
		memset(histBuffer, 0, histSize);
	}
	setGainAndChannel(gain);
	powerUp();
}

NBHX711::~NBHX711() {
	delete[] histBuffer;
	pinMode(clockPin, INPUT);
}

byte NBHX711::getHistSize() {
	return histSize / 3;
}

void NBHX711::begin() {
	pinMode(clockPin, OUTPUT);
}

bool NBHX711::isReady() {
	return digitalRead(dataPin) == LOW;
}

void NBHX711::setGainAndChannel(byte gain) {
	gainCode = gain;
}

long NBHX711::getRaw() {
	return cvt24(histBuffer + curr);
}

void NBHX711::putData(byte* storeTo) {
	// pulse the clock pin 24 times to read the data
	storeTo[2] = shiftIn(dataPin, clockPin, MSBFIRST);
	storeTo[1] = shiftIn(dataPin, clockPin, MSBFIRST);
	storeTo[0] = shiftIn(dataPin, clockPin, MSBFIRST);
	// set the channel and the gain factor for the next reading using the clock pin
	for (byte i = 0; i < gainCode; i++) {
		digitalWrite(clockPin, HIGH);
		digitalWrite(clockPin, LOW);
	}
}

long NBHX711::cvt24(byte* from) {
	uint8_t filler = 0x00;
	if (from[2] & 0x80) {
		filler--;
	}
	return (  static_cast<unsigned long>(filler) << 24
			| static_cast<unsigned long>(from[2]) << 16
			| static_cast<unsigned long>(from[1]) << 8
			| static_cast<unsigned long>(from[0]) );
}

bool NBHX711::update() {
	bool retVal = false;
	if (isReady()) {
		retVal = true;
		curr = nextIndex(curr);
		putData(histBuffer + curr);
	}
	return retVal;
}

byte NBHX711::backIndex(byte times) {
	int index = curr - (times - 1) * 3;
	if (index < 0) {
		index += histSize;
	}
	return index;
}

byte NBHX711::nextIndex(byte index) {
	int nIndex = index + 3;
	if (nIndex >= histSize) {
		nIndex = 0;
	}
	return nIndex;
}

long NBHX711::readAverage(byte times) {
	long sum = 0;
	byte index = backIndex(times);
	for (byte i = 0; i < times; i++) {
		sum += cvt24(histBuffer + index);
		index = nextIndex(index);
	}
	return sum / times;
}

long NBHX711::getValue(byte times) {
	return readAverage(times) - offset;
}

float NBHX711::getUnits(byte times) {
	return getValue(times) / scaleFactor;
}

void NBHX711::tare(byte times) {
	setOffset(readAverage(times));
}

void NBHX711::setScale(float scale) {
	scaleFactor = scale;
}

float NBHX711::getScale() {
	return scaleFactor;
}

void NBHX711::setOffset(long inOffset) {
	offset = inOffset;
}

long NBHX711::getOffset() {
	return offset;
}

void NBHX711::powerDown() {
	digitalWrite(clockPin, LOW);
	digitalWrite(clockPin, HIGH);
}

void NBHX711::powerUp() {
	digitalWrite(clockPin, LOW);
}
<commit_msg>Removed unused yield() definition.<commit_after>#include <Arduino.h>
#include <NBHX711.h>

NBHX711::NBHX711(byte data, byte clock, byte depth, byte gain) :
	dataPin(data),
	clockPin(clock),
	offset(0),
	scaleFactor(1.0),
	histSize(0),
	histBuffer(NULL),
	curr(0)
{
	histSize = 3 * min(max(depth, 6), 255/3);
	histBuffer = new byte[histSize];
	if (!histBuffer) {
		histSize = 0;
	} else {
		memset(histBuffer, 0, histSize);
	}
	setGainAndChannel(gain);
	powerUp();
}

NBHX711::~NBHX711() {
	delete[] histBuffer;
	pinMode(clockPin, INPUT);
}

byte NBHX711::getHistSize() {
	return histSize / 3;
}

void NBHX711::begin() {
	pinMode(clockPin, OUTPUT);
}

bool NBHX711::isReady() {
	return digitalRead(dataPin) == LOW;
}

void NBHX711::setGainAndChannel(byte gain) {
	gainCode = gain;
}

long NBHX711::getRaw() {
	return cvt24(histBuffer + curr);
}

void NBHX711::putData(byte* storeTo) {
	// pulse the clock pin 24 times to read the data
	storeTo[2] = shiftIn(dataPin, clockPin, MSBFIRST);
	storeTo[1] = shiftIn(dataPin, clockPin, MSBFIRST);
	storeTo[0] = shiftIn(dataPin, clockPin, MSBFIRST);
	// set the channel and the gain factor for the next reading using the clock pin
	for (byte i = 0; i < gainCode; i++) {
		digitalWrite(clockPin, HIGH);
		digitalWrite(clockPin, LOW);
	}
}

long NBHX711::cvt24(byte* from) {
	uint8_t filler = 0x00;
	if (from[2] & 0x80) {
		filler--;
	}
	return (  static_cast<unsigned long>(filler) << 24
			| static_cast<unsigned long>(from[2]) << 16
			| static_cast<unsigned long>(from[1]) << 8
			| static_cast<unsigned long>(from[0]) );
}

bool NBHX711::update() {
	bool retVal = false;
	if (isReady()) {
		retVal = true;
		curr = nextIndex(curr);
		putData(histBuffer + curr);
	}
	return retVal;
}

byte NBHX711::backIndex(byte times) {
	int index = curr - (times - 1) * 3;
	if (index < 0) {
		index += histSize;
	}
	return index;
}

byte NBHX711::nextIndex(byte index) {
	int nIndex = index + 3;
	if (nIndex >= histSize) {
		nIndex = 0;
	}
	return nIndex;
}

long NBHX711::readAverage(byte times) {
	long sum = 0;
	byte index = backIndex(times);
	for (byte i = 0; i < times; i++) {
		sum += cvt24(histBuffer + index);
		index = nextIndex(index);
	}
	return sum / times;
}

long NBHX711::getValue(byte times) {
	return readAverage(times) - offset;
}

float NBHX711::getUnits(byte times) {
	return getValue(times) / scaleFactor;
}

void NBHX711::tare(byte times) {
	setOffset(readAverage(times));
}

void NBHX711::setScale(float scale) {
	scaleFactor = scale;
}

float NBHX711::getScale() {
	return scaleFactor;
}

void NBHX711::setOffset(long inOffset) {
	offset = inOffset;
}

long NBHX711::getOffset() {
	return offset;
}

void NBHX711::powerDown() {
	digitalWrite(clockPin, LOW);
	digitalWrite(clockPin, HIGH);
}

void NBHX711::powerUp() {
	digitalWrite(clockPin, LOW);
}
<|endoftext|>


<commit_before>/******************************************************************************
 *
 * Project:  laszip - http://liblas.org -
 * Purpose:
 * Author:   Martin Isenburg
 *           martin.isenburg at gmail.com
 *
 ******************************************************************************
 * Copyright (c) 2009, Martin Isenburg
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Licence as published
 * by the Free Software Foundation.
 *
 * See the COPYING file for more information.
 *
 ****************************************************************************/

/*
===============================================================================

  FILE:  arithmeticdecoder.cpp

  CONTENTS:

    see header file

  PROGRAMMERS:

    martin isenburg@cs.unc.edu

  COPYRIGHT:

    copyright (C) 2009 martin isenburg (isenburg@cs.unc.edu)

    This software 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.

  CHANGE HISTORY:

    see header file

===============================================================================
*/

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#include "arithmeticdecoder.h"

namespace laszipalternate {

ArithmeticDecoder::ArithmeticDecoder(unsigned char* bytes, unsigned int number_bytes)
{
  inbuffer = bytes;
  endbuffer = bytes + number_bytes;
  fp = 0;

  /*
  if ((value = get_inbyte()) != AC_HEADER_BYTE)
  {
    fprintf(stderr, "ArithmeticDecoder: wrong AC_HEADER_BYTE of %d. is should be %d\n", value, AC_HEADER_BYTE);
    return;
  }
  */

  length = AC__MaxLength;
  value = (get_inbyte() << 24);
  value |= (get_inbyte() << 16);
  value |= (get_inbyte() << 8);
  value |= (get_inbyte());
}

ArithmeticDecoder::ArithmeticDecoder(FILE* fp)
{
  inbuffer = 0;
  endbuffer = 0;
  this->fp = fp;

/*
  if ((value = get_inbyte()) != AC_HEADER_BYTE)
  {
    fprintf(stderr, "ArithmeticDecoder: wrong AC_HEADER_BYTE of %d. is should be %d\n", value, AC_HEADER_BYTE);
    return;
  }
*/

  length = AC__MaxLength;
  value = (get_inbyte() << 24);
  value |= (get_inbyte() << 16);
  value |= (get_inbyte() << 8);
  value |= (get_inbyte());
}

unsigned int ArithmeticDecoder::decode(ArithmeticBitModel* m)
{
  unsigned int x = m->bit_0_prob * (length >> BM__LengthShift); // product l x p0
  unsigned int sym = (value >= x);                                 // decision
                                                    // update & shift interval
  if (sym == 0) {
    length  = x;
    ++m->bit_0_count;
  }
  else {
    value  -= x;                                 // shifted interval base = 0
    length -= x;
  }

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization
  if (--m->bits_until_update == 0) m->update();       // periodic model update

  return sym;                                         // return data bit value
}

unsigned int ArithmeticDecoder::decode(ArithmeticModel* m)
{
  unsigned n, sym, x, y = length;

  if (m->decoder_table) {              // use table look-up for faster decoding

    unsigned dv = value / (length >>= DM__LengthShift);
    unsigned t = dv >> m->table_shift;

    sym = m->decoder_table[t];         // initial decision based on table look-up
    n = m->decoder_table[t+1] + 1;

    while (n > sym + 1) {                        // finish with bisection search
      unsigned int k = (sym + n) >> 1;
      if (m->distribution[k] > dv) n = k; else sym = k;
    }
                                                           // compute products
    x = m->distribution[sym] * length;
    if (sym != m->last_symbol) y = m->distribution[sym+1] * length;
  }

  else {                                  // decode using only multiplications

    x = sym = 0;
    length >>= DM__LengthShift;
    unsigned int k = (n = m->data_symbols) >> 1;
                                                // decode via bisection search
    do {
      unsigned int z = length * m->distribution[k];
      if (z > value) {
        n = k;
        y = z;                                             // value is smaller
      }
      else {
        sym = k;
        x = z;                                     // value is larger or equal
      }
    } while ((k = (sym + n) >> 1) != sym);
  }

  value -= x;                                               // update interval
  length = y - x;

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization

  ++m->symbol_count[sym];
  if (--m->symbols_until_update == 0) m->update(false); // periodic model update

  return sym;
}

unsigned int ArithmeticDecoder::readBits(unsigned int bits)
{
  assert(bits && (bits <= 32));

  if (bits > 20)
  {
    unsigned int tmp = readShort();
    bits = bits - 16;
    unsigned int tmp1 = readBits(bits) << 16;
    return (tmp1|tmp);
  }

  unsigned int sym = value / (length >>= bits);// decode symbol, change length
  value -= length * sym;                                    // update interval

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization

  return sym;
}

unsigned char ArithmeticDecoder::readByte()
{
  unsigned int sym = value / (length >>= 8);   // decode symbol, change length
  value -= length * sym;                                    // update interval

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization

  assert(sym < (1<<8));

  return (unsigned char)sym;
}

unsigned short ArithmeticDecoder::readShort()
{
  unsigned int sym = value / (length >>= 16);  // decode symbol, change length
  value -= length * sym;                                    // update interval

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization

  assert(sym < (1<<16));

  return (unsigned short)sym;
}

unsigned int ArithmeticDecoder::readInt()
{
  unsigned int lowerInt = readShort();
  unsigned int upperInt = readShort();
  return upperInt*65536+lowerInt;
}

float ArithmeticDecoder::readFloat()
{
  float f;
  *((unsigned int*)(&f)) = readInt();
  return f;
}

U64 ArithmeticDecoder::readInt64()
{
  U64 lowerInt = readInt();
  U64 upperInt = readInt();
  return upperInt*4294967296+lowerInt;
}

double ArithmeticDecoder::readDouble()
{
  double d;
  *((U64*)(&d)) = readInt64();
  return d;
}

void ArithmeticDecoder::done()
{
}

ArithmeticDecoder::~ArithmeticDecoder()
{
}

inline void ArithmeticDecoder::renorm_dec_interval()
{
  do {                                          // read least-significant byte
    value = (value << 8) | get_inbyte();
  } while ((length <<= 8) < AC__MinLength);        // length multiplied by 256
}

int read_bytes = 0;

inline unsigned int ArithmeticDecoder::get_inbyte()
{
  unsigned int c;
  if (fp)
  {
    read_bytes++;
    c = getc(fp);
    if (c == EOF)
    {
      c = 0;
    }
  }
  else
  {
    if (inbuffer == endbuffer)
    {
      c = 0;
    }
    else
    {
      c = *inbuffer++;
    }
  }
  return c;
}

}<commit_msg>clean up warning<commit_after>/******************************************************************************
 *
 * Project:  laszip - http://liblas.org -
 * Purpose:
 * Author:   Martin Isenburg
 *           martin.isenburg at gmail.com
 *
 ******************************************************************************
 * Copyright (c) 2009, Martin Isenburg
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Licence as published
 * by the Free Software Foundation.
 *
 * See the COPYING file for more information.
 *
 ****************************************************************************/

/*
===============================================================================

  FILE:  arithmeticdecoder.cpp

  CONTENTS:

    see header file

  PROGRAMMERS:

    martin isenburg@cs.unc.edu

  COPYRIGHT:

    copyright (C) 2009 martin isenburg (isenburg@cs.unc.edu)

    This software 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.

  CHANGE HISTORY:

    see header file

===============================================================================
*/

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#include "arithmeticdecoder.h"

namespace laszipalternate {

ArithmeticDecoder::ArithmeticDecoder(unsigned char* bytes, unsigned int number_bytes)
{
  inbuffer = bytes;
  endbuffer = bytes + number_bytes;
  fp = 0;

  /*
  if ((value = get_inbyte()) != AC_HEADER_BYTE)
  {
    fprintf(stderr, "ArithmeticDecoder: wrong AC_HEADER_BYTE of %d. is should be %d\n", value, AC_HEADER_BYTE);
    return;
  }
  */

  length = AC__MaxLength;
  value = (get_inbyte() << 24);
  value |= (get_inbyte() << 16);
  value |= (get_inbyte() << 8);
  value |= (get_inbyte());
}

ArithmeticDecoder::ArithmeticDecoder(FILE* fp)
{
  inbuffer = 0;
  endbuffer = 0;
  this->fp = fp;

/*
  if ((value = get_inbyte()) != AC_HEADER_BYTE)
  {
    fprintf(stderr, "ArithmeticDecoder: wrong AC_HEADER_BYTE of %d. is should be %d\n", value, AC_HEADER_BYTE);
    return;
  }
*/

  length = AC__MaxLength;
  value = (get_inbyte() << 24);
  value |= (get_inbyte() << 16);
  value |= (get_inbyte() << 8);
  value |= (get_inbyte());
}

unsigned int ArithmeticDecoder::decode(ArithmeticBitModel* m)
{
  unsigned int x = m->bit_0_prob * (length >> BM__LengthShift); // product l x p0
  unsigned int sym = (value >= x);                                 // decision
                                                    // update & shift interval
  if (sym == 0) {
    length  = x;
    ++m->bit_0_count;
  }
  else {
    value  -= x;                                 // shifted interval base = 0
    length -= x;
  }

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization
  if (--m->bits_until_update == 0) m->update();       // periodic model update

  return sym;                                         // return data bit value
}

unsigned int ArithmeticDecoder::decode(ArithmeticModel* m)
{
  unsigned n, sym, x, y = length;

  if (m->decoder_table) {              // use table look-up for faster decoding

    unsigned dv = value / (length >>= DM__LengthShift);
    unsigned t = dv >> m->table_shift;

    sym = m->decoder_table[t];         // initial decision based on table look-up
    n = m->decoder_table[t+1] + 1;

    while (n > sym + 1) {                        // finish with bisection search
      unsigned int k = (sym + n) >> 1;
      if (m->distribution[k] > dv) n = k; else sym = k;
    }
                                                           // compute products
    x = m->distribution[sym] * length;
    if (sym != m->last_symbol) y = m->distribution[sym+1] * length;
  }

  else {                                  // decode using only multiplications

    x = sym = 0;
    length >>= DM__LengthShift;
    unsigned int k = (n = m->data_symbols) >> 1;
                                                // decode via bisection search
    do {
      unsigned int z = length * m->distribution[k];
      if (z > value) {
        n = k;
        y = z;                                             // value is smaller
      }
      else {
        sym = k;
        x = z;                                     // value is larger or equal
      }
    } while ((k = (sym + n) >> 1) != sym);
  }

  value -= x;                                               // update interval
  length = y - x;

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization

  ++m->symbol_count[sym];
  if (--m->symbols_until_update == 0) m->update(false); // periodic model update

  return sym;
}

unsigned int ArithmeticDecoder::readBits(unsigned int bits)
{
  assert(bits && (bits <= 32));

  if (bits > 20)
  {
    unsigned int tmp = readShort();
    bits = bits - 16;
    unsigned int tmp1 = readBits(bits) << 16;
    return (tmp1|tmp);
  }

  unsigned int sym = value / (length >>= bits);// decode symbol, change length
  value -= length * sym;                                    // update interval

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization

  return sym;
}

unsigned char ArithmeticDecoder::readByte()
{
  unsigned int sym = value / (length >>= 8);   // decode symbol, change length
  value -= length * sym;                                    // update interval

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization

  assert(sym < (1<<8));

  return (unsigned char)sym;
}

unsigned short ArithmeticDecoder::readShort()
{
  unsigned int sym = value / (length >>= 16);  // decode symbol, change length
  value -= length * sym;                                    // update interval

  if (length < AC__MinLength) renorm_dec_interval();        // renormalization

  assert(sym < (1<<16));

  return (unsigned short)sym;
}

unsigned int ArithmeticDecoder::readInt()
{
  unsigned int lowerInt = readShort();
  unsigned int upperInt = readShort();
  return upperInt*65536+lowerInt;
}

float ArithmeticDecoder::readFloat()
{
  float f;
  *((unsigned int*)(&f)) = readInt();
  return f;
}

U64 ArithmeticDecoder::readInt64()
{
  U64 lowerInt = readInt();
  U64 upperInt = readInt();
  return upperInt*4294967296+lowerInt;
}

double ArithmeticDecoder::readDouble()
{
  double d;
  *((U64*)(&d)) = readInt64();
  return d;
}

void ArithmeticDecoder::done()
{
}

ArithmeticDecoder::~ArithmeticDecoder()
{
}

inline void ArithmeticDecoder::renorm_dec_interval()
{
  do {                                          // read least-significant byte
    value = (value << 8) | get_inbyte();
  } while ((length <<= 8) < AC__MinLength);        // length multiplied by 256
}

int read_bytes = 0;

inline unsigned int ArithmeticDecoder::get_inbyte()
{
  int c;
  if (fp)
  {
    read_bytes++;
    c = getc(fp);
    if (c == EOF)
    {
      c = 0;
    }
  }
  else
  {
    if (inbuffer == endbuffer)
    {
      c = 0;
    }
    else
    {
      c = *inbuffer++;
    }
  }
  return c;
}

}<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2011, Shane Liesegang
// 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 copyright holder nor the names of any
//       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.
//////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "../Input/MobileSimulator.h"

#include "../Actors/Actor.h"
#include "../Input/InputManager.h"
#include "../Input/MultiTouch.h"
#include "../Messaging/Switchboard.h"

// maximum duration of touch (in seconds) to be considered a swipe
//  (too long and we're dragging)
#define SWIPE_MAX_DURATION 0.4f
// distance in pixels the touch must go to be considered a swipe
//  (too short and it might have just been a tap)
#define SWIPE_MIN_DISTANCE 50

// distance in pixels that the touches have to move before multi-touch
//  recognition starts
#define MULTI_MIN_DISTANCE 13
// angle in radians that the touches' vectors need to shift by to
//   be considered a rotation instead of a pinch
// (equivalent of 2.5 degrees)
#define MULTI_ROTATE_ANGLE 0.0436332313f

MobileSimulator::MobileSimulator()
{
	_multiGestureOngoing = false;
	_gestureType = NONE;
	_mouseDown = false;

	_fingerGhost1 = new Actor();
	_fingerGhost1->SetSize(1.5f);
	_fingerGhost1->SetDrawShape(ADS_Circle);
	_fingerGhost1->SetColor(0.8f, 0.8f, 0.8f, 0.0f);

	_fingerGhost2 = new Actor();
	_fingerGhost2->SetSize(1.5f);
	_fingerGhost2->SetDrawShape(ADS_Circle);
	_fingerGhost2->SetColor(0.8f, 0.8f, 0.8f, 0.0f);

	theWorld.Add(_fingerGhost1, 1000);
	theWorld.Add(_fingerGhost2, 1000);
}

MobileSimulator::~MobileSimulator()
{

}

void MobileSimulator::Update(float dt)
{
	if (theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL) || theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL))
	{
		_fingerGhost1->SetAlpha(0.5f);
		_fingerGhost2->SetAlpha(0.5f);
	}
	else
	{
		_fingerGhost1->SetAlpha(0.0f);
		_fingerGhost2->SetAlpha(0.0f);
	}
}

void MobileSimulator::MouseMotionEvent(Vec2i screenCoordinates)
{
	Vector2 pos = MathUtil::ScreenToWorld(screenCoordinates);
	_fingerGhost1->SetPosition(pos);
	_fingerGhost2->SetPosition(-pos);

	if (_mouseDown)
	{
		//move touch(es)
		TouchList *tl = &TouchListener::GetTouchList();
		if (tl->size() > 0)
		{
			(*tl)[0]->CurrentPoint = screenCoordinates;
			if ( (*tl)[0]->MotionStartTime < 0.0f )
			{
				(*tl)[0]->MotionStartTime = theWorld.GetCurrentTimeSeconds();
			}
		}
		if (tl->size() > 1)
		{
			Vector2 negCoordsVec = MathUtil::WorldToScreen(-pos);
			Vec2i negCoords(negCoordsVec.X, negCoordsVec.Y);
			(*tl)[1]->CurrentPoint = negCoords;
			if ( (*tl)[1]->MotionStartTime < 0.0f )
			{
				(*tl)[1]->MotionStartTime = theWorld.GetCurrentTimeSeconds();
			}

			Touch* t1 = (*tl)[0];
			Touch* t2 = (*tl)[1];

			Vector2 start1(t1->StartingPoint);
			Vector2 current1(t1->CurrentPoint);
			Vector2 start2(t2->StartingPoint);
			Vector2 current2(t2->CurrentPoint);

			Vector2 initialVector = start2 - start1;
			Vector2 currentVector = current2 - current1;

			Vector2 initNorm = Vector2::Normalize(initialVector);
			Vector2 currentNorm = Vector2::Normalize(currentVector);
			float radiansRotated = acos(Vector2::Dot(initNorm, currentNorm));

			if (!_multiGestureOngoing)
			{
				Vector2 motion = current1 - start1;

				if (motion.LengthSquared() >= (MULTI_MIN_DISTANCE * MULTI_MIN_DISTANCE) )
				{
					_multiGestureOngoing = true;

					// figure out if it's a rotate or a pinch
					if (radiansRotated > MULTI_ROTATE_ANGLE)
					{
						_gestureType = ROTATE;
					}
					else
					{
						_gestureType = PINCH;
					}
				}
			}

			if (_multiGestureOngoing)
			{
				GestureData gd;
				gd.Velocity = 0.0f; // don't want to store all the extra datums
									//  needed to actually calculate this

				if      (_gestureType == ROTATE)
				{
					float cross = Vector2::Cross(initNorm, currentNorm);
					if (cross > 0.0f)
					{
						radiansRotated = -radiansRotated;
					}
					gd.GestureMagnitude = radiansRotated;
					theSwitchboard.Broadcast(new TypedMessage<GestureData>("MultiTouchRotate", gd));
				}
				else if (_gestureType == PINCH)
				{
					gd.GestureMagnitude = currentVector.Length() / initialVector.Length();
					theSwitchboard.Broadcast(new TypedMessage<GestureData>("MultiTouchPinch", gd));
				}
			}
		}
	}
}

void MobileSimulator::MouseDownEvent(Vec2i screenCoordinates, MouseButtonInput button)
{
	_mouseDown = true;

	TouchList* tl = &TouchListener::GetTouchList();

	if (theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL) || theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL))
	{
		// add the two touches
		Touch* t = new Touch();
		t->__platformTouch = NULL;
		t->StartingPoint = screenCoordinates;
		t->CurrentPoint = t->StartingPoint;
		tl->push_back(t);
		SendTouchNotifiers(t, TOUCH_START);

		t = new Touch();
		t->__platformTouch = NULL;
		Vector2 pos2 = MathUtil::WorldToScreen(_fingerGhost2->GetPosition());
		t->StartingPoint = Vec2i(pos2.X, pos2.Y);
		t->CurrentPoint = t->StartingPoint;
		tl->push_back(t);
		SendTouchNotifiers(t, TOUCH_START);
	}
	else
	{
		// just a single touch
		Touch* t = new Touch();
		t->__platformTouch = NULL;
		t->StartingPoint = screenCoordinates;
		t->CurrentPoint = t->StartingPoint;
		tl->push_back(t);
		SendTouchNotifiers(t, TOUCH_START);
	}
}

void MobileSimulator::MouseUpEvent(Vec2i screenCoordinates, MouseButtonInput button)
{
	_multiGestureOngoing = false;
	_gestureType = NONE;
	_mouseDown = false;

	TouchList* tl = &TouchListener::GetTouchList();

	if (theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL) || theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL))
	{
		TouchList::iterator it = tl->begin();
		while (it != tl->end())
		{
			SendTouchNotifiers((*it), TOUCH_END);
			delete (*it);
			it = tl->erase(it);
		}
	}
	else
	{
		// just a single touch, but we'll iterate anyway
		TouchList::iterator it = tl->begin();
		while (it != tl->end())
		{
			if ( (theWorld.GetCurrentTimeSeconds() - (*it)->MotionStartTime) < SWIPE_MAX_DURATION)
			{
				Vector2 start((*it)->StartingPoint.X, (*it)->StartingPoint.Y);
				Vector2 end((*it)->CurrentPoint.X, (*it)->CurrentPoint.Y);
				Vector2 motion = end - start;
				if (motion.LengthSquared() >= (SWIPE_MIN_DISTANCE * SWIPE_MIN_DISTANCE))
				{
					float angle = MathUtil::ToDegrees(acos(Vector2::Dot(Vector2::UnitX, Vector2::Normalize(motion))));
					if (motion.Y > 0.0f)
					{
						angle = 360.0f - angle;
					}

					if      ( (angle > 45.0f) && (angle <= 135.0f) )
					{
						// swipe up
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeUp"));
					}
					else if ( (angle > 135.0f) && (angle <= 225.0f) )
					{
						// swipe left
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeLeft"));
					}
					else if ( (angle > 225.0f) && (angle <= 315.0f) )
					{
						// swipe down
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeDown"));
					}
					else
					{
						// swipe right
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeRight"));
					}
				}
			}
			SendTouchNotifiers((*it), TOUCH_END);
			delete (*it);
			it = tl->erase(it);
		}
	}
}
<commit_msg>MobileSimulator was fat-fingered; need to check for either Control key.<commit_after>//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2011, Shane Liesegang
// 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 copyright holder nor the names of any
//       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.
//////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "../Input/MobileSimulator.h"

#include "../Actors/Actor.h"
#include "../Input/InputManager.h"
#include "../Input/MultiTouch.h"
#include "../Messaging/Switchboard.h"

// maximum duration of touch (in seconds) to be considered a swipe
//  (too long and we're dragging)
#define SWIPE_MAX_DURATION 0.4f
// distance in pixels the touch must go to be considered a swipe
//  (too short and it might have just been a tap)
#define SWIPE_MIN_DISTANCE 50

// distance in pixels that the touches have to move before multi-touch
//  recognition starts
#define MULTI_MIN_DISTANCE 13
// angle in radians that the touches' vectors need to shift by to
//   be considered a rotation instead of a pinch
// (equivalent of 2.5 degrees)
#define MULTI_ROTATE_ANGLE 0.0436332313f

MobileSimulator::MobileSimulator()
{
	_multiGestureOngoing = false;
	_gestureType = NONE;
	_mouseDown = false;

	_fingerGhost1 = new Actor();
	_fingerGhost1->SetSize(1.5f);
	_fingerGhost1->SetDrawShape(ADS_Circle);
	_fingerGhost1->SetColor(0.8f, 0.8f, 0.8f, 0.0f);

	_fingerGhost2 = new Actor();
	_fingerGhost2->SetSize(1.5f);
	_fingerGhost2->SetDrawShape(ADS_Circle);
	_fingerGhost2->SetColor(0.8f, 0.8f, 0.8f, 0.0f);

	theWorld.Add(_fingerGhost1, 1000);
	theWorld.Add(_fingerGhost2, 1000);
}

MobileSimulator::~MobileSimulator()
{

}

void MobileSimulator::Update(float dt)
{
	if (theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL) || theInput.IsKeyDown(ANGEL_KEY_RIGHTCONTROL))
	{
		_fingerGhost1->SetAlpha(0.5f);
		_fingerGhost2->SetAlpha(0.5f);
	}
	else
	{
		_fingerGhost1->SetAlpha(0.0f);
		_fingerGhost2->SetAlpha(0.0f);
	}
}

void MobileSimulator::MouseMotionEvent(Vec2i screenCoordinates)
{
	Vector2 pos = MathUtil::ScreenToWorld(screenCoordinates);
	_fingerGhost1->SetPosition(pos);
	_fingerGhost2->SetPosition(-pos);

	if (_mouseDown)
	{
		//move touch(es)
		TouchList *tl = &TouchListener::GetTouchList();
		if (tl->size() > 0)
		{
			(*tl)[0]->CurrentPoint = screenCoordinates;
			if ( (*tl)[0]->MotionStartTime < 0.0f )
			{
				(*tl)[0]->MotionStartTime = theWorld.GetCurrentTimeSeconds();
			}
		}
		if (tl->size() > 1)
		{
			Vector2 negCoordsVec = MathUtil::WorldToScreen(-pos);
			Vec2i negCoords(negCoordsVec.X, negCoordsVec.Y);
			(*tl)[1]->CurrentPoint = negCoords;
			if ( (*tl)[1]->MotionStartTime < 0.0f )
			{
				(*tl)[1]->MotionStartTime = theWorld.GetCurrentTimeSeconds();
			}

			Touch* t1 = (*tl)[0];
			Touch* t2 = (*tl)[1];

			Vector2 start1(t1->StartingPoint);
			Vector2 current1(t1->CurrentPoint);
			Vector2 start2(t2->StartingPoint);
			Vector2 current2(t2->CurrentPoint);

			Vector2 initialVector = start2 - start1;
			Vector2 currentVector = current2 - current1;

			Vector2 initNorm = Vector2::Normalize(initialVector);
			Vector2 currentNorm = Vector2::Normalize(currentVector);
			float radiansRotated = acos(Vector2::Dot(initNorm, currentNorm));

			if (!_multiGestureOngoing)
			{
				Vector2 motion = current1 - start1;

				if (motion.LengthSquared() >= (MULTI_MIN_DISTANCE * MULTI_MIN_DISTANCE) )
				{
					_multiGestureOngoing = true;

					// figure out if it's a rotate or a pinch
					if (radiansRotated > MULTI_ROTATE_ANGLE)
					{
						_gestureType = ROTATE;
					}
					else
					{
						_gestureType = PINCH;
					}
				}
			}

			if (_multiGestureOngoing)
			{
				GestureData gd;
				gd.Velocity = 0.0f; // don't want to store all the extra datums
									//  needed to actually calculate this

				if      (_gestureType == ROTATE)
				{
					float cross = Vector2::Cross(initNorm, currentNorm);
					if (cross > 0.0f)
					{
						radiansRotated = -radiansRotated;
					}
					gd.GestureMagnitude = radiansRotated;
					theSwitchboard.Broadcast(new TypedMessage<GestureData>("MultiTouchRotate", gd));
				}
				else if (_gestureType == PINCH)
				{
					gd.GestureMagnitude = currentVector.Length() / initialVector.Length();
					theSwitchboard.Broadcast(new TypedMessage<GestureData>("MultiTouchPinch", gd));
				}
			}
		}
	}
}

void MobileSimulator::MouseDownEvent(Vec2i screenCoordinates, MouseButtonInput button)
{
	_mouseDown = true;

	TouchList* tl = &TouchListener::GetTouchList();

	if (theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL) || theInput.IsKeyDown(ANGEL_KEY_RIGHTCONTROL))
	{
		// add the two touches
		Touch* t = new Touch();
		t->__platformTouch = NULL;
		t->StartingPoint = screenCoordinates;
		t->CurrentPoint = t->StartingPoint;
		tl->push_back(t);
		SendTouchNotifiers(t, TOUCH_START);

		t = new Touch();
		t->__platformTouch = NULL;
		Vector2 pos2 = MathUtil::WorldToScreen(_fingerGhost2->GetPosition());
		t->StartingPoint = Vec2i(pos2.X, pos2.Y);
		t->CurrentPoint = t->StartingPoint;
		tl->push_back(t);
		SendTouchNotifiers(t, TOUCH_START);
	}
	else
	{
		// just a single touch
		Touch* t = new Touch();
		t->__platformTouch = NULL;
		t->StartingPoint = screenCoordinates;
		t->CurrentPoint = t->StartingPoint;
		tl->push_back(t);
		SendTouchNotifiers(t, TOUCH_START);
	}
}

void MobileSimulator::MouseUpEvent(Vec2i screenCoordinates, MouseButtonInput button)
{
	_multiGestureOngoing = false;
	_gestureType = NONE;
	_mouseDown = false;

	TouchList* tl = &TouchListener::GetTouchList();

	if (theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL) || theInput.IsKeyDown(ANGEL_KEY_RIGHTCONTROL))
	{
		TouchList::iterator it = tl->begin();
		while (it != tl->end())
		{
			SendTouchNotifiers((*it), TOUCH_END);
			delete (*it);
			it = tl->erase(it);
		}
	}
	else
	{
		// just a single touch, but we'll iterate anyway
		TouchList::iterator it = tl->begin();
		while (it != tl->end())
		{
			if ( (theWorld.GetCurrentTimeSeconds() - (*it)->MotionStartTime) < SWIPE_MAX_DURATION)
			{
				Vector2 start((*it)->StartingPoint.X, (*it)->StartingPoint.Y);
				Vector2 end((*it)->CurrentPoint.X, (*it)->CurrentPoint.Y);
				Vector2 motion = end - start;
				if (motion.LengthSquared() >= (SWIPE_MIN_DISTANCE * SWIPE_MIN_DISTANCE))
				{
					float angle = MathUtil::ToDegrees(acos(Vector2::Dot(Vector2::UnitX, Vector2::Normalize(motion))));
					if (motion.Y > 0.0f)
					{
						angle = 360.0f - angle;
					}

					if      ( (angle > 45.0f) && (angle <= 135.0f) )
					{
						// swipe up
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeUp"));
					}
					else if ( (angle > 135.0f) && (angle <= 225.0f) )
					{
						// swipe left
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeLeft"));
					}
					else if ( (angle > 225.0f) && (angle <= 315.0f) )
					{
						// swipe down
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeDown"));
					}
					else
					{
						// swipe right
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeRight"));
					}
				}
			}
			SendTouchNotifiers((*it), TOUCH_END);
			delete (*it);
			it = tl->erase(it);
		}
	}
}
<|endoftext|>


<commit_before>#include "PID.h"

using namespace std;

/*
* TODO: Complete the PID class.
*/

PID::PID() {}

PID::~PID() {}

void PID::Init(double Kp, double Ki, double Kd) {
}

void PID::UpdateError(double cte) {
}

double PID::TotalError() {
}

<commit_msg>PID Class<commit_after>#include "PID.h"

using namespace std;

/*
* TODO: Complete the PID class.
*/

PID::PID() {
  this->p_error = 0.0;
  this->i_error = 0.0;
  this->d_error = 0.0;
}

PID::~PID() {}

void PID::Init(double Kp, double Ki, double Kd) {
  this->Kp = Kp;
  this->Ki = Ki;
  this->Kd = Kd;
}

void PID::UpdateError(double cte) {
  this->i_error += cte;
  this->d_error = cte - p_error;
  this->p_error = cte;
}

double PID::TotalError() {
  return -this->Kp * this->p_error - this->Ki * this->i_error - this->Kd * this->d_error;
}
<|endoftext|>