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

#include "nearest_neighbor_recommender.hpp"

#include <string>
#include <utility>
#include <vector>
#include "jubatus/util/data/serialization.h"
#include "jubatus/util/lang/shared_ptr.h"
#include "../common/exception.hpp"

using jubatus::util::lang::shared_ptr;

namespace jubatus {
namespace core {
namespace recommender {

class nearest_neighbor_recommender::unlearning_callback {
 public:
  explicit unlearning_callback(nearest_neighbor_recommender* recommender)
      : recommender_(recommender),
        table_(recommender_->get_table()) {
  }

  void operator()(const std::string& id) {
    recommender_->orig_.remove_row(id);
    table_->delete_row(id);
  }

 private:
  nearest_neighbor_recommender* recommender_;
  jubatus::util::lang::shared_ptr<table::column_table> table_;
};

nearest_neighbor_recommender::nearest_neighbor_recommender(
    jubatus::util::lang::shared_ptr<nearest_neighbor::nearest_neighbor_base>
        nearest_neighbor_engine)
    : nearest_neighbor_engine_(nearest_neighbor_engine) {
}

nearest_neighbor_recommender::nearest_neighbor_recommender(
    jubatus::util::lang::shared_ptr<nearest_neighbor::nearest_neighbor_base>
        nearest_neighbor_engine,
    jubatus::util::lang::shared_ptr<unlearner::unlearner_base> unlearner)
    : nearest_neighbor_engine_(nearest_neighbor_engine),
      unlearner_(unlearner) {
  unlearner_->set_callback(unlearning_callback(this));
}

void nearest_neighbor_recommender::similar_row(
    const common::sfv_t& query,
    std::vector<std::pair<std::string, float> >& ids,
    size_t ret_num) const {
  nearest_neighbor_engine_->similar_row(query, ids, ret_num);
}

void nearest_neighbor_recommender::neighbor_row(
    const common::sfv_t& query,
    std::vector<std::pair<std::string, float> >& ids,
    size_t ret_num) const {
  nearest_neighbor_engine_->neighbor_row(query, ids, ret_num);
}

void nearest_neighbor_recommender::clear() {
  orig_.clear();
  nearest_neighbor_engine_->clear();
}

void nearest_neighbor_recommender::clear_row(const std::string& id) {
  throw JUBATUS_EXCEPTION(common::unsupported_method(__func__));
}

void nearest_neighbor_recommender::update_row(
    const std::string& id,
    const common::sfv_t& diff) {
  if (unlearner_) {
    if (!unlearner_->touch(id)) {
      throw JUBATUS_EXCEPTION(common::exception::runtime_error(
          "no more space available to add new ID: " + id));
    }
  }
  orig_.set_row(id, diff);
  common::sfv_t row;
  orig_.get_row(id, row);
  nearest_neighbor_engine_->set_row(id, row);
}

void nearest_neighbor_recommender::get_all_row_ids(
    std::vector<std::string>& ids) const {
  nearest_neighbor_engine_->get_all_row_ids(ids);
}

std::string nearest_neighbor_recommender::type() const {
  return "nearest_neighbor_recommender:" + nearest_neighbor_engine_->type();
}

framework::mixable* nearest_neighbor_recommender::get_mixable() const {
  return nearest_neighbor_engine_->get_mixable();
}

void nearest_neighbor_recommender::pack(framework::packer& packer) const {
  packer.pack_array(2);
  orig_.pack(packer);
  nearest_neighbor_engine_->pack(packer);
}

void nearest_neighbor_recommender::unpack(msgpack::object o) {
  if (o.type != msgpack::type::ARRAY || o.via.array.size != 2) {
    throw msgpack::type_error();
  }
  orig_.unpack(o.via.array.ptr[0]);
  nearest_neighbor_engine_->unpack(o.via.array.ptr[1]);
}

jubatus::util::lang::shared_ptr<table::column_table>
nearest_neighbor_recommender::get_table() {
  return nearest_neighbor_engine_->get_table();
}

jubatus::util::lang::shared_ptr<const table::column_table>
nearest_neighbor_recommender::get_const_table() const {
  return nearest_neighbor_engine_->get_const_table();
}

jubatus::util::lang::shared_ptr<unlearner::unlearner_base>
nearest_neighbor_recommender::get_unlearner() {
  return unlearner_;
}

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

#include "nearest_neighbor_recommender.hpp"

#include <string>
#include <utility>
#include <vector>
#include "jubatus/util/data/serialization.h"
#include "jubatus/util/lang/shared_ptr.h"
#include "../common/exception.hpp"

using jubatus::util::lang::shared_ptr;

namespace jubatus {
namespace core {
namespace recommender {

class nearest_neighbor_recommender::unlearning_callback {
 public:
  explicit unlearning_callback(nearest_neighbor_recommender* recommender)
      : recommender_(recommender),
        table_(recommender_->get_table()) {
  }

  void operator()(const std::string& id) {
    recommender_->orig_.remove_row(id);
    table_->delete_row(id);
  }

 private:
  nearest_neighbor_recommender* recommender_;
  jubatus::util::lang::shared_ptr<table::column_table> table_;
};

nearest_neighbor_recommender::nearest_neighbor_recommender(
    jubatus::util::lang::shared_ptr<nearest_neighbor::nearest_neighbor_base>
        nearest_neighbor_engine)
    : nearest_neighbor_engine_(nearest_neighbor_engine) {
}

nearest_neighbor_recommender::nearest_neighbor_recommender(
    jubatus::util::lang::shared_ptr<nearest_neighbor::nearest_neighbor_base>
        nearest_neighbor_engine,
    jubatus::util::lang::shared_ptr<unlearner::unlearner_base> unlearner)
    : nearest_neighbor_engine_(nearest_neighbor_engine),
      unlearner_(unlearner) {
  unlearner_->set_callback(unlearning_callback(this));
}

void nearest_neighbor_recommender::similar_row(
    const common::sfv_t& query,
    std::vector<std::pair<std::string, float> >& ids,
    size_t ret_num) const {
  nearest_neighbor_engine_->similar_row(query, ids, ret_num);
}

void nearest_neighbor_recommender::neighbor_row(
    const common::sfv_t& query,
    std::vector<std::pair<std::string, float> >& ids,
    size_t ret_num) const {
  nearest_neighbor_engine_->neighbor_row(query, ids, ret_num);
}

void nearest_neighbor_recommender::clear() {
  orig_.clear();
  nearest_neighbor_engine_->clear();
  if (unlearner_) {
    unlearner_->clear();
  }
}

void nearest_neighbor_recommender::clear_row(const std::string& id) {
  throw JUBATUS_EXCEPTION(common::unsupported_method(__func__));
}

void nearest_neighbor_recommender::update_row(
    const std::string& id,
    const common::sfv_t& diff) {
  if (unlearner_) {
    if (!unlearner_->touch(id)) {
      throw JUBATUS_EXCEPTION(common::exception::runtime_error(
          "no more space available to add new ID: " + id));
    }
  }
  orig_.set_row(id, diff);
  common::sfv_t row;
  orig_.get_row(id, row);
  nearest_neighbor_engine_->set_row(id, row);
}

void nearest_neighbor_recommender::get_all_row_ids(
    std::vector<std::string>& ids) const {
  nearest_neighbor_engine_->get_all_row_ids(ids);
}

std::string nearest_neighbor_recommender::type() const {
  return "nearest_neighbor_recommender:" + nearest_neighbor_engine_->type();
}

framework::mixable* nearest_neighbor_recommender::get_mixable() const {
  return nearest_neighbor_engine_->get_mixable();
}

void nearest_neighbor_recommender::pack(framework::packer& packer) const {
  packer.pack_array(2);
  orig_.pack(packer);
  nearest_neighbor_engine_->pack(packer);
}

void nearest_neighbor_recommender::unpack(msgpack::object o) {
  if (o.type != msgpack::type::ARRAY || o.via.array.size != 2) {
    throw msgpack::type_error();
  }
  orig_.unpack(o.via.array.ptr[0]);
  nearest_neighbor_engine_->unpack(o.via.array.ptr[1]);
}

jubatus::util::lang::shared_ptr<table::column_table>
nearest_neighbor_recommender::get_table() {
  return nearest_neighbor_engine_->get_table();
}

jubatus::util::lang::shared_ptr<const table::column_table>
nearest_neighbor_recommender::get_const_table() const {
  return nearest_neighbor_engine_->get_const_table();
}

jubatus::util::lang::shared_ptr<unlearner::unlearner_base>
nearest_neighbor_recommender::get_unlearner() {
  return unlearner_;
}

}  // namespace recommender
}  // namespace core
}  // namespace jubatus
<|endoftext|>


<commit_before>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <ctype.h>                                          /* isxxx() */
#include <ros/ros.h>                                        /* ROS */
#include <geometry_msgs/Twist.h>                            /* ROS Twist message */
#include <base_controller/encoders.h>                       /* Custom message /encoders */
#include <base_controller/md49data.h>                       /* Custom message /encoders */

#include <serialport/serialport.h>
#define REPLY_SIZE 18
#define TIMEOUT 1000

int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
char reply[REPLY_SIZE];
char speed_l=128;
char speed_r=128;                                  /* speed to set for MD49 */
char last_speed_l=128, last_speed_r=128;           /* speed to set for MD49 */
double vr = 0.0;
double vl = 0.0;
double max_vr = 0.2;
double max_vl = 0.2;
double min_vr = 0.2;
double min_vl = 0.2;
double base_width = 0.4;                                    /* Base width in meters */

unsigned char serialBuffer[18];                             /* Serial buffer to store uart data */
void read_MD49_Data (void);
void write_MD49_speed (unsigned char speed_l, unsigned char speed_r);
void set_MD49_speed (void);
char* itoa(int value, char* result, int base);

using namespace std;
cereal::CerealPort device;
base_controller::encoders encoders;
base_controller::md49data md49data;

void cmd_vel_callback(const geometry_msgs::Twist& vel_cmd){

        if (vel_cmd.linear.x>0){
            speed_l = 255;
            speed_r = 255;
        }
        if (vel_cmd.linear.x<0){
            speed_l = 0;
            speed_r = 0;
        }
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){
            speed_l = 128;
            speed_r = 128;
        }
        if (vel_cmd.angular.z>0){
            speed_l = 0;
            speed_r = 255;
        }
        if (vel_cmd.angular.z<0){
            speed_l = 255;
            speed_r = 0;
        }

    /*
        //ANFANG Alternative
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){vl=0;vr=0;}
        else if(vel_cmd.linear.x == 0){
            // turning
            vr = vel_cmd.angular.z * base_width / 2.0;
            vl = (-1) * vr;
        }
        else if(vel_cmd.angular.z == 0){
            // forward / backward
            vl = vr = vel_cmd.linear.x;
        }
        else{
            // moving doing arcs
            vl = vel_cmd.linear.x - vel_cmd.angular.z * base_width / 2.0;
            if (vl > max_vl) {vl=max_vl;}
            if (vl < min_vl) {vl=min_vl;}
            vr = vel_cmd.linear.x + vel_cmd.angular.z * base_width / 2.0;
            if (vr > max_vr) {vr=max_vr;}
            if (vr < min_vr) {vr=min_vr;}
        }
        //ENDE Alternative
    */
}

int main( int argc, char* argv[] ){

    ros::init(argc, argv, "base_controller" );
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("/cmd_vel", 10, cmd_vel_callback);
    ros::Publisher encoders_pub = n.advertise<base_controller::encoders>("encoders",10);
    ros::Publisher md49data_pub = n.advertise<base_controller::md49data>("md49data",10);

    // Init node
    // *********
    ros::Rate loop_rate(10);
    ROS_INFO("base_controller running...");
    ROS_INFO("=============================");
    ROS_INFO("Subscribing to topic /cmd_vel");
    ROS_INFO("Publishing to topic /encoders");
    ROS_INFO("Publishing to topic /md49data");

    // Open serial port
    // ****************
    try{ device.open("/dev/ttyAMA0", 38400); }
    catch(cereal::Exception& e)
    {
      ROS_FATAL("Failed to open the serial port!!!");
      ROS_BREAK();
    }
    ROS_INFO("The serial port is opened.");

    while(n.ok())
    {
        // Read encoder and other data from MD49
        // (data is read from serial_controller_node
        //  and avaiable through md49_data.txt)
        // *****************************************
        read_MD49_Data();

        // set speed as in md49speed.txt
        // *****************************
        if ((speed_l != last_speed_l) || (speed_r != last_speed_r)){
            // gewünschte werte in textfile
            write_MD49_speed(speed_l,speed_r);
            set_MD49_speed();
            last_speed_l=speed_l;
            last_speed_r=speed_r;
        }

        // Publish encoder values to topic /encoders (custom message)
        // **********************************************************
        encoders.encoder_l=EncoderL;
        encoders.encoder_r=EncoderR;
        encoders_pub.publish(encoders);

        // Publish MD49 data to topic /md49data (custom message)
        // *****************************************************
        md49data.speed_l = reply[8];
        md49data.speed_r = reply[9];
        md49data.volt = reply[10];
        md49data.current_l = reply[11];
        md49data.current_r = reply[12];
        md49data.error = reply[13];
        md49data.acceleration = reply[14];
        md49data.mode = reply[15];
        md49data.regulator = reply[16];
        md49data.timeout = reply[17];
        md49data_pub.publish(md49data);

        // ****
        ros::spinOnce();
        loop_rate.sleep();

    }// end.mainloop

    return 1;
} // end.main

void read_MD49_Data (void){

    // Send 'R' over the serial port
    device.write("R");
    // Get the reply, the last value is the timeout in ms
    try{ device.read(reply, REPLY_SIZE, TIMEOUT); }
    catch(cereal::TimeoutException& e)
    {
      ROS_ERROR("Timeout on serialport! No data read");
    }
    //ROS_INFO("Received MD49 data");

    // Put toghether new encodervalues
    // *******************************
    EncoderL = reply[0] << 24;                        // Put together first encoder value
    EncoderL |= (reply[1] << 16);
    EncoderL |= (reply[2] << 8);
    EncoderL |= (reply[3]);
    EncoderR = reply[4] << 24;                        // Put together second encoder value
    EncoderR |= (reply[5] << 16);
    EncoderR |= (reply[6] << 8);
    EncoderR |= (reply[7]);

/*
    // Output MD49 data on screen
    // **************************
    printf("\033[2J");                                      //  clear the screen
    printf("\033[H");                                       //  position cursor at top-left corner
    printf ("MD49-Data read from AVR-Master: \n");
    printf("========================================\n");
    printf("Encoder1 Byte1: %i ",reply[0]);
    printf("Byte2: %i ",reply[1]);
    printf("Byte3: % i ",reply[2]);
    printf("Byte4: %i \n",reply[3]);
    printf("Encoder2 Byte1: %i ",reply[4]);
    printf("Byte2: %i ",reply[5]);
    printf("Byte3: %i ",reply[6]);
    printf("Byte4: %i \n",reply[7]);
    printf("EncoderL: %i ",EncoderL);
    printf("EncoderR: %i \n",EncoderR);
    printf("========================================\n");
    printf("Speed1: %i ",reply[8]);
    printf("Speed2: %i \n",reply[9]);
    printf("Volts: %i \n",reply[10]);
    printf("Current1: %i ",reply[11]);
    printf("Current2: %i \n",reply[12]);
    printf("Error: %i \n",reply[13]);
    printf("Acceleration: %i \n",reply[14]);
    printf("Mode: %i \n",reply[15]);
    printf("Regulator: %i \n",reply[16]);
    printf("Timeout: %i \n",reply[17]);
*/

}

void write_MD49_speed (unsigned char speed_l, unsigned char speed_r){

    char buffer[33];
    ofstream myfile;
    myfile.open ("md49speed.txt");
    //myfile << "Writing this to a file.\n";
    if (speed_l==0){
        myfile << "000";
        myfile << "\n";
    }
    else if (speed_l<10){
        myfile << "00";
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }
    else if (speed_l<100){
        myfile << "0";
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }
    else{
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }

    if (speed_r==0){
        myfile << "000";
        myfile << "\n";
    }
    else if (speed_r<10){
        myfile << "00";
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    else if (speed_r<100){
        myfile << "0";
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    else{
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    myfile.close();

}

void set_MD49_speed(void){
    unsigned char md49_speed[2];                                /* keeps data from MD49, read from AVR-Master */
    string line;
    string arrayOfString[2];
    ifstream myfile ("md49speed.txt");
    if (myfile.is_open()){
        int i=0;
        while ( getline (myfile,line) )
        {
            //cout << line << '\n';
            char data[10];
            std::copy(line.begin(), line.end(), data);
            md49_speed[i]=atoi(data);
            arrayOfString[i]=atoi(data);
            i =i++;
        }
        myfile.close();
        speed_l=md49_speed[0];
        speed_r=md49_speed[1];
    }
    else{
        cout << "Unable to open file";
    }
    const char* pointerToSpeedL =  arrayOfString[0].c_str();
    const char* pointerToSpeedR =  arrayOfString[1].c_str();
    device.write("Xs",2);
    device.write(pointerToSpeedL,1);
    device.write(pointerToSpeedR,1);

}

char* itoa(int value, char* result, int base) {
        // check that the base if valid
        if (base < 2 || base > 36) { *result = '\0'; return result; }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
            tmp_value = value;
            value /= base;
            *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        // Apply negative sign
        if (tmp_value < 0) *ptr++ = '-';
        *ptr-- = '\0';
        while(ptr1 < ptr) {
            tmp_char = *ptr;
            *ptr--= *ptr1;
            *ptr1++ = tmp_char;
        }
        return result;
}
<commit_msg>Update code<commit_after>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <ctype.h>                                          /* isxxx() */
#include <ros/ros.h>                                        /* ROS */
#include <geometry_msgs/Twist.h>                            /* ROS Twist message */
#include <base_controller/encoders.h>                       /* Custom message /encoders */
#include <base_controller/md49data.h>                       /* Custom message /encoders */

#include <serialport/serialport.h>
#define REPLY_SIZE 18
#define TIMEOUT 1000

int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
char reply[REPLY_SIZE];
char speed_l=128;
char speed_r=128;                                  /* speed to set for MD49 */
char last_speed_l=128, last_speed_r=128;           /* speed to set for MD49 */
double vr = 0.0;
double vl = 0.0;
double max_vr = 0.2;
double max_vl = 0.2;
double min_vr = 0.2;
double min_vl = 0.2;
double base_width = 0.4;                                    /* Base width in meters */

unsigned char serialBuffer[18];                             /* Serial buffer to store uart data */
void read_MD49_Data (void);
void write_MD49_speed (unsigned char speed_l, unsigned char speed_r);
void set_MD49_speed (void);
char* itoa(int value, char* result, int base);

using namespace std;
cereal::CerealPort device;
base_controller::encoders encoders;
base_controller::md49data md49data;

void cmd_vel_callback(const geometry_msgs::Twist& vel_cmd){

        if (vel_cmd.linear.x>0){
            speed_l = 255;
            speed_r = 255;
            device.write("Xsÿÿ",2);
        }
        if (vel_cmd.linear.x<0){
            speed_l = 0;
            speed_r = 0;
        }
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){
            speed_l = 128;
            speed_r = 128;
            device.write("Xs€€",2);
        }
        if (vel_cmd.angular.z>0){
            speed_l = 0;
            speed_r = 255;
        }
        if (vel_cmd.angular.z<0){
            speed_l = 255;
            speed_r = 0;
        }

    /*
        //ANFANG Alternative
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){vl=0;vr=0;}
        else if(vel_cmd.linear.x == 0){
            // turning
            vr = vel_cmd.angular.z * base_width / 2.0;
            vl = (-1) * vr;
        }
        else if(vel_cmd.angular.z == 0){
            // forward / backward
            vl = vr = vel_cmd.linear.x;
        }
        else{
            // moving doing arcs
            vl = vel_cmd.linear.x - vel_cmd.angular.z * base_width / 2.0;
            if (vl > max_vl) {vl=max_vl;}
            if (vl < min_vl) {vl=min_vl;}
            vr = vel_cmd.linear.x + vel_cmd.angular.z * base_width / 2.0;
            if (vr > max_vr) {vr=max_vr;}
            if (vr < min_vr) {vr=min_vr;}
        }
        //ENDE Alternative
    */
}

int main( int argc, char* argv[] ){

    ros::init(argc, argv, "base_controller" );
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("/cmd_vel", 10, cmd_vel_callback);
    ros::Publisher encoders_pub = n.advertise<base_controller::encoders>("encoders",10);
    ros::Publisher md49data_pub = n.advertise<base_controller::md49data>("md49data",10);

    // Init node
    // *********
    ros::Rate loop_rate(10);
    ROS_INFO("base_controller running...");
    ROS_INFO("=============================");
    ROS_INFO("Subscribing to topic /cmd_vel");
    ROS_INFO("Publishing to topic /encoders");
    ROS_INFO("Publishing to topic /md49data");

    // Open serial port
    // ****************
    try{ device.open("/dev/ttyAMA0", 38400); }
    catch(cereal::Exception& e)
    {
      ROS_FATAL("Failed to open the serial port!!!");
      ROS_BREAK();
    }
    ROS_INFO("The serial port is opened.");

    while(n.ok())
    {
        // Read encoder and other data from MD49
        // (data is read from serial_controller_node
        //  and avaiable through md49_data.txt)
        // *****************************************
        read_MD49_Data();

        // set speed as in md49speed.txt
        // *****************************
        if ((speed_l != last_speed_l) || (speed_r != last_speed_r)){
            // gewünschte werte in textfile
            //write_MD49_speed(speed_l,speed_r);
            //set_MD49_speed();
           // last_speed_l=speed_l;
           // last_speed_r=speed_r;
        }

        // Publish encoder values to topic /encoders (custom message)
        // **********************************************************
        encoders.encoder_l=EncoderL;
        encoders.encoder_r=EncoderR;
        encoders_pub.publish(encoders);

        // Publish MD49 data to topic /md49data (custom message)
        // *****************************************************
        md49data.speed_l = reply[8];
        md49data.speed_r = reply[9];
        md49data.volt = reply[10];
        md49data.current_l = reply[11];
        md49data.current_r = reply[12];
        md49data.error = reply[13];
        md49data.acceleration = reply[14];
        md49data.mode = reply[15];
        md49data.regulator = reply[16];
        md49data.timeout = reply[17];
        md49data_pub.publish(md49data);

        // ****
        ros::spinOnce();
        loop_rate.sleep();

    }// end.mainloop

    return 1;
} // end.main

void read_MD49_Data (void){

    // Send 'R' over the serial port
    device.write("R");
    // Get the reply, the last value is the timeout in ms
    try{ device.read(reply, REPLY_SIZE, TIMEOUT); }
    catch(cereal::TimeoutException& e)
    {
      ROS_ERROR("Timeout on serialport! No data read");
    }
    //ROS_INFO("Received MD49 data");

    // Put toghether new encodervalues
    // *******************************
    EncoderL = reply[0] << 24;                        // Put together first encoder value
    EncoderL |= (reply[1] << 16);
    EncoderL |= (reply[2] << 8);
    EncoderL |= (reply[3]);
    EncoderR = reply[4] << 24;                        // Put together second encoder value
    EncoderR |= (reply[5] << 16);
    EncoderR |= (reply[6] << 8);
    EncoderR |= (reply[7]);

/*
    // Output MD49 data on screen
    // **************************
    printf("\033[2J");                                      //  clear the screen
    printf("\033[H");                                       //  position cursor at top-left corner
    printf ("MD49-Data read from AVR-Master: \n");
    printf("========================================\n");
    printf("Encoder1 Byte1: %i ",reply[0]);
    printf("Byte2: %i ",reply[1]);
    printf("Byte3: % i ",reply[2]);
    printf("Byte4: %i \n",reply[3]);
    printf("Encoder2 Byte1: %i ",reply[4]);
    printf("Byte2: %i ",reply[5]);
    printf("Byte3: %i ",reply[6]);
    printf("Byte4: %i \n",reply[7]);
    printf("EncoderL: %i ",EncoderL);
    printf("EncoderR: %i \n",EncoderR);
    printf("========================================\n");
    printf("Speed1: %i ",reply[8]);
    printf("Speed2: %i \n",reply[9]);
    printf("Volts: %i \n",reply[10]);
    printf("Current1: %i ",reply[11]);
    printf("Current2: %i \n",reply[12]);
    printf("Error: %i \n",reply[13]);
    printf("Acceleration: %i \n",reply[14]);
    printf("Mode: %i \n",reply[15]);
    printf("Regulator: %i \n",reply[16]);
    printf("Timeout: %i \n",reply[17]);
*/

}

void write_MD49_speed (unsigned char speed_l, unsigned char speed_r){

    char buffer[33];
    ofstream myfile;
    myfile.open ("md49speed.txt");
    //myfile << "Writing this to a file.\n";
    if (speed_l==0){
        myfile << "000";
        myfile << "\n";
    }
    else if (speed_l<10){
        myfile << "00";
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }
    else if (speed_l<100){
        myfile << "0";
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }
    else{
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }

    if (speed_r==0){
        myfile << "000";
        myfile << "\n";
    }
    else if (speed_r<10){
        myfile << "00";
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    else if (speed_r<100){
        myfile << "0";
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    else{
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    myfile.close();

}

void set_MD49_speed(void){
    unsigned char md49_speed[2];                                /* keeps data from MD49, read from AVR-Master */
    string line;
    string arrayOfString[2];
    ifstream myfile ("md49speed.txt");
    if (myfile.is_open()){
        int i=0;
        while ( getline (myfile,line) )
        {
            //cout << line << '\n';
            char data[10];
            std::copy(line.begin(), line.end(), data);
            md49_speed[i]=atoi(data);
            arrayOfString[i]=atoi(data);
            i =i++;
        }
        myfile.close();
        speed_l=md49_speed[0];
        speed_r=md49_speed[1];
    }
    else{
        cout << "Unable to open file";
    }
    const char* pointerToSpeedL =  arrayOfString[0].c_str();
    const char* pointerToSpeedR =  arrayOfString[1].c_str();
    device.write("Xs",2);
    device.write(pointerToSpeedL,1);
    device.write(pointerToSpeedR,1);

}

char* itoa(int value, char* result, int base) {
        // check that the base if valid
        if (base < 2 || base > 36) { *result = '\0'; return result; }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
            tmp_value = value;
            value /= base;
            *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        // Apply negative sign
        if (tmp_value < 0) *ptr++ = '-';
        *ptr-- = '\0';
        while(ptr1 < ptr) {
            tmp_char = *ptr;
            *ptr--= *ptr1;
            *ptr1++ = tmp_char;
        }
        return result;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include "consoleui.h"
#include "scientist.h"

using namespace std;

ConsoleUI::ConsoleUI()
{

}

// Should not contain logic for individual commands, that should be in separate functions!
void ConsoleUI::run()
{
    string command;
    do
    {
        cout << "Select one of the following options: " << endl;
        cout << "Add - add a programmer/computer scientist" << endl;
        cout << "List - show a list of all programmer's/computer scientist's" << endl;
        cout << "Search - search the list of programmer's/computer scientist's" << endl;
        cout << "Quit - end program" << endl;

        cin >> command;
        for(unsigned int i = 0; i < command.length(); i++) // to make all lowercase, taken from c++ site
        {
            command[i] = tolower(command[i]);
        }

        cout << endl;

        if(command == "add") // Could possibly be improved upon
        {
           userMenuAdd();
        }
        else if(command == "list") // Could possibly be improved upon
        {
           userMenuList();
        }
        else if(command == "search") // Could possibly be improved upon
        {
           userMenuSearch();
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(command != "quit");

}
void ConsoleUI::userMenuAdd()
{
    string name;
    char gender;
    int birthYear;
    int deathYear = 0;

    cout << "Enter the programmer's/computer scientist's name: ";
    cin.ignore();
    getline(cin, name);

    bool check = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's gender (m/f): ";
        cin >> gender;

        if((gender != 'm') && (gender != 'f'))
        {
            cout << "Invalid input" << endl;
        }
        else
        {
            cout << endl;
            check = false;
        }
    }while(check == true);

    bool check2 = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's year of birth: ";
        cin >> birthYear;
        if(birthYear < 2016) // Just in case we find a programmer of the univers
        {
            cout << endl;
            check2 = false;
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(check2 == true);

    bool check3 = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's year of death (type 0 if not applicable): ";
        cin >> deathYear;
        if(deathYear >= birthYear)
        {
            cout << endl;
            check3 = false;
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(check3 == true);

    _service.addScientist(name, gender, birthYear, deathYear);
}
void ConsoleUI::userMenuList()
{
    vector<Scientist> scientist = _service.getScientists();

    cout << "Scientist name:" << endl;
    cout << "===============" << endl;
    for (size_t i = 0; i< scientist.size(); ++i)
    {
        cout << scientist[i].getName() << endl;
    }
    cout << endl;
}
void ConsoleUI::userMenuSearch()
{
    string command;
    cout << "Select a search option: " << endl;
    cout << "Name - Search by name" << endl;
    cout << "Birth - Search by year of birth" << endl;
    cout << "Death - search by year of death" << endl;
    cin >> command;

    if(command == "name" || command == "Name" || command == "NAME")
    {
        vector<Scientist> scientist = _service.getScientists();
        string nameInputSearch;
        cout << "Enter a name to search: ";
        cin >> nameInputSearch;

        for(unsigned int i = 0; i < scientist.size(); ++i)
        {
            if(scientist[i].getName() == nameInputSearch)
            {
                cout << scientist[i].getName() << endl;
            }
        }
    }
    else if(command == "birth" || command == "Birth" || command == "BIRTH")
    {

    }
    else if(command == "death" || command == "Death" || command == "DEATH")
    {

    }

}
<commit_msg>Fix 0 error<commit_after>#include <iostream>
#include <string>
#include "consoleui.h"
#include "scientist.h"

using namespace std;

ConsoleUI::ConsoleUI()
{

}

// Should not contain logic for individual commands, that should be in separate functions!
void ConsoleUI::run()
{
    string command;
    do
    {
        cout << "Select one of the following options: " << endl;
        cout << "Add - add a programmer/computer scientist" << endl;
        cout << "List - show a list of all programmer's/computer scientist's" << endl;
        cout << "Search - search the list of programmer's/computer scientist's" << endl;
        cout << "Quit - end program" << endl;

        cin >> command;
        for(unsigned int i = 0; i < command.length(); i++) // to make all lowercase, taken from c++ site
        {
            command[i] = tolower(command[i]);
        }

        cout << endl;

        if(command == "add") // Could possibly be improved upon
        {
           userMenuAdd();
        }
        else if(command == "list") // Could possibly be improved upon
        {
           userMenuList();
        }
        else if(command == "search") // Could possibly be improved upon
        {
           userMenuSearch();
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(command != "quit");

}
void ConsoleUI::userMenuAdd()
{
    string name;
    char gender;
    int birthYear;
    int deathYear = 0;

    cout << "Enter the programmer's/computer scientist's name: ";
    cin.ignore();
    getline(cin, name);

    bool check = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's gender (m/f): ";
        cin >> gender;

        if((gender != 'm') && (gender != 'f'))
        {
            cout << "Invalid input" << endl;
        }
        else
        {
            cout << endl;
            check = false;
        }
    }while(check == true);

    bool check2 = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's year of birth: ";
        cin >> birthYear;
        if(birthYear < 2016) // Just in case we find a programmer of the univers
        {
            cout << endl;
            check2 = false;
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(check2 == true);

    bool check3 = true;
    do
    {
        cout << "Enter the programmer's/computer scientist's year of death (type 0 if not applicable): ";
        cin >> deathYear;
        if (deathYear == 0)
        {
            cout << endl;
            check3 = false;
        }
        else if(deathYear >= birthYear)
        {
            cout << endl;
            check3 = false;
        }
        else
        {
            cout << "Invalid input" << endl;
        }
    }while(check3 == true);

    _service.addScientist(name, gender, birthYear, deathYear);
}
void ConsoleUI::userMenuList()
{
    vector<Scientist> scientist = _service.getScientists();

    cout << "Scientist name:" << endl;
    cout << "===============" << endl;
    for (size_t i = 0; i< scientist.size(); ++i)
    {
        cout << scientist[i].getName() << endl;
    }
    cout << endl;
}
void ConsoleUI::userMenuSearch()
{
    string command;
    cout << "Select a search option: " << endl;
    cout << "Name - Search by name" << endl;
    cout << "Birth - Search by year of birth" << endl;
    cout << "Death - search by year of death" << endl;
    cin >> command;

    if(command == "name" || command == "Name" || command == "NAME")
    {
        vector<Scientist> scientist = _service.getScientists();
        string nameInputSearch;
        cout << "Enter a name to search: ";
        cin >> nameInputSearch;

        for(unsigned int i = 0; i < scientist.size(); ++i)
        {
            if(scientist[i].getName() == nameInputSearch)
            {
                cout << scientist[i].getName() << endl;
            }
        }
    }
    else if(command == "birth" || command == "Birth" || command == "BIRTH")
    {

    }
    else if(command == "death" || command == "Death" || command == "DEATH")
    {

    }

}
<|endoftext|>


<commit_before>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/* linbox/tests/test-common.C
 * Copyright (C) 2001, 2002 Bradford Hovinen
 *
 * Written by Bradford Hovinen <hovinen@cis.udel.edu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "linbox-config.h"

#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cmath>

#include "linbox/util/commentator.h"
#include "linbox/field/archetype.h"

#include "test-common.h"

using namespace LinBox;

/* Display a help message on command usage */

void printHelpMessage (const char *program, Argument *args, bool printDefaults = false)
{
	int i, l;

	// Skip past libtool prefix in program name
	if (!strncmp (program, "lt-", strlen ("lt-")))
		program += strlen ("lt-");

	std::cout << "Usage: " << program << " [options] [<report file>]" << std::endl;
	std::cout << std::endl;
	std::cout << "Where [options] are the following:" << std::endl;

	for (i = 0; args[i].c != '\0'; i++) {
		if (args[i].example != 0) {
			std::cout << "  " << args[i].example;
			l = 10 - strlen (args[i].example);
			do std::cout << ' '; while (--l > 0);
		}
		else if (args[i].type == TYPE_NONE)
			std::cout << "  -" << args[i].c << " {YN+-} ";
		else
			std::cout << "  -" << args[i].c << ' ' << args[i].c << "      ";

		std::cout << args[i].helpString;
		if (printDefaults) {
			l = 54 - strlen (args[i].helpString);
			do std::cout << ' '; while (--l > 0);
			std::cout << " (default ";
			switch (args[i].type) {
			case TYPE_NONE:
				cout << ((*(bool *)args[i].data)?"ON":"OFF");
				break;
			case TYPE_INT:
				cout << *(int *) args[i].data;
				break;
			case TYPE_INTEGER:
				cout << *(Integer *) args[i].data;
				break;
			case TYPE_DOUBLE:
				cout << *(double *) args[i].data;
				break;
			}
			std::cout << ")";
		}
		std::cout << std::endl;
	}

	std::cout << "  -h or -?  Display this message" << std::endl;
	std::cout << "For boolean switches, the argument may be omitted, meaning the switch should be ON" << std::endl;
	std::cout << std::endl;
	std::cout << "If <report file> is not given, then no detailed reporting is done. This is" << std::endl;
	std::cout << "suitable if you wish only to determine whether the tests succeeded." << std::endl;
	std::cout << std::endl;
	std::cout << "[1] N.B. This program does not verify the primality of Q, and does not use a" << std::endl;
	std::cout << "    field extension in the event that Q=p^n, n > 1" << std::endl;
	std::cout << std::endl;
}

/* Find an argument in the argument list for a character */

Argument *findArgument (Argument *args, char c)
{
	int i;

	for (i = 0; args[i].c != '\0' && args[i].c != c; i++);

	if (args[i].c != '\0')
		return &(args[i]);
	else
		return (Argument *) 0;
}

/* Parse command line arguments */

void parseArguments (int argc, char **argv, Argument *args, bool printDefaults = false)
{
	int i;
	Argument *current;

	for (i = 1; i < argc; i++) {
		if (argv[i][0] == '-') {
			if (argv[i][1] == 'h' || argv[i][1] == '?') {
				printHelpMessage (argv[0], args, printDefaults);
				exit (1);
			}
			else if ((current = findArgument (args, argv[i][1])) != (Argument *) 0) {
				switch (current->type) {
				case TYPE_NONE:
					if (argc == i+1 || (argv[i+1][0] == '-' && argv[i+1][1] != '\0')) {
						// if last argument, or next argument is a switch, set to true
						*(bool *) current->data = true;
						break;
					}
					*(bool *) current->data = (argv[i+1][0] == '+' || argv[i+1][0] == 'Y' || argv[i+1][0] == 'y'
								   || argv[i+1][0] == 'T' || argv[i+1][0] == 't') ;
					i++;
					break;

				case TYPE_INT:
					*(int *) current->data = atoi (argv[i+1]);
					i++;
					break;

				case TYPE_INTEGER:
					*(integer *) current->data = atoi (argv[i+1]);
					i++;
					break;

				case TYPE_DOUBLE:
					*(double *) current->data = atof (argv[i+1]);
					i++;
					break;
				}
			} else {
				std::cerr << "ERROR: Bad argument " << argv[i] << std::endl;
				break;
			}
		} else {
			commentator.setDefaultReportFile (argv[i]);
			std::cout << "Writing report data to " << argv[i] << std::endl << std::endl;
			std::cout.flush ();
		}
	}
}

std::ostream& writeCommandString (std::ostream& os, Argument *args, char* programName) {
	os << programName;
	for (int i = 0; args[i].c != '\0'; i++) {
		cout << " -" << args[i].c;
		switch (args[i].type) {
		case TYPE_NONE:
			if (! (*(bool *)args[i].data)) os << " N";
			break;
		case TYPE_INT:
			os << ' ' << *(int *) args[i].data;
			break;
		case TYPE_INTEGER:
			os << ' ' << *(Integer *) args[i].data;
			break;
		case TYPE_DOUBLE:
			os << ' ' << *(double *) args[i].data;
			break;
		}
	}
	return os << std::endl;
}

bool isPower (integer n, integer m)
{
	return (n == 1) || ((n % m) == 0) && isPower (n/m, m);
}

inline double incompleteGamma (double a, double x, double tol)
{
	double xa_ex = pow (x, a) * exp (-x);
	double pi = 1.0;
	double xn = 1.0;
	double sigma = 0.0;
	double last_sigma;

	int n = 0;

	do {
		pi *= a + n;
		last_sigma = sigma;
		sigma += xn / pi;
		xn *= x;
		++n;
	} while (abs (sigma - last_sigma) >= tol);

	return sigma * xa_ex;
}

double chiSquaredCDF (double chi_sqr, double df)
{
	return incompleteGamma (df / 2.0, chi_sqr / 2.0, 1e-10) / exp (gamma (df / 2.0));
}

<commit_msg>Removed default initialization of last arg of parseArgument:  didn't compile since it was already initialized in the declaration in test-common.h<commit_after>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/* linbox/tests/test-common.C
 * Copyright (C) 2001, 2002 Bradford Hovinen
 *
 * Written by Bradford Hovinen <hovinen@cis.udel.edu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "linbox-config.h"

#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cmath>

#include "linbox/util/commentator.h"
#include "linbox/field/archetype.h"

#include "test-common.h"

using namespace LinBox;

/* Display a help message on command usage */

void printHelpMessage (const char *program, Argument *args, bool printDefaults = false)
{
	int i, l;

	// Skip past libtool prefix in program name
	if (!strncmp (program, "lt-", strlen ("lt-")))
		program += strlen ("lt-");

	std::cout << "Usage: " << program << " [options] [<report file>]" << std::endl;
	std::cout << std::endl;
	std::cout << "Where [options] are the following:" << std::endl;

	for (i = 0; args[i].c != '\0'; i++) {
		if (args[i].example != 0) {
			std::cout << "  " << args[i].example;
			l = 10 - strlen (args[i].example);
			do std::cout << ' '; while (--l > 0);
		}
		else if (args[i].type == TYPE_NONE)
			std::cout << "  -" << args[i].c << " {YN+-} ";
		else
			std::cout << "  -" << args[i].c << ' ' << args[i].c << "      ";

		std::cout << args[i].helpString;
		if (printDefaults) {
			l = 54 - strlen (args[i].helpString);
			do std::cout << ' '; while (--l > 0);
			std::cout << " (default ";
			switch (args[i].type) {
			case TYPE_NONE:
				cout << ((*(bool *)args[i].data)?"ON":"OFF");
				break;
			case TYPE_INT:
				cout << *(int *) args[i].data;
				break;
			case TYPE_INTEGER:
				cout << *(Integer *) args[i].data;
				break;
			case TYPE_DOUBLE:
				cout << *(double *) args[i].data;
				break;
			}
			std::cout << ")";
		}
		std::cout << std::endl;
	}

	std::cout << "  -h or -?  Display this message" << std::endl;
	std::cout << "For boolean switches, the argument may be omitted, meaning the switch should be ON" << std::endl;
	std::cout << std::endl;
	std::cout << "If <report file> is not given, then no detailed reporting is done. This is" << std::endl;
	std::cout << "suitable if you wish only to determine whether the tests succeeded." << std::endl;
	std::cout << std::endl;
	std::cout << "[1] N.B. This program does not verify the primality of Q, and does not use a" << std::endl;
	std::cout << "    field extension in the event that Q=p^n, n > 1" << std::endl;
	std::cout << std::endl;
}

/* Find an argument in the argument list for a character */

Argument *findArgument (Argument *args, char c)
{
	int i;

	for (i = 0; args[i].c != '\0' && args[i].c != c; i++);

	if (args[i].c != '\0')
		return &(args[i]);
	else
		return (Argument *) 0;
}

/* Parse command line arguments */

void parseArguments (int argc, char **argv, Argument *args, bool printDefaults)
{
	int i;
	Argument *current;

	for (i = 1; i < argc; i++) {
		if (argv[i][0] == '-') {
			if (argv[i][1] == 'h' || argv[i][1] == '?') {
				printHelpMessage (argv[0], args, printDefaults);
				exit (1);
			}
			else if ((current = findArgument (args, argv[i][1])) != (Argument *) 0) {
				switch (current->type) {
				case TYPE_NONE:
					if (argc == i+1 || (argv[i+1][0] == '-' && argv[i+1][1] != '\0')) {
						// if last argument, or next argument is a switch, set to true
						*(bool *) current->data = true;
						break;
					}
					*(bool *) current->data = (argv[i+1][0] == '+' || argv[i+1][0] == 'Y' || argv[i+1][0] == 'y'
								   || argv[i+1][0] == 'T' || argv[i+1][0] == 't') ;
					i++;
					break;

				case TYPE_INT:
					*(int *) current->data = atoi (argv[i+1]);
					i++;
					break;

				case TYPE_INTEGER:
					*(integer *) current->data = atoi (argv[i+1]);
					i++;
					break;

				case TYPE_DOUBLE:
					*(double *) current->data = atof (argv[i+1]);
					i++;
					break;
				}
			} else {
				std::cerr << "ERROR: Bad argument " << argv[i] << std::endl;
				break;
			}
		} else {
			commentator.setDefaultReportFile (argv[i]);
			std::cout << "Writing report data to " << argv[i] << std::endl << std::endl;
			std::cout.flush ();
		}
	}
}

std::ostream& writeCommandString (std::ostream& os, Argument *args, char* programName) {
	os << programName;
	for (int i = 0; args[i].c != '\0'; i++) {
		cout << " -" << args[i].c;
		switch (args[i].type) {
		case TYPE_NONE:
			if (! (*(bool *)args[i].data)) os << " N";
			break;
		case TYPE_INT:
			os << ' ' << *(int *) args[i].data;
			break;
		case TYPE_INTEGER:
			os << ' ' << *(Integer *) args[i].data;
			break;
		case TYPE_DOUBLE:
			os << ' ' << *(double *) args[i].data;
			break;
		}
	}
	return os << std::endl;
}

bool isPower (integer n, integer m)
{
	return (n == 1) || ((n % m) == 0) && isPower (n/m, m);
}

inline double incompleteGamma (double a, double x, double tol)
{
	double xa_ex = pow (x, a) * exp (-x);
	double pi = 1.0;
	double xn = 1.0;
	double sigma = 0.0;
	double last_sigma;

	int n = 0;

	do {
		pi *= a + n;
		last_sigma = sigma;
		sigma += xn / pi;
		xn *= x;
		++n;
	} while (abs (sigma - last_sigma) >= tol);

	return sigma * xa_ex;
}

double chiSquaredCDF (double chi_sqr, double df)
{
	return incompleteGamma (df / 2.0, chi_sqr / 2.0, 1e-10) / exp (gamma (df / 2.0));
}

<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 *
 * Razor - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2011 Razor team
 * Authors:
 *   Petr Vanek <petr@scribus.info>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation;  only version 2 of
 * the License is valid for this program.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * END_COMMON_COPYRIGHT_HEADER */
/* Based on a "MountTray" project - modified for Razor needs
    http://hatred.homelinux.net

    @date   2010-11-11
    @brief  Main application class: integrate all components

    Copyright (C) 2010 by hatred <hatred@inbox.ru>

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

    For more information see LICENSE and LICENSE.ru files
*/

#include <QtDebug>

#include <QtGui/QMessageBox>
#include <QtGui/QDesktopServices>
#include <QtCore/QUrl>

#include "qtxdg/xdgicon.h"
#include "mountbutton.h"

MountButton::MountButton(QWidget * parent, RazorPanel *panel)
    : QToolButton(parent),
      m_panel(panel)
{
    if (!QDBusConnection::systemBus().isConnected())
    {
        qDebug() << "Can't connect to dbus daemon. Some functions will be omited";
    }

    setIcon(XdgIcon::fromTheme("emblem-mounted"));

    // Display disk menu
    m_menu = new QMenu(this);
    QAction *empty_action = m_menu->addAction(tr("Empty"));
    empty_action->setEnabled(false);

//    setMenu(m_menu);

    QDBusConnection conn = QDBusConnection::systemBus();
    // TODO: Check for connection, timer for reconect
    /*bool connected =*/ conn.connect("org.freedesktop.UDisks",
                                  "/org/freedesktop/UDisks",
                                  "org.freedesktop.UDisks",
                                  "DeviceChanged",
                                  this,
                                  SLOT(onDbusDeviceChangesMessage(QDBusObjectPath)));

    // Scan already connected devices
    initialScanDevices();

    connect(this, SIGNAL(clicked()), this, SLOT(showMenu()));

    connect(&_dm, SIGNAL(deviceConnected(DiskInfo)),
            this, SLOT(onDiskAdded(DiskInfo)));
    connect(&_dm, SIGNAL(deviceDisconnected(DiskInfo)),
            this, SLOT(onDiskRemoved(DiskInfo)));
    _dm.start();
}

MountButton::~MountButton()
{
    _dm.exit(0);
    _dm.wait(1000);
    _dm.terminate();
    _dm.wait();
}

void MountButton::initialScanDevices()
{
    QList<DiskInfo*> devices = _dm.scanDevices();
    for (int i = 0; i < devices.count(); i++)
    {
        DiskInfo *disk = devices.at(i);

        // add device
        _sm.addDevice(*disk);
        addMenuItem(*disk);

        StorageItem *sitem = _sm.getDevice(*disk);
        updateMenuItem(disk->device_name, disk->file_system_label, sitem->isMounted());

        // clear
        delete disk;
    }
}

void MountButton::addMenuItem(const DiskInfo &info)
{
    MenuDiskItem  *item   = new MenuDiskItem(info, this);
    QWidgetAction *action = new QWidgetAction(this);
    action->setDefaultWidget(item);

    if (m_menu_items.count() == 0)
    {
        // Clear 'Empty' item
        m_menu->clear();
        m_menu->addAction(action);
    }
    else
    {
        // Insert on Top
        m_menu->insertAction(m_menu->actions().at(0), action);
    }

    m_menu_items.insert(info.device_name, action);

    // Connect signals
    connect(item, SIGNAL(mountMedia(const QString&)),
            this, SLOT(onMediaMount(const QString&)));

    connect(item, SIGNAL(ejectMedia(const QString&)),
            this, SLOT(onMediaEject(const QString&)));
}

void MountButton::removeMenuItem(const QString &device)
{
    QWidgetAction *action = 0;
    if (m_menu_items.contains(device))
    {
        action = m_menu_items[device];
        m_menu->removeAction(action);
        m_menu_items.remove(device);
        delete action;
    }

    if (m_menu_items.count() == 0)
    {
        QAction *empty_action = m_menu->addAction(tr("Empty"));
        empty_action->setEnabled(false);
    }
}

void MountButton::updateMenuItem(const QString &device, const QString &name, bool is_mounted)
{
    QWidgetAction *action = 0;
    if (m_menu_items.contains(device))
    {
        action = m_menu_items[device];
        MenuDiskItem *item = static_cast<MenuDiskItem*>(action->defaultWidget());

        if (item == 0)
        {
            return;
        }

        if (!name.isEmpty())
        {
            item->setLabel(name);
        }

        item->setMountStatus(is_mounted);
    }
}

void MountButton::showMessage(const QString &text)
{
    // TODO/FIXME: messaging!
    //_tray_icon.showMessage("MountTray", text);
    qDebug() << "MESSAGE" << text;
}

void MountButton::showError(const QString &text)
{
    // TODO/FIXME: messaging!
//    _tray_icon.showMessage("MountTray Error", text, QSystemTrayIcon::Critical);
    qDebug() << "ERRMSG" << text;
}

/**************************************************************************************************/
/* Signals ---------------------------------------------------------------------------------------*/
/**************************************************************************************************/

void MountButton::onDiskAdded(DiskInfo info)
{
    _sm.addDevice(info);
    addMenuItem(info);
    showMessage(tr("Device connected: %1").arg(info.device_name));
}

void MountButton::onDiskRemoved(DiskInfo info)
{
    _sm.removeDevice(info);
    removeMenuItem(info.device_name);
    showMessage(tr("Device removed: %1").arg(info.device_name));
}

void MountButton::onDbusDeviceChangesMessage(QDBusObjectPath device)
{
    QString path = device.path();
    qDebug() << "Changed: " << qPrintable(path);

    QDBusInterface iface("org.freedesktop.UDisks",
                         path,
                         "org.freedesktop.UDisks.Device",
                         QDBusConnection::systemBus());

    //qDebug() << "Device name: " << iface.property("DeviceFile");
    //qDebug() << "Is mounted:  " << iface.property("DeviceIsMounted");

    QString dev_name   = iface.property("DeviceFile").toString();
    bool    is_mounted = iface.property("DeviceIsMounted").toBool();

    StorageItem *item = _sm.getDevice(dev_name);
    if (item == NULL)
    {
        return;
    }

    bool old_state = item->isMounted();
    item->setMountStatus(is_mounted);
    updateMenuItem(dev_name, QString(), item->isMounted());

    if (item->isMounted() != old_state)
    {
        if (item->isMounted())
        {
            QString mount_point = item->getMountPoint();
            showMessage(tr("Device '%1' is mounted to %2").arg(dev_name).arg(mount_point));
        }
        else
        {
            showMessage(tr("Device '%1' is unmounted\nNow you can eject USB Flash or CD/DVD Disk").arg(dev_name));
        }
    }
}

void MountButton::onMediaMount(const QString &device)
{
    qDebug() << "Mount media: " << qPrintable(device) << "\n";
    m_menu->hide();

    StorageItem *item = _sm.getDevice(device);
    if (item == NULL)
    {
        return;
    }

    bool    old_state   = item->isMounted();
    QString status_text;
    if (!item->isMounted())
    {
        item->mount(status_text);
    }

    QString mount_point = item->getMountPoint();

    if (!item->isMounted())
    {
        // Error
        showError(tr("Can't mount device: %1\n%2").arg(device).arg(status_text));
        return;
    }

    if (item->isMounted() != old_state)
    {
        showMessage(tr("Device '%1' is mounted to %2").arg(device).arg(mount_point));
        updateMenuItem(device, "", true);
    }

    // Run manager
    QDesktopServices::openUrl(QUrl(mount_point));

}

void MountButton::onMediaEject(const QString &device)
{
    qDebug() << "UnMount media: " << qPrintable(device) << "\n";
    m_menu->hide();

    StorageItem *item = _sm.getDevice(device);
    if (item == NULL)
    {
        return;
    }

    QString status_text;
    if (item->isMounted())
    {
        item->unmount(status_text);
    }

    if (item->isMounted())
    {
        // Error
        showError(tr("Can't unmount device: %1\n%2").arg(device).arg(status_text));
        return;
    }

    showMessage(tr("Device '%1' is unmounted").arg(device));
    updateMenuItem(device, "", false);
}

void MountButton::showMenu()
{
    // TODO/FIXME: shared code with MainMenu plugin. How to share? Something like "menubutton base class"?
    int x, y;

    switch (m_panel->position())
    {
        case RazorPanel::PositionTop:
            x = mapToGlobal(QPoint(0, 0)).x();
            y = m_panel->mapToGlobal(QPoint(0, m_panel->sizeHint().height())).y();
            break;

        case RazorPanel::PositionBottom:
            x = mapToGlobal(QPoint(0, 0)).x();
            y = m_panel->mapToGlobal(QPoint(0, 0)).y() - m_menu->sizeHint().height();
            break;

        case RazorPanel::PositionLeft:
            x = m_panel->mapToGlobal(QPoint(m_panel->sizeHint().width(), 0)).x();
            y = mapToGlobal(QPoint(0, 0)).y();
            break;

        case RazorPanel::PositionRight:
            x = m_panel->mapToGlobal(QPoint(0, 0)).x() - m_menu->sizeHint().width();
            y = mapToGlobal(QPoint(0, 0)).y();
            break;

    }

    QPoint pos(x, y);
    m_menu->exec(pos);
}
<commit_msg>fixed (workaround before real event notifications) #42 mount plugin: display notifications when connected<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 *
 * Razor - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2011 Razor team
 * Authors:
 *   Petr Vanek <petr@scribus.info>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation;  only version 2 of
 * the License is valid for this program.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * END_COMMON_COPYRIGHT_HEADER */
/* Based on a "MountTray" project - modified for Razor needs
    http://hatred.homelinux.net

    @date   2010-11-11
    @brief  Main application class: integrate all components

    Copyright (C) 2010 by hatred <hatred@inbox.ru>

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

    For more information see LICENSE and LICENSE.ru files
*/

#include <QtDebug>

#include <QtGui/QMessageBox>
#include <QtGui/QDesktopServices>
#include <QtCore/QUrl>
#include <QtGui/QToolTip>

#include "qtxdg/xdgicon.h"
#include "mountbutton.h"

MountButton::MountButton(QWidget * parent, RazorPanel *panel)
    : QToolButton(parent),
      m_panel(panel)
{
    if (!QDBusConnection::systemBus().isConnected())
    {
        qDebug() << "Can't connect to dbus daemon. Some functions will be omited";
    }

    setIcon(XdgIcon::fromTheme("emblem-mounted"));

    // Display disk menu
    m_menu = new QMenu(this);
    QAction *empty_action = m_menu->addAction(tr("Empty"));
    empty_action->setEnabled(false);

//    setMenu(m_menu);

    QDBusConnection conn = QDBusConnection::systemBus();
    // TODO: Check for connection, timer for reconect
    /*bool connected =*/ conn.connect("org.freedesktop.UDisks",
                                  "/org/freedesktop/UDisks",
                                  "org.freedesktop.UDisks",
                                  "DeviceChanged",
                                  this,
                                  SLOT(onDbusDeviceChangesMessage(QDBusObjectPath)));

    // Scan already connected devices
    initialScanDevices();

    connect(this, SIGNAL(clicked()), this, SLOT(showMenu()));

    connect(&_dm, SIGNAL(deviceConnected(DiskInfo)),
            this, SLOT(onDiskAdded(DiskInfo)));
    connect(&_dm, SIGNAL(deviceDisconnected(DiskInfo)),
            this, SLOT(onDiskRemoved(DiskInfo)));
    _dm.start();
}

MountButton::~MountButton()
{
    _dm.exit(0);
    _dm.wait(1000);
    _dm.terminate();
    _dm.wait();
}

void MountButton::initialScanDevices()
{
    QList<DiskInfo*> devices = _dm.scanDevices();
    for (int i = 0; i < devices.count(); i++)
    {
        DiskInfo *disk = devices.at(i);

        // add device
        _sm.addDevice(*disk);
        addMenuItem(*disk);

        StorageItem *sitem = _sm.getDevice(*disk);
        updateMenuItem(disk->device_name, disk->file_system_label, sitem->isMounted());

        // clear
        delete disk;
    }
}

void MountButton::addMenuItem(const DiskInfo &info)
{
    MenuDiskItem  *item   = new MenuDiskItem(info, this);
    QWidgetAction *action = new QWidgetAction(this);
    action->setDefaultWidget(item);

    if (m_menu_items.count() == 0)
    {
        // Clear 'Empty' item
        m_menu->clear();
        m_menu->addAction(action);
    }
    else
    {
        // Insert on Top
        m_menu->insertAction(m_menu->actions().at(0), action);
    }

    m_menu_items.insert(info.device_name, action);

    // Connect signals
    connect(item, SIGNAL(mountMedia(const QString&)),
            this, SLOT(onMediaMount(const QString&)));

    connect(item, SIGNAL(ejectMedia(const QString&)),
            this, SLOT(onMediaEject(const QString&)));
}

void MountButton::removeMenuItem(const QString &device)
{
    QWidgetAction *action = 0;
    if (m_menu_items.contains(device))
    {
        action = m_menu_items[device];
        m_menu->removeAction(action);
        m_menu_items.remove(device);
        delete action;
    }

    if (m_menu_items.count() == 0)
    {
        QAction *empty_action = m_menu->addAction(tr("Empty"));
        empty_action->setEnabled(false);
    }
}

void MountButton::updateMenuItem(const QString &device, const QString &name, bool is_mounted)
{
    QWidgetAction *action = 0;
    if (m_menu_items.contains(device))
    {
        action = m_menu_items[device];
        MenuDiskItem *item = static_cast<MenuDiskItem*>(action->defaultWidget());

        if (item == 0)
        {
            return;
        }

        if (!name.isEmpty())
        {
            item->setLabel(name);
        }

        item->setMountStatus(is_mounted);
    }
}

void MountButton::showMessage(const QString &text)
{
    // TODO/FIXME: messaging!
    //_tray_icon.showMessage("MountTray", text);
    qDebug() << "MESSAGE" << text;
    QToolTip::showText(mapToGlobal(pos()), text, this);
}

void MountButton::showError(const QString &text)
{
    // TODO/FIXME: messaging!
//    _tray_icon.showMessage("MountTray Error", text, QSystemTrayIcon::Critical);
    qDebug() << "ERRMSG" << text;
    QToolTip::showText(mapToGlobal(pos()), QString("<b>Error:</b> %1").arg(text), this);
}

/**************************************************************************************************/
/* Signals ---------------------------------------------------------------------------------------*/
/**************************************************************************************************/

void MountButton::onDiskAdded(DiskInfo info)
{
    _sm.addDevice(info);
    addMenuItem(info);
    showMessage(tr("Device connected: %1").arg(info.device_name));
}

void MountButton::onDiskRemoved(DiskInfo info)
{
    _sm.removeDevice(info);
    removeMenuItem(info.device_name);
    showMessage(tr("Device removed: %1").arg(info.device_name));
}

void MountButton::onDbusDeviceChangesMessage(QDBusObjectPath device)
{
    QString path = device.path();
    qDebug() << "Changed: " << qPrintable(path);

    QDBusInterface iface("org.freedesktop.UDisks",
                         path,
                         "org.freedesktop.UDisks.Device",
                         QDBusConnection::systemBus());

    //qDebug() << "Device name: " << iface.property("DeviceFile");
    //qDebug() << "Is mounted:  " << iface.property("DeviceIsMounted");

    QString dev_name   = iface.property("DeviceFile").toString();
    bool    is_mounted = iface.property("DeviceIsMounted").toBool();

    StorageItem *item = _sm.getDevice(dev_name);
    if (item == NULL)
    {
        return;
    }

    bool old_state = item->isMounted();
    item->setMountStatus(is_mounted);
    updateMenuItem(dev_name, QString(), item->isMounted());

    if (item->isMounted() != old_state)
    {
        if (item->isMounted())
        {
            QString mount_point = item->getMountPoint();
            showMessage(tr("Device '%1' is mounted to %2").arg(dev_name).arg(mount_point));
        }
        else
        {
            showMessage(tr("Device '%1' is unmounted\nNow you can eject USB Flash or CD/DVD Disk").arg(dev_name));
        }
    }
}

void MountButton::onMediaMount(const QString &device)
{
    qDebug() << "Mount media: " << qPrintable(device) << "\n";
    m_menu->hide();

    StorageItem *item = _sm.getDevice(device);
    if (item == NULL)
    {
        return;
    }

    bool    old_state   = item->isMounted();
    QString status_text;
    if (!item->isMounted())
    {
        item->mount(status_text);
    }

    QString mount_point = item->getMountPoint();

    if (!item->isMounted())
    {
        // Error
        showError(tr("Can't mount device: %1\n%2").arg(device).arg(status_text));
        return;
    }

    if (item->isMounted() != old_state)
    {
        showMessage(tr("Device '%1' is mounted to %2").arg(device).arg(mount_point));
        updateMenuItem(device, "", true);
    }

    // Run manager
    QDesktopServices::openUrl(QUrl(mount_point));

}

void MountButton::onMediaEject(const QString &device)
{
    qDebug() << "UnMount media: " << qPrintable(device) << "\n";
    m_menu->hide();

    StorageItem *item = _sm.getDevice(device);
    if (item == NULL)
    {
        return;
    }

    QString status_text;
    if (item->isMounted())
    {
        item->unmount(status_text);
    }

    if (item->isMounted())
    {
        // Error
        showError(tr("Can't unmount device: %1\n%2").arg(device).arg(status_text));
        return;
    }

    showMessage(tr("Device '%1' is unmounted").arg(device));
    updateMenuItem(device, "", false);
}

void MountButton::showMenu()
{
    // TODO/FIXME: shared code with MainMenu plugin. How to share? Something like "menubutton base class"?
    int x, y;

    switch (m_panel->position())
    {
        case RazorPanel::PositionTop:
            x = mapToGlobal(QPoint(0, 0)).x();
            y = m_panel->mapToGlobal(QPoint(0, m_panel->sizeHint().height())).y();
            break;

        case RazorPanel::PositionBottom:
            x = mapToGlobal(QPoint(0, 0)).x();
            y = m_panel->mapToGlobal(QPoint(0, 0)).y() - m_menu->sizeHint().height();
            break;

        case RazorPanel::PositionLeft:
            x = m_panel->mapToGlobal(QPoint(m_panel->sizeHint().width(), 0)).x();
            y = mapToGlobal(QPoint(0, 0)).y();
            break;

        case RazorPanel::PositionRight:
            x = m_panel->mapToGlobal(QPoint(0, 0)).x() - m_menu->sizeHint().width();
            y = mapToGlobal(QPoint(0, 0)).y();
            break;

    }

    QPoint pos(x, y);
    m_menu->exec(pos);
}
<|endoftext|>


<commit_before>//==-- AArch64DeadRegisterDefinitions.cpp - Replace dead defs w/ zero reg --==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// When allowed by the instruction, replace a dead definition of a GPR with
// the zero register. This makes the code a bit friendlier towards the
// hardware's register renamer.
//===----------------------------------------------------------------------===//

#include "AArch64.h"
#include "AArch64RegisterInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;

#define DEBUG_TYPE "aarch64-dead-defs"

STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced");

#define AARCH64_DEAD_REG_DEF_NAME "AArch64 Dead register definitions"

namespace {
class AArch64DeadRegisterDefinitions : public MachineFunctionPass {
private:
  const TargetRegisterInfo *TRI;
  bool implicitlyDefinesOverlappingReg(unsigned Reg, const MachineInstr &MI);
  bool processMachineBasicBlock(MachineBasicBlock &MBB);
  bool usesFrameIndex(const MachineInstr &MI);
public:
  static char ID; // Pass identification, replacement for typeid.
  explicit AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) {
    initializeAArch64DeadRegisterDefinitionsPass(
        *PassRegistry::getPassRegistry());
  }

  bool runOnMachineFunction(MachineFunction &F) override;

  MachineFunctionProperties getRequiredProperties() const override {
    return MachineFunctionProperties().set(
        MachineFunctionProperties::Property::NoVRegs);
  }

  StringRef getPassName() const override { return AARCH64_DEAD_REG_DEF_NAME; }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
};
char AArch64DeadRegisterDefinitions::ID = 0;
} // end anonymous namespace

INITIALIZE_PASS(AArch64DeadRegisterDefinitions, "aarch64-dead-defs",
                AARCH64_DEAD_REG_DEF_NAME, false, false)

bool AArch64DeadRegisterDefinitions::implicitlyDefinesOverlappingReg(
    unsigned Reg, const MachineInstr &MI) {
  for (const MachineOperand &MO : MI.implicit_operands())
    if (MO.isReg() && MO.isDef())
      if (TRI->regsOverlap(Reg, MO.getReg()))
        return true;
  return false;
}

bool AArch64DeadRegisterDefinitions::usesFrameIndex(const MachineInstr &MI) {
  for (const MachineOperand &Op : MI.uses())
    if (Op.isFI())
      return true;
  return false;
}

bool AArch64DeadRegisterDefinitions::processMachineBasicBlock(
    MachineBasicBlock &MBB) {
  bool Changed = false;
  for (MachineInstr &MI : MBB) {
    if (usesFrameIndex(MI)) {
      // We need to skip this instruction because while it appears to have a
      // dead def it uses a frame index which might expand into a multi
      // instruction sequence during EPI.
      DEBUG(dbgs() << "    Ignoring, operand is frame index\n");
      continue;
    }
    if (MI.definesRegister(AArch64::XZR) || MI.definesRegister(AArch64::WZR)) {
      // It is not allowed to write to the same register (not even the zero
      // register) twice in a single instruction.
      DEBUG(dbgs() << "    Ignoring, XZR or WZR already used by the instruction\n");
      continue;
    }
    for (int i = 0, e = MI.getDesc().getNumDefs(); i != e; ++i) {
      MachineOperand &MO = MI.getOperand(i);
      if (MO.isReg() && MO.isDead() && MO.isDef()) {
        assert(!MO.isImplicit() && "Unexpected implicit def!");
        DEBUG(dbgs() << "  Dead def operand #" << i << " in:\n    ";
              MI.print(dbgs()));
        // Be careful not to change the register if it's a tied operand.
        if (MI.isRegTiedToUseOperand(i)) {
          DEBUG(dbgs() << "    Ignoring, def is tied operand.\n");
          continue;
        }
        // Don't change the register if there's an implicit def of a subreg or
        // superreg.
        if (implicitlyDefinesOverlappingReg(MO.getReg(), MI)) {
          DEBUG(dbgs() << "    Ignoring, implicitly defines overlap reg.\n");
          continue;
        }
        // Make sure the instruction take a register class that contains
        // the zero register and replace it if so.
        unsigned NewReg;
        switch (MI.getDesc().OpInfo[i].RegClass) {
        default:
          DEBUG(dbgs() << "    Ignoring, register is not a GPR.\n");
          continue;
        case AArch64::GPR32RegClassID:
          NewReg = AArch64::WZR;
          break;
        case AArch64::GPR64RegClassID:
          NewReg = AArch64::XZR;
          break;
        }
        DEBUG(dbgs() << "    Replacing with zero register. New:\n      ");
        MO.setReg(NewReg);
        DEBUG(MI.print(dbgs()));
        ++NumDeadDefsReplaced;
        // Only replace one dead register, see check for zero register above.
        break;
      }
    }
  }
  return Changed;
}

// Scan the function for instructions that have a dead definition of a
// register. Replace that register with the zero register when possible.
bool AArch64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) {
  TRI = MF.getSubtarget().getRegisterInfo();
  bool Changed = false;
  DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n");

  if (skipFunction(*MF.getFunction()))
    return false;

  for (auto &MBB : MF)
    if (processMachineBasicBlock(MBB))
      Changed = true;
  return Changed;
}

FunctionPass *llvm::createAArch64DeadRegisterDefinitions() {
  return new AArch64DeadRegisterDefinitions();
}
<commit_msg>AArch64DeadRegisterDefinitionsPass: Cleanup; NFC<commit_after>//==-- AArch64DeadRegisterDefinitions.cpp - Replace dead defs w/ zero reg --==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file When allowed by the instruction, replace a dead definition of a GPR
/// with the zero register. This makes the code a bit friendlier towards the
/// hardware's register renamer.
//===----------------------------------------------------------------------===//

#include "AArch64.h"
#include "AArch64RegisterInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;

#define DEBUG_TYPE "aarch64-dead-defs"

STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced");

#define AARCH64_DEAD_REG_DEF_NAME "AArch64 Dead register definitions"

namespace {
class AArch64DeadRegisterDefinitions : public MachineFunctionPass {
private:
  const TargetRegisterInfo *TRI;
  bool Changed;
  bool implicitlyDefinesOverlappingReg(unsigned Reg, const MachineInstr &MI);
  void processMachineBasicBlock(MachineBasicBlock &MBB);
public:
  static char ID; // Pass identification, replacement for typeid.
  AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) {
    initializeAArch64DeadRegisterDefinitionsPass(
        *PassRegistry::getPassRegistry());
  }

  bool runOnMachineFunction(MachineFunction &F) override;

  MachineFunctionProperties getRequiredProperties() const override {
    return MachineFunctionProperties().set(
        MachineFunctionProperties::Property::NoVRegs);
  }

  StringRef getPassName() const override { return AARCH64_DEAD_REG_DEF_NAME; }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
};
char AArch64DeadRegisterDefinitions::ID = 0;
} // end anonymous namespace

INITIALIZE_PASS(AArch64DeadRegisterDefinitions, "aarch64-dead-defs",
                AARCH64_DEAD_REG_DEF_NAME, false, false)

bool AArch64DeadRegisterDefinitions::implicitlyDefinesOverlappingReg(
    unsigned Reg, const MachineInstr &MI) {
  for (const MachineOperand &MO : MI.implicit_operands())
    if (MO.isReg() && MO.isDef())
      if (TRI->regsOverlap(Reg, MO.getReg()))
        return true;
  return false;
}

static bool usesFrameIndex(const MachineInstr &MI) {
  for (const MachineOperand &MO : MI.uses())
    if (MO.isFI())
      return true;
  return false;
}

void AArch64DeadRegisterDefinitions::processMachineBasicBlock(
    MachineBasicBlock &MBB) {
  for (MachineInstr &MI : MBB) {
    if (usesFrameIndex(MI)) {
      // We need to skip this instruction because while it appears to have a
      // dead def it uses a frame index which might expand into a multi
      // instruction sequence during EPI.
      DEBUG(dbgs() << "    Ignoring, operand is frame index\n");
      continue;
    }
    if (MI.definesRegister(AArch64::XZR) || MI.definesRegister(AArch64::WZR)) {
      // It is not allowed to write to the same register (not even the zero
      // register) twice in a single instruction.
      DEBUG(dbgs() << "    Ignoring, XZR or WZR already used by the instruction\n");
      continue;
    }
    const MCInstrDesc &Desc = MI.getDesc();
    for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) {
      MachineOperand &MO = MI.getOperand(I);
      if (!MO.isReg() || !MO.isDead() || !MO.isDef())
        continue;
      assert(!MO.isImplicit() && "Unexpected implicit def!");
      DEBUG(dbgs() << "  Dead def operand #" << I << " in:\n    ";
            MI.print(dbgs()));
      // Be careful not to change the register if it's a tied operand.
      if (MI.isRegTiedToUseOperand(I)) {
        DEBUG(dbgs() << "    Ignoring, def is tied operand.\n");
        continue;
      }
      // Don't change the register if there's an implicit def of a subreg or
      // superreg.
      if (implicitlyDefinesOverlappingReg(MO.getReg(), MI)) {
        DEBUG(dbgs() << "    Ignoring, implicitly defines overlap reg.\n");
        continue;
      }
      // Make sure the instruction take a register class that contains
      // the zero register and replace it if so.
      unsigned NewReg;
      switch (Desc.OpInfo[I].RegClass) {
      default:
        DEBUG(dbgs() << "    Ignoring, register is not a GPR.\n");
        continue;
      case AArch64::GPR32RegClassID:
        NewReg = AArch64::WZR;
        break;
      case AArch64::GPR64RegClassID:
        NewReg = AArch64::XZR;
        break;
      }
      DEBUG(dbgs() << "    Replacing with zero register. New:\n      ");
      MO.setReg(NewReg);
      DEBUG(MI.print(dbgs()));
      ++NumDeadDefsReplaced;
      Changed = true;
      // Only replace one dead register, see check for zero register above.
      break;
    }
  }
}

// Scan the function for instructions that have a dead definition of a
// register. Replace that register with the zero register when possible.
bool AArch64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) {
  if (skipFunction(*MF.getFunction()))
    return false;

  TRI = MF.getSubtarget().getRegisterInfo();
  bool Changed = false;
  DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n");
  Changed = false;
  for (auto &MBB : MF)
    processMachineBasicBlock(MBB);
  return Changed;
}

FunctionPass *llvm::createAArch64DeadRegisterDefinitions() {
  return new AArch64DeadRegisterDefinitions();
}
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------

 Copyright 2017 Hopsan Group

    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.

 The full license is available in the file LICENSE.
 For details about the 'Hopsan Group' or information about Authors and
 Contributors see the HOPSANGROUP and AUTHORS files that are located in
 the Hopsan source code root directory.

-----------------------------------------------------------------------------*/

//$Id$

#include "Quantities.h"

hopsan::QuantityRegister::QuantityRegister()
{
    registerQuantity("Pressure", "Pa");
    registerQuantityAlias("Pressure", "Stress");
    registerQuantity("Flow", "m^3/s");

    registerQuantity("Force", "N");
    registerQuantity("Position", "m");
    registerQuantity("Velocity", "m/s");
    registerQuantity("Acceleration", "m/(s^2)");

    registerQuantity("Torque", "Nm");
    registerQuantity("Angle", "rad");
    registerQuantity("AngularVelocity", "rad/s");

    registerQuantity("Voltage", "V");
    registerQuantity("Current", "A");

    registerQuantity("Momentum", "kg m/s");
    registerQuantity("Energy", "J");
    registerQuantity("Power", "J/s");

    registerQuantity("Mass", "kg");
    registerQuantity("Area", "m^2");
    registerQuantity("Volume", "m^3");
    registerQuantity("Displacement", "m^3/rev");

    registerQuantity("Density", "kg/m^3");

    registerQuantity("Frequency", "rad/s");
    registerQuantity("Time", "s");

    registerQuantity("Temperature", "K");

    registerQuantity("Resistance", "ohm");

    // This is a fake quantity for scaling between absolute and dB values
    registerQuantity("Magnitude", "");

    // Register quantity aliases
    registerQuantityAlias("Position", "Length");
}

void hopsan::QuantityRegister::registerQuantity(const hopsan::HString &rQuantity, const hopsan::HString &rBaseUnit)
{
    mQuantity2BaseUnit.insert(std::pair<HString, HString>(rQuantity, rBaseUnit));
}

void hopsan::QuantityRegister::registerQuantityAlias(const hopsan::HString &rQuantity, const hopsan::HString &rAlias)
{
    mQuantityAliases.insert(std::pair<HString, HString>(rAlias, rQuantity));
}

hopsan::HString hopsan::QuantityRegister::lookupBaseUnit(const hopsan::HString &rQuantity) const
{
    // First check if alias, then lookup actual quantity
    std::map<HString, HString>::const_iterator it = mQuantityAliases.find(rQuantity);
    if (it != mQuantityAliases.end())
    {
        it = mQuantity2BaseUnit.find(it->second);
    }
    // else lookup directly
    else
    {
        it = mQuantity2BaseUnit.find(rQuantity);
    }
    // If quantity registered, then return its base unit
    if (it != mQuantity2BaseUnit.end())
    {
        return it->second;
    }
    // else return empty string
    return HString();
}

bool hopsan::QuantityRegister::haveQuantity(const hopsan::HString &rQuantity) const
{
    // First check if alias, then lookup actual quantity
    std::map<HString, HString>::const_iterator it = mQuantityAliases.find(rQuantity);
    if (it != mQuantityAliases.end())
    {
        it = mQuantity2BaseUnit.find(it->second);
    }
    // else lookup directly
    else
    {
        it = mQuantity2BaseUnit.find(rQuantity);
    }
    return (it != mQuantity2BaseUnit.end());
}

//! @brief Lookup a quantity base unit, or return as a unit if not a valid quantity is given
//! @param[in] rQuantityOrUnit The name of the quantity (or unit)
//! @param[out] rQuantity The quantity, empty if rQuantityOrUnit is not a valid quantity
//! @param[out] rUnitOrBaseUnit The base unit for the given quantity, or the value of rQuantityOrUnit if it is not a valid quantity
//! @returns true if rQuantityOrUnit is a valid quantity else false
bool hopsan::checkIfQuantityOrUnit(const hopsan::HString &rQuantityOrUnit, hopsan::HString &rQuantity, hopsan::HString &rUnitOrBaseUnit)
{
    rUnitOrBaseUnit = gpInternalCoreQuantityRegister->lookupBaseUnit(rQuantityOrUnit);
    // rUnitOrQuantity is treated as a unit because no valid quantity has been specified
    if (rUnitOrBaseUnit.empty())
    {
        rQuantity.clear();
        rUnitOrBaseUnit = rQuantityOrUnit;
        return false;
    }
    // rUnitOrQuantity is actually a quantity, and bu is the corresponding base unit
    else
    {
        rQuantity = rQuantityOrUnit;
        return true;
    }
}
<commit_msg>Add "Altitude" as alias for "Position" in Quantities.cpp<commit_after>/*-----------------------------------------------------------------------------

 Copyright 2017 Hopsan Group

    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.

 The full license is available in the file LICENSE.
 For details about the 'Hopsan Group' or information about Authors and
 Contributors see the HOPSANGROUP and AUTHORS files that are located in
 the Hopsan source code root directory.

-----------------------------------------------------------------------------*/

//$Id$

#include "Quantities.h"

hopsan::QuantityRegister::QuantityRegister()
{
    registerQuantity("Pressure", "Pa");
    registerQuantityAlias("Pressure", "Stress");
    registerQuantity("Flow", "m^3/s");

    registerQuantity("Force", "N");
    registerQuantity("Position", "m");
    registerQuantity("Velocity", "m/s");
    registerQuantity("Acceleration", "m/(s^2)");

    registerQuantity("Torque", "Nm");
    registerQuantity("Angle", "rad");
    registerQuantity("AngularVelocity", "rad/s");

    registerQuantity("Voltage", "V");
    registerQuantity("Current", "A");

    registerQuantity("Momentum", "kg m/s");
    registerQuantity("Energy", "J");
    registerQuantity("Power", "J/s");

    registerQuantity("Mass", "kg");
    registerQuantity("Area", "m^2");
    registerQuantity("Volume", "m^3");
    registerQuantity("Displacement", "m^3/rev");

    registerQuantity("Density", "kg/m^3");

    registerQuantity("Frequency", "rad/s");
    registerQuantity("Time", "s");

    registerQuantity("Temperature", "K");

    registerQuantity("Resistance", "ohm");

    // This is a fake quantity for scaling between absolute and dB values
    registerQuantity("Magnitude", "");

    // Register quantity aliases
    registerQuantityAlias("Position", "Length");
    registerQuantityAlias("Position", "Altitude");
}

void hopsan::QuantityRegister::registerQuantity(const hopsan::HString &rQuantity, const hopsan::HString &rBaseUnit)
{
    mQuantity2BaseUnit.insert(std::pair<HString, HString>(rQuantity, rBaseUnit));
}

void hopsan::QuantityRegister::registerQuantityAlias(const hopsan::HString &rQuantity, const hopsan::HString &rAlias)
{
    mQuantityAliases.insert(std::pair<HString, HString>(rAlias, rQuantity));
}

hopsan::HString hopsan::QuantityRegister::lookupBaseUnit(const hopsan::HString &rQuantity) const
{
    // First check if alias, then lookup actual quantity
    std::map<HString, HString>::const_iterator it = mQuantityAliases.find(rQuantity);
    if (it != mQuantityAliases.end())
    {
        it = mQuantity2BaseUnit.find(it->second);
    }
    // else lookup directly
    else
    {
        it = mQuantity2BaseUnit.find(rQuantity);
    }
    // If quantity registered, then return its base unit
    if (it != mQuantity2BaseUnit.end())
    {
        return it->second;
    }
    // else return empty string
    return HString();
}

bool hopsan::QuantityRegister::haveQuantity(const hopsan::HString &rQuantity) const
{
    // First check if alias, then lookup actual quantity
    std::map<HString, HString>::const_iterator it = mQuantityAliases.find(rQuantity);
    if (it != mQuantityAliases.end())
    {
        it = mQuantity2BaseUnit.find(it->second);
    }
    // else lookup directly
    else
    {
        it = mQuantity2BaseUnit.find(rQuantity);
    }
    return (it != mQuantity2BaseUnit.end());
}

//! @brief Lookup a quantity base unit, or return as a unit if not a valid quantity is given
//! @param[in] rQuantityOrUnit The name of the quantity (or unit)
//! @param[out] rQuantity The quantity, empty if rQuantityOrUnit is not a valid quantity
//! @param[out] rUnitOrBaseUnit The base unit for the given quantity, or the value of rQuantityOrUnit if it is not a valid quantity
//! @returns true if rQuantityOrUnit is a valid quantity else false
bool hopsan::checkIfQuantityOrUnit(const hopsan::HString &rQuantityOrUnit, hopsan::HString &rQuantity, hopsan::HString &rUnitOrBaseUnit)
{
    rUnitOrBaseUnit = gpInternalCoreQuantityRegister->lookupBaseUnit(rQuantityOrUnit);
    // rUnitOrQuantity is treated as a unit because no valid quantity has been specified
    if (rUnitOrBaseUnit.empty())
    {
        rQuantity.clear();
        rUnitOrBaseUnit = rQuantityOrUnit;
        return false;
    }
    // rUnitOrQuantity is actually a quantity, and bu is the corresponding base unit
    else
    {
        rQuantity = rQuantityOrUnit;
        return true;
    }
}
<|endoftext|>