<commit_before>#include "WiringPiButtons.hpp"
// Pin number declarations using WiringPi numbering scheme
// 1 or UP is default -Not Pressed-, if button is pressed, the signal should go 0.
// Will only accept calls 10 times a second, this is a simple way to debounce

WiringPiButtons::WiringPiButtons()
{
    wiringPiSetup(); // Initialize wiringPi
    initButton(SPACE);
    initButton(VOLUMEDOWN);
    initButton(VOLUMEUP);
    initButton(NEXT);
    initButton(PREVIOUS);
    initButton(TOGGLEPLAY);
    state = RELEASED;
    period_start = std::chrono::high_resolution_clock::now();
    returnButton = RELEASED;
}

void WiringPiButtons::initButton(int buttonNumber)
{
    pinMode(buttonNumber, INPUT);      // Set button as INPUT
    pullUpDnControl(buttonNumber, PUD_UP); //Default Pulled UP
}

WiringPiButtons::Button WiringPiButtons::getEvents()
{

    deltaTime = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - period_start);
    if (deltaTime.count() < 0.04)
    {
        return RELEASED;
    }
    period_start = std::chrono::high_resolution_clock::now();

    switch(state)
    {
        case RELEASED:
            if (returnButton != 0)
            {
                Button tempValue = returnButton;
                returnButton = RELEASED;
	            printf("FUNCTION returned %d\n",tempValue);
                return tempValue;
            }

            if (!digitalRead(VOLUMEDOWN))
                state = VOLUMEDOWN;

            if (!digitalRead(VOLUMEUP))
                state = VOLUMEUP;

            if (!digitalRead(NEXT))
                state = NEXT;

            if (!digitalRead(PREVIOUS))
                state = PREVIOUS;

            if (!digitalRead(TOGGLEPLAY))
                state = TOGGLEPLAY;
            break;
        case UP:
            if (digitalRead(VOLUMEDOWN))
            {
                returnButton = VOLUMEDOWN;
                state = RELEASED;
            }
            break;
        case DOWN:
            if (digitalRead(VOLUMEUP))
            {
                returnButton = VOLUMEUP;
                state = RELEASED;
            }
            break;
        case LEFT:
            if (digitalRead(NEXT))
            {
                returnButton = NEXT;
                state = RELEASED;
            }
            break;
        case RIGHT:
            if (digitalRead(PREVIOUS))
            {
                returnButton = PREVIOUS;
                state = RELEASED;
            }
            break;
        case TOGGLEPLAY:
            if (digitalRead(TOGGLEPLAY))
            {
                returnButton = TOGGLEPLAY;
                state = RELEASED;
            }
            break;
    }
}
<commit_msg>Changed switch statement to new names<commit_after>#include "WiringPiButtons.hpp"
// Pin number declarations using WiringPi numbering scheme
// 1 or UP is default -Not Pressed-, if button is pressed, the signal should go 0.
// Will only accept calls 10 times a second, this is a simple way to debounce

WiringPiButtons::WiringPiButtons()
{
    wiringPiSetup(); // Initialize wiringPi
    initButton(SPACE);
    initButton(VOLUMEDOWN);
    initButton(VOLUMEUP);
    initButton(NEXT);
    initButton(PREVIOUS);
    initButton(TOGGLEPLAY);
    state = RELEASED;
    period_start = std::chrono::high_resolution_clock::now();
    returnButton = RELEASED;
}

void WiringPiButtons::initButton(int buttonNumber)
{
    pinMode(buttonNumber, INPUT);      // Set button as INPUT
    pullUpDnControl(buttonNumber, PUD_UP); //Default Pulled UP
}

WiringPiButtons::Button WiringPiButtons::getEvents()
{

    deltaTime = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - period_start);
    if (deltaTime.count() < 0.04)
    {
        return RELEASED;
    }
    period_start = std::chrono::high_resolution_clock::now();

    switch(state)
    {
        case RELEASED:
            if (returnButton != 0)
            {
                Button tempValue = returnButton;
                returnButton = RELEASED;
	            printf("FUNCTION returned %d\n",tempValue);
                return tempValue;
            }

            if (!digitalRead(VOLUMEDOWN))
                state = VOLUMEDOWN;

            if (!digitalRead(VOLUMEUP))
                state = VOLUMEUP;

            if (!digitalRead(NEXT))
                state = NEXT;

            if (!digitalRead(PREVIOUS))
                state = PREVIOUS;

            if (!digitalRead(TOGGLEPLAY))
                state = TOGGLEPLAY;
            break;
        case VOLUMEDOWN:
            if (digitalRead(VOLUMEDOWN))
            {
                returnButton = VOLUMEDOWN;
                state = RELEASED;
            }
            break;
        case VOLUMEUP:
            if (digitalRead(VOLUMEUP))
            {
                returnButton = VOLUMEUP;
                state = RELEASED;
            }
            break;
        case NEXT:
            if (digitalRead(NEXT))
            {
                returnButton = NEXT;
                state = RELEASED;
            }
            break;
        case PREVIOUS:
            if (digitalRead(PREVIOUS))
            {
                returnButton = PREVIOUS;
                state = RELEASED;
            }
            break;
        case TOGGLEPLAY:
            if (digitalRead(TOGGLEPLAY))
            {
                returnButton = TOGGLEPLAY;
                state = RELEASED;
            }
            break;
    }
}
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! TODO: this is a messy set of unit tests. It maybe worth reinstating Google
//! mock in the library. We can compare easily vectors.

#include <set>

#include <gtest/gtest.h>

#include <DO/KDTree.hpp>

#include "../AssertHelpers.hpp"

using namespace DO;
using namespace std;

inline vector<int> range(int begin, int end)
{
  vector<int> _range(end-begin);
  for (int i = begin; i < end; ++i)
    _range[i-begin] = i;
  return _range;
}

inline vector<int> range(int end)
{
  return range(0, end);
}

class TestKDTree : public testing::Test
{
protected:
  MatrixXd data;
  size_t num_points;
  size_t num_points_in_each_circle;

  TestKDTree()
  {
    // We construct two sets in points. The first one lives in the
    // zero-centered unit circle and the second in the zero-centered
    // circle with radius 10.
    num_points_in_each_circle = 20;
    num_points = 2*num_points_in_each_circle;
    data.resize(2, num_points);

    const size_t& N = num_points_in_each_circle;
    for (size_t i = 0; i < N; ++i)
    {
      double theta = (2*i*M_PI) / N;
      data.col(i) << cos(theta), sin(theta);
    }

    for (size_t i = N; i < 2*N; ++i)
    {
      double theta = (2*(i-N)*M_PI) / N;
      data.col(i) << 10*cos(theta), 10*sin(theta);
    }
  }
};

TEST_F(TestKDTree, test_simple_knn_search)
{
  KDTree tree(data);

  Vector2d query = Vector2d::Zero();
  size_t num_nearest_neighbors = num_points_in_each_circle;

  vector<int> nn_indices;
  vector<double> nn_squared_distances;

  tree.knn_search(query, num_nearest_neighbors, nn_indices,
                  nn_squared_distances);

  // Check equality of items.
  EXPECT_ITEMS_EQ(nn_indices, range(num_points_in_each_circle));

  // Check the squared distances.
  EXPECT_EQ(nn_squared_distances.size(), num_points_in_each_circle);
  for (size_t j = 0; j < nn_squared_distances.size(); ++j)
    EXPECT_NEAR(nn_squared_distances[j], 1., 1e-10);
}

TEST_F(TestKDTree, test_simple_knn_search_with_query_point_in_data)
{
  KDTree tree(data);

  size_t query_index = 0;
  size_t num_nearest_neighbors = num_points_in_each_circle-1;

  vector<int> indices;
  vector<double> squared_distances;

  tree.knn_search(query_index, num_nearest_neighbors, indices,
                  squared_distances);

  // Check the indices of the neighbors.
  EXPECT_ITEMS_EQ(indices, range(1, num_points_in_each_circle));

  // Check the squared distances of the neighbors.
  EXPECT_EQ(num_nearest_neighbors, squared_distances.size());
  for (size_t j = 0; j < squared_distances.size(); ++j)
    EXPECT_LE(squared_distances[j], pow(2., 2));
}

TEST_F(TestKDTree, test_batch_knn_search)
{
  // Input data.
  KDTree tree(data);
  const size_t& num_queries = num_points_in_each_circle;
  const size_t& num_nearest_neighbors = num_points_in_each_circle;
  MatrixXd queries(data.leftCols(num_queries));

  // In-out data.
  vector<vector<int> > indices;
  vector<vector<double> > squared_distances;

  // Use case.
  tree.knn_search(queries, num_nearest_neighbors, indices, squared_distances);

  // Check the contents of the retrieval.
  EXPECT_EQ(indices.size(), num_queries);
  EXPECT_EQ(squared_distances.size(), num_queries);

  for (size_t i = 0; i < num_queries; ++i)
  {
    // Check the indices.
    EXPECT_ITEMS_EQ(indices[i], range(num_points_in_each_circle));

    // Check the squared distances.
    EXPECT_EQ(num_nearest_neighbors, squared_distances.size());
    for (size_t j = 0; j < squared_distances[i].size(); ++j)
      EXPECT_LE(squared_distances[i][j], pow(2., 2));
  }
}

TEST_F(TestKDTree, test_batch_knn_search_with_query_point_in_data)
{
  // Input data.
  KDTree tree(data);
  const size_t num_queries = num_points_in_each_circle;
  const size_t num_nearest_neighbors = num_points_in_each_circle-1;

  vector<size_t> queries(num_queries);
  for (size_t i = 0; i != queries.size(); ++i)
    queries[i] = i;

  // In-out data.
  vector<vector<int> > indices;
  vector<vector<double> > squared_distances;

  // Use case.
  tree.knn_search(queries, num_nearest_neighbors, indices, squared_distances);

  // Check the number of queries.
  EXPECT_EQ(indices.size(), num_queries);
  EXPECT_EQ(squared_distances.size(), num_queries);

  // Check the contents of the retrieval.
  for (size_t i = 0; i != indices.size(); ++i)
  {
    // The correct list of indices is: {0, 1, 2, 3, 4 } \ {i},
    // where i = 0, 1, ... 4.
    vector<int> true_indices = range(num_points_in_each_circle);
    true_indices.erase(true_indices.begin()+i);

    EXPECT_ITEMS_EQ(indices[i], true_indices);

    // Check the squared distances.
    EXPECT_EQ(squared_distances[i].size(), true_indices.size());
    for (size_t j = 0; j < indices[i].size(); ++j)
      EXPECT_LE(squared_distances[i][j], pow(2., 2));
  }
}

int main(int argc, char **argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}<commit_msg>Fixed numerical accuracy in failing tests.<commit_after>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! TODO: this is a messy set of unit tests. It maybe worth reinstating Google
//! mock in the library. We can compare easily vectors.

#include <set>

#include <gtest/gtest.h>

#include <DO/KDTree.hpp>

#include "../AssertHelpers.hpp"

using namespace DO;
using namespace std;

inline vector<int> range(int begin, int end)
{
  vector<int> _range(end-begin);
  for (int i = begin; i < end; ++i)
    _range[i-begin] = i;
  return _range;
}

inline vector<int> range(int end)
{
  return range(0, end);
}

class TestKDTree : public testing::Test
{
protected:
  MatrixXd data;
  size_t num_points;
  size_t num_points_in_each_circle;

  TestKDTree()
  {
    // We construct two sets in points. The first one lives in the
    // zero-centered unit circle and the second in the zero-centered
    // circle with radius 10.
    num_points_in_each_circle = 20;
    num_points = 2*num_points_in_each_circle;
    data.resize(2, num_points);

    const size_t& N = num_points_in_each_circle;
    for (size_t i = 0; i < N; ++i)
    {
      double theta = (2*i*M_PI) / N;
      data.col(i) << cos(theta), sin(theta);
    }

    for (size_t i = N; i < 2*N; ++i)
    {
      double theta = (2*(i-N)*M_PI) / N;
      data.col(i) << 10*cos(theta), 10*sin(theta);
    }
  }
};

TEST_F(TestKDTree, test_simple_knn_search)
{
  KDTree tree(data);

  Vector2d query = Vector2d::Zero();
  size_t num_nearest_neighbors = num_points_in_each_circle;

  vector<int> nn_indices;
  vector<double> nn_squared_distances;

  tree.knn_search(query, num_nearest_neighbors, nn_indices,
                  nn_squared_distances);

  // Check equality of items.
  EXPECT_ITEMS_EQ(nn_indices, range(num_points_in_each_circle));

  // Check the squared distances.
  EXPECT_EQ(nn_squared_distances.size(), num_points_in_each_circle);
  for (size_t j = 0; j < nn_squared_distances.size(); ++j)
    EXPECT_NEAR(nn_squared_distances[j], 1., 1e-10);
}

TEST_F(TestKDTree, test_simple_knn_search_with_query_point_in_data)
{
  KDTree tree(data);

  size_t query_index = 0;
  size_t num_nearest_neighbors = num_points_in_each_circle-1;

  vector<int> indices;
  vector<double> squared_distances;

  tree.knn_search(query_index, num_nearest_neighbors, indices,
                  squared_distances);

  // Check the indices of the neighbors.
  EXPECT_ITEMS_EQ(indices, range(1, num_points_in_each_circle));

  // Check the squared distances of the neighbors.
  EXPECT_EQ(num_nearest_neighbors, squared_distances.size());
  for (size_t j = 0; j < squared_distances.size(); ++j)
    EXPECT_LE(squared_distances[j], pow(2.+1e-5, 2));
}

TEST_F(TestKDTree, test_batch_knn_search)
{
  // Input data.
  KDTree tree(data);
  const size_t& num_queries = num_points_in_each_circle;
  const size_t& num_nearest_neighbors = num_points_in_each_circle;
  MatrixXd queries(data.leftCols(num_queries));

  // In-out data.
  vector<vector<int> > indices;
  vector<vector<double> > squared_distances;

  // Use case.
  tree.knn_search(queries, num_nearest_neighbors, indices, squared_distances);

  // Check the contents of the retrieval.
  EXPECT_EQ(indices.size(), num_queries);
  EXPECT_EQ(squared_distances.size(), num_queries);

  for (size_t i = 0; i < num_queries; ++i)
  {
    // Check the indices.
    EXPECT_ITEMS_EQ(indices[i], range(num_points_in_each_circle));

    // Check the squared distances.
    EXPECT_EQ(num_nearest_neighbors, squared_distances.size());
    for (size_t j = 0; j < squared_distances[i].size(); ++j)
      EXPECT_LE(squared_distances[i][j], pow(2.+1e-5, 2));
  }
}

TEST_F(TestKDTree, test_batch_knn_search_with_query_point_in_data)
{
  // Input data.
  KDTree tree(data);
  const size_t num_queries = num_points_in_each_circle;
  const size_t num_nearest_neighbors = num_points_in_each_circle-1;

  vector<size_t> queries(num_queries);
  for (size_t i = 0; i != queries.size(); ++i)
    queries[i] = i;

  // In-out data.
  vector<vector<int> > indices;
  vector<vector<double> > squared_distances;

  // Use case.
  tree.knn_search(queries, num_nearest_neighbors, indices, squared_distances);

  // Check the number of queries.
  EXPECT_EQ(indices.size(), num_queries);
  EXPECT_EQ(squared_distances.size(), num_queries);

  // Check the contents of the retrieval.
  for (size_t i = 0; i != indices.size(); ++i)
  {
    // The correct list of indices is: {0, 1, 2, 3, 4 } \ {i},
    // where i = 0, 1, ... 4.
    vector<int> true_indices = range(num_points_in_each_circle);
    true_indices.erase(true_indices.begin()+i);

    EXPECT_ITEMS_EQ(indices[i], true_indices);

    // Check the squared distances.
    EXPECT_EQ(squared_distances[i].size(), true_indices.size());
    for (size_t j = 0; j < indices[i].size(); ++j)
      EXPECT_LE(squared_distances[i][j], pow(2.+1e-5, 2));
  }
}

int main(int argc, char **argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}<|endoftext|>


<commit_before>// basic file operations
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <vector>

#include "Customer.hpp"
#include "Event.hpp"
#include "PriorityQueue.hpp"
#include "RegisterQueue.hpp"
using namespace std;

class StoreSimulator{

private:
  PriorityQueue<Event> events;
  vector<RegisterQueue> registers;
  vector<double> waitTimes;
  double simClock;

public:
  StoreSimulator(){
    simClock = 0;
  }

  void startSimulation(int numNormal, int numSelfScan) {
    loadRegisters(numNormal, numSelfScan);
    loadCustomerData();

    while(events.size > 0){
      Event e = events.dequeue();
      simClock = e.simTime;
      cout << "Event at " << simClock << "/1440min: ";
      if(e.type == EventType::Arrival){
        handleArrival(e);
      }else if(e.type == EventType::EndShopping){
        handleEndShopping(e);
      }else{
        handleEndCheckout(e);
      }
    }
    endSimulation();
  }

  void loadCustomerData(){
    double simClock, avgSelectionTime;
    int items;

    ifstream myfile ("arrival.txt");
    if (myfile.is_open()){
      while (myfile >> simClock >> items >> avgSelectionTime){
        Customer cust(simClock, items, avgSelectionTime) ;
        cout << cust << endl;
        Event e(EventType::Arrival, simClock, cust);
        events.enqueue(e);
      }
      myfile.close();
    }else
    throw(1);
  }

  void loadRegisters(int numNormal, int numSelfScan){
    for(int i = 0; i < numNormal; i ++){
      RegisterQueue r(1.5, .01);
      registers.push_back(r);
    }
    for(int i = 0; i < numSelfScan; i++){
      RegisterQueue r(3.0, .04);
      registers.push_back(r);
    }
  }

  void handleArrival(Event& e){
    Customer c = e.person;
    double finishShopping = c.getCustomerArrival() + (c.getOrderSize() * c.getTimeToGetItem());
    Event next(EventType::EndShopping, finishShopping, c);
    cout << "Customer " << c << " started shopping" << endl;
    events.enqueue(next);
  }

  void handleEndShopping(Event& e){
    Customer c = e.person;
    // Find lane with least # of people
    int min = 0;
    for (int i = 1; i < registers.size(); i++) {
      if (registers[i].numberOfCustomers < registers[min].numberOfCustomers)
        min = i;
    }
    RegisterQueue *r = &registers[min];
    c.chooseRegister(min);
    r->enqueue(c);
    // If waiting in line, their EndCheckout is scheduled once they are up
    if(r->numberOfCustomers <= 1) {
      double finishCheckout = e.simTime + r->minToPay + (c.getOrderSize() * r->minPerItem);
      cout << "Customer " << c << " has started checking out" << endl;
      Event next(EventType::EndCheckout, finishCheckout, c);
      events.enqueue(next);
    } else {
      cout << "Customer " << c << " waiting in line " << min << endl;
    }
  }
  void handleEndCheckout(Event& e){
    Customer out = e.person;
    int lane = out.getRegister();
    RegisterQueue *r = &registers[lane];

    // Calculate wait time = EndCheckout - (arrival + shopTime + checkoutTime)
    double wait = e.simTime // EndCheckout
                  - (out.getCustomerArrival() // arrival
                     + (out.getOrderSize() * out.getTimeToGetItem()) // shopTime
                     + r->minToPay + (out.getOrderSize() * r->minPerItem)); // checkoutTime
    waitTimes.push_back(wait);

    // Let person leave simulation
    try {
      r->dequeue();
    } catch(char const* e) {
      cout << "- Caught eror: " << e << endl;
    }
    cout << "Customer " << out << " finished checking out from register " << lane << endl;
    // Check out next person in line
    if (r->numberOfCustomers > 0) {
      Customer c = r->seeNext();
      double finishCheckout = e.simTime + r->minToPay + (c.getOrderSize() * r->minPerItem);
      Event next(EventType::EndCheckout, finishCheckout, c);
      events.enqueue(next);
    }
  }
  void endSimulation() {
    double avgWait = 0;
    for(int i = 0; i < waitTimes.size(); i++) {
      avgWait += waitTimes[i];
      cout << i+1 << ": " << waitTimes[i] << endl;
    }
    avgWait /= waitTimes.size();
    cout << "Average wait time was " << avgWait << endl;
    int maxLineLength = registers[0].maxLineLength;
    for(int i = 1; i < registers.size(); i++) {
      if(registers[i].maxLineLength > maxLineLength)
        maxLineLength = registers[i].maxLineLength;
    }
    cout << "Most customers in line at once " << maxLineLength << endl;
  }
};
<commit_msg>Remove excess verbosity<commit_after>// basic file operations
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <vector>

#include "Customer.hpp"
#include "Event.hpp"
#include "PriorityQueue.hpp"
#include "RegisterQueue.hpp"
using namespace std;

class StoreSimulator{

private:
  PriorityQueue<Event> events;
  vector<RegisterQueue> registers;
  vector<double> waitTimes;
  double simClock;

public:
  StoreSimulator(){
    simClock = 0;
  }

  void startSimulation(int numNormal, int numSelfScan) {
    loadRegisters(numNormal, numSelfScan);
    loadCustomerData();

    while(events.size > 0){
      Event e = events.dequeue();
      simClock = e.simTime;
      if(e.type == EventType::Arrival){
        handleArrival(e);
      }else if(e.type == EventType::EndShopping){
        handleEndShopping(e);
      }else{
        handleEndCheckout(e);
      }
    }
    endSimulation();
  }

  void loadCustomerData(){
    double simClock, avgSelectionTime;
    int items;

    ifstream myfile ("arrival.txt");
    if (myfile.is_open()){
      while (myfile >> simClock >> items >> avgSelectionTime){
        Customer cust(simClock, items, avgSelectionTime) ;
        Event e(EventType::Arrival, simClock, cust);
        events.enqueue(e);
      }
      myfile.close();
    }else
    throw(1);
  }

  void loadRegisters(int numNormal, int numSelfScan){
    for(int i = 0; i < numNormal; i ++){
      RegisterQueue r(1.5, .01);
      registers.push_back(r);
    }
    for(int i = 0; i < numSelfScan; i++){
      RegisterQueue r(3.0, .04);
      registers.push_back(r);
    }
  }

  void handleArrival(Event& e){
    Customer c = e.person;
    double finishShopping = c.getCustomerArrival() + (c.getOrderSize() * c.getTimeToGetItem());
    Event next(EventType::EndShopping, finishShopping, c);
    events.enqueue(next);
  }

  void handleEndShopping(Event& e){
    Customer c = e.person;
    // Find lane with least # of people
    int min = 0;
    for (int i = 1; i < registers.size(); i++) {
      if (registers[i].numberOfCustomers < registers[min].numberOfCustomers)
        min = i;
    }
    RegisterQueue *r = &registers[min];
    c.chooseRegister(min);
    r->enqueue(c);
    // If waiting in line, their EndCheckout is scheduled once they are up
    if(r->numberOfCustomers <= 1) {
      double finishCheckout = e.simTime + r->minToPay + (c.getOrderSize() * r->minPerItem);
      Event next(EventType::EndCheckout, finishCheckout, c);
      events.enqueue(next);
    }
  }
  void handleEndCheckout(Event& e){
    Customer out = e.person;
    int lane = out.getRegister();
    RegisterQueue *r = &registers[lane];

    // Calculate wait time = EndCheckout - (arrival + shopTime + checkoutTime)
    double wait = e.simTime // EndCheckout
                  - (out.getCustomerArrival() // arrival
                     + (out.getOrderSize() * out.getTimeToGetItem()) // shopTime
                     + r->minToPay + (out.getOrderSize() * r->minPerItem)); // checkoutTime
    waitTimes.push_back(wait);

    // Let person leave simulation
    try {
      r->dequeue();
    } catch(char const* e) {
      cout << "- Caught eror: " << e << endl;
    }
    // Check out next person in line
    if (r->numberOfCustomers > 0) {
      Customer c = r->seeNext();
      double finishCheckout = e.simTime + r->minToPay + (c.getOrderSize() * r->minPerItem);
      Event next(EventType::EndCheckout, finishCheckout, c);
      events.enqueue(next);
    }
  }
  void endSimulation() {
    double avgWait = 0;
    for(int i = 0; i < waitTimes.size(); i++) {
      avgWait += waitTimes[i];
    }
    avgWait /= waitTimes.size();
    cout << "Average wait time was " << avgWait << endl;
    int maxLineLength = registers[0].maxLineLength;
    for(int i = 1; i < registers.size(); i++) {
      if(registers[i].maxLineLength > maxLineLength)
        maxLineLength = registers[i].maxLineLength;
    }
    cout << "Most customers in line at once " << maxLineLength << endl;
  }
};
<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#define DBUG
//#define DENORMAL_CHECK
#include <pthread.h>
#include <sys/resource.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>

#include "RTcmixMain.h"
#include "prototypes.h"
#include <ugens.h>
#include <ug_intro.h>
#include "version.h"
#include "rt.h"
#include "heap.h"
#include "sockdefs.h"
#include "notetags.h"           // contains defs for note-tagging
#include "dbug.h"
#include <MMPrint.h>

#ifdef MAXMSP
// BGG -- this is how you print to the console.app now in max/msp
extern "C" {
extern
void cpost(char *fmt, ...);
}
#endif

extern "C" {
#ifdef SGI
  void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
  void sigfpe_handler(int sig);
#endif
}

/* ----------------------------------------------------- detect_denormals --- */
/* Unmask "denormalized operand" bit of the x86 FPU control word, so that
   any operations with denormalized numbers will raise a SIGFPE signal,
   and our handler will be called.  NOTE: This is for debugging only!
   This will not tell you how many denormal ops there are, so just because
   the exception is thrown doesn't mean there's a serious problem.  For
   more info, see: http://www.musicdsp.org/files/other001.txt.
*/
#ifdef LINUX
#ifdef DENORMAL_CHECK
static void
detect_denormals()
{
   #include <fpu_control.h>
   int cw = 0;
   _FPU_GETCW(cw);
   cw &= ~_FPU_MASK_DM;
   _FPU_SETCW(cw);
}
#endif /* DENORMAL_CHECK */
#endif /* LINUX */

#ifndef MAXMSP
/* ----------------------------------------------------------------- main --- */
int
main(int argc, char *argv[], char **env)
{
#ifdef LINUX
 #ifdef DENORMAL_CHECK
   detect_denormals();
 #endif
   signal(SIGFPE, sigfpe_handler);          /* Install signal handler */
#endif /* LINUX */
#ifdef SGI
   flush_all_underflows_to_zero();
#endif

	bzero(MMPrint::mm_print_buf, SIZEOF_MMPRINTBUF);
	MMPrint::mm_print_ptr = MMPrint::mm_print_buf;

   RTcmixMain app(argc, argv, env);
   app.run();

   return 0;
}

#else // MAXMSP
/* ----------------------------------------------------------- rtcmixmain --- */
RTcmixMain *app;

extern "C" {
int
rtcmixmain()	// BGG mm -- now called this for max/msp
{
	bzero(MMPrint::mm_print_buf, SIZEOF_MMPRINTBUF);
	MMPrint::mm_print_ptr = MMPrint::mm_print_buf;

// BGG no argc and argv in max/msp version mm
   app = new RTcmixMain();
   app->run(); // in max/msp this just sets it all up...

   return 0;
}

// BGG -- these will be called from max/msp, an instrument will set
// the *_ready value to signal to return something other than NULL
// max/msp will then respond accordingly

int bang_ready = 0;

int check_bang()
{
   if (bang_ready == 1) {
      bang_ready = 0;
      return(1);
   } else {
      return(0);
   }
}

int vals_ready = 0;
float maxmsp_vals[MAXDISPARGS];

int check_vals(float thevals[])
{
   int i, tvals;

   if (vals_ready > 0) { // vals_ready will contain how many vals to return
      for (i = 0; i < vals_ready; i++) thevals[i] = maxmsp_vals[i];
      tvals = vals_ready;
      vals_ready = 0;
      return(tvals);
   } else {
      return(0);
   }
}

char *get_print()
{
	return(MMPrint::mm_print_buf);
}

void reset_print()
{
	bzero(MMPrint::mm_print_buf, SIZEOF_MMPRINTBUF);
	MMPrint::mm_print_ptr = MMPrint::mm_print_buf;
}

#ifdef IOS
// BGG ii -- we can fill these directly in iOS, so we pass them in below
extern short *maxmsp_outbuf; // defined in mm_rtsetparams.cpp
extern short *maxmsp_inbuf; // defined in mm_rtsetparams.cpp

void pullTraverse(short *inbuf, short *outbuf)
{
	maxmsp_inbuf = inbuf;
	maxmsp_outbuf = outbuf;

	app->inTraverse(NULL, NULL);
}
#else // not IOS
void pullTraverse()
{
	app->inTraverse(NULL, NULL);
}
#endif // IOS

// BGG ii -- mm_inbuf/mm_outbuf come as NULL, they are passed in pulltraverse()
int maxmsp_rtsetparams(float sr, int nchans, int vecsize, float *mm_inbuf, float *mm_outbuf)
{
	int status;

	status = (int)app->mm_rtsetparams(sr, nchans, vecsize, mm_inbuf, mm_outbuf);

	return(status);
}

// these are set from inlets on the rtcmix~ object, using PFields to
// control the Instruments
// rtcmix~ is set to constrain up to a max of 19 inlets for PFields
float inletvals[20];

void pfield_set(int inlet, float pval)
{
	inletvals[inlet-1] = pval;
}

// use this to pass in info from the max/msp [buffer~] object.  All
// we need to know is the number of frames, nchans, and starting address
// flags and globals to support this stuff, arg!
#define MAX_MM_BUFS 50
mm_buf mm_bufs[MAX_MM_BUFS]; // mm_buf defined in rtdefs.h
int mm_buf_input = -1; // used in rtgetin() and then rtsetinput()
int n_mm_bufs = 0;

void buffer_set(char *bufname, float *bufstart, int nframes, int nchans, int modtime)
{
	int i;
	int foundit;

	if (strlen(bufname) >= MAX_MM_BUFNAME) { // defined in rtdefs.h
		rtcmix_warn("bufset", "[buffer~] name has to be < %d chars", MAX_MM_BUFNAME);
		return;
	}

	// check to see if this is already set
	foundit = 0;
	for (i = 0; i < n_mm_bufs; i++) {
			if (strcmp(bufname, mm_bufs[i].name) == 0) {
				foundit = 1;
				if (modtime > mm_bufs[i].mm_modtime) { // buffer was modified
					mm_bufs[i].mm_bufstart = bufstart;
					mm_bufs[i].mm_buf_nframes = nframes;
					mm_bufs[i].mm_buf_chans = nchans;
					mm_bufs[i].mm_modtime = modtime;
				}
				break;
			}
	}

	// it's a new one
	if (foundit == 0) {
		if (n_mm_bufs >= MAX_MM_BUFS) {
			rtcmix_warn("bufset", "we can only do %d [buffer~] buffers at present, sorry!", MAX_MM_BUFS);
			return;
		}
		strcpy(mm_bufs[n_mm_bufs].name, bufname);
		mm_bufs[n_mm_bufs].mm_bufstart = bufstart;
		mm_bufs[n_mm_bufs].mm_buf_nframes = nframes;
		mm_bufs[n_mm_bufs].mm_buf_chans = nchans;
		mm_bufs[n_mm_bufs].mm_modtime = modtime;
		n_mm_bufs++;
	}
}

// called for the [flush] message; deletes and reinstantiates the rtQueue
// and rtHeap, thus flushing all scheduled events in the future
void flush_sched()
{
	app->resetQueueHeap(); // in RTcmixMain.cpp
}

// this is for dynamic loading of RTcmix instruments (for development)
// only one rtcmix~ may be instantiated for this to work
// the scorefile load() system is disabled in rtcmix~
void loadinst(char *dsoname)
{
	// the dsoname should be a fully-qualified pathname to the dynlib
	app->doload(dsoname);
}

void unloadinst()
{
	// it is necessary to unload the dso directly, otherwise the dlopen()
	// system keeps it in memory
	app->unload();
}

} // end of "extern C"  BGG mm
#endif // MAXMSP

<commit_msg>added support for internal sound buffer access for OpenFrameworks -- BGG<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#define DBUG
//#define DENORMAL_CHECK
#include <pthread.h>
#include <sys/resource.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>

#include "RTcmixMain.h"
#include "prototypes.h"
#include <ugens.h>
#include <ug_intro.h>
#include "version.h"
#include "rt.h"
#include "heap.h"
#include "sockdefs.h"
#include "notetags.h"           // contains defs for note-tagging
#include "dbug.h"
#include <MMPrint.h>

#ifdef MAXMSP
// BGG -- this is how you print to the console.app now in max/msp
extern "C" {
extern
void cpost(char *fmt, ...);
}
#endif

extern "C" {
#ifdef SGI
  void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
  void sigfpe_handler(int sig);
#endif
}

/* ----------------------------------------------------- detect_denormals --- */
/* Unmask "denormalized operand" bit of the x86 FPU control word, so that
   any operations with denormalized numbers will raise a SIGFPE signal,
   and our handler will be called.  NOTE: This is for debugging only!
   This will not tell you how many denormal ops there are, so just because
   the exception is thrown doesn't mean there's a serious problem.  For
   more info, see: http://www.musicdsp.org/files/other001.txt.
*/
#ifdef LINUX
#ifdef DENORMAL_CHECK
static void
detect_denormals()
{
   #include <fpu_control.h>
   int cw = 0;
   _FPU_GETCW(cw);
   cw &= ~_FPU_MASK_DM;
   _FPU_SETCW(cw);
}
#endif /* DENORMAL_CHECK */
#endif /* LINUX */

#ifndef MAXMSP
/* ----------------------------------------------------------------- main --- */
int
main(int argc, char *argv[], char **env)
{
#ifdef LINUX
 #ifdef DENORMAL_CHECK
   detect_denormals();
 #endif
   signal(SIGFPE, sigfpe_handler);          /* Install signal handler */
#endif /* LINUX */
#ifdef SGI
   flush_all_underflows_to_zero();
#endif

	bzero(MMPrint::mm_print_buf, SIZEOF_MMPRINTBUF);
	MMPrint::mm_print_ptr = MMPrint::mm_print_buf;

   RTcmixMain app(argc, argv, env);
   app.run();

   return 0;
}

#else // MAXMSP
/* ----------------------------------------------------------- rtcmixmain --- */
RTcmixMain *app;

extern "C" {
int
rtcmixmain()	// BGG mm -- now called this for max/msp
{
	bzero(MMPrint::mm_print_buf, SIZEOF_MMPRINTBUF);
	MMPrint::mm_print_ptr = MMPrint::mm_print_buf;

// BGG no argc and argv in max/msp version mm
   app = new RTcmixMain();
   app->run(); // in max/msp this just sets it all up...

   return 0;
}

// BGG -- these will be called from max/msp, an instrument will set
// the *_ready value to signal to return something other than NULL
// max/msp will then respond accordingly

int bang_ready = 0;

int check_bang()
{
   if (bang_ready == 1) {
      bang_ready = 0;
      return(1);
   } else {
      return(0);
   }
}

int vals_ready = 0;
float maxmsp_vals[MAXDISPARGS];

int check_vals(float thevals[])
{
   int i, tvals;

   if (vals_ready > 0) { // vals_ready will contain how many vals to return
      for (i = 0; i < vals_ready; i++) thevals[i] = maxmsp_vals[i];
      tvals = vals_ready;
      vals_ready = 0;
      return(tvals);
   } else {
      return(0);
   }
}

char *get_print()
{
	return(MMPrint::mm_print_buf);
}

void reset_print()
{
	bzero(MMPrint::mm_print_buf, SIZEOF_MMPRINTBUF);
	MMPrint::mm_print_ptr = MMPrint::mm_print_buf;
}

#ifdef IOS
// BGG ii -- we can fill these directly in iOS, so we pass them in below
extern short *maxmsp_outbuf; // defined in mm_rtsetparams.cpp
extern short *maxmsp_inbuf; // defined in mm_rtsetparams.cpp

void pullTraverse(short *inbuf, short *outbuf)
{
	maxmsp_inbuf = inbuf;
	maxmsp_outbuf = outbuf;

	app->inTraverse(NULL, NULL);
}
#else // not IOS
void pullTraverse()
{
	app->inTraverse(NULL, NULL);
}
#endif // IOS

#ifdef PD
int pd_rtsetparams(float sr, int nchans, int vecsize, float *mm_inbuf, float *mm_outbuf)
#else
int maxmsp_rtsetparams(float sr, int nchans, int vecsize, float *mm_inbuf, float *mm_outbuf)
#endif
{
	int status;

	status = (int)app->mm_rtsetparams(sr, nchans, vecsize, mm_inbuf, mm_outbuf);

	return(status);
}

// these are set from inlets on the rtcmix~ object, using PFields to
// control the Instruments
// rtcmix~ is set to constrain up to a max of 19 inlets for PFields
float inletvals[20];

void pfield_set(int inlet, float pval)
{
	inletvals[inlet-1] = pval;
}

// use this to pass in info from the max/msp [buffer~] object.  All
// we need to know is the number of frames, nchans, and starting address
// flags and globals to support this stuff, arg!
#define MAX_MM_BUFS 50
mm_buf mm_bufs[MAX_MM_BUFS]; // mm_buf defined in rtdefs.h
int mm_buf_input = -1; // used in rtgetin() and then rtsetinput()
int n_mm_bufs = 0;

void buffer_set(char *bufname, float *bufstart, int nframes, int nchans, int modtime)
{
	int i;
	int foundit;

	if (strlen(bufname) >= MAX_MM_BUFNAME) { // defined in rtdefs.h
		rtcmix_warn("bufset", "[buffer~] name has to be < %d chars", MAX_MM_BUFNAME);
		return;
	}

	// check to see if this is already set
	foundit = 0;
	for (i = 0; i < n_mm_bufs; i++) {
			if (strcmp(bufname, mm_bufs[i].name) == 0) {
				foundit = 1;
				if (modtime > mm_bufs[i].mm_modtime) { // buffer was modified
					mm_bufs[i].mm_bufstart = bufstart;
					mm_bufs[i].mm_buf_nframes = nframes;
					mm_bufs[i].mm_buf_chans = nchans;
					mm_bufs[i].mm_modtime = modtime;
				}
				break;
			}
	}

	// it's a new one
	if (foundit == 0) {
		if (n_mm_bufs >= MAX_MM_BUFS) {
			rtcmix_warn("bufset", "we can only do %d [buffer~] buffers at present, sorry!", MAX_MM_BUFS);
			return;
		}
		strcpy(mm_bufs[n_mm_bufs].name, bufname);
		mm_bufs[n_mm_bufs].mm_bufstart = bufstart;
		mm_bufs[n_mm_bufs].mm_buf_nframes = nframes;
		mm_bufs[n_mm_bufs].mm_buf_chans = nchans;
		mm_bufs[n_mm_bufs].mm_modtime = modtime;
		n_mm_bufs++;
	}
}

#ifdef OPENFRAMEWORKS

// this is used for OpenFrameworks; will read a soundfile into a named
// buffer for use by rtinput("MMBUF", "namedbuffer")
void OF_buffer_load_set(char *filename, char *bufname, float insk, float dur)
{
	int i;
	int foundit;
	float *bufstart; // starting pointer to buffer
	int nframes, nchans;

	if (strlen(bufname) >= MAX_MM_BUFNAME) { // defined in rtdefs.h
		rterror("OF_buffer_set", "the bufname has to be < %d chars", MAX_MM_BUFNAME);
		return;
	}

	// check to see if this is already set
	foundit = 0;
	for (i = 0; i < n_mm_bufs; i++) {
			if (strcmp(bufname, mm_bufs[i].name) == 0) foundit = 1;
			break;
	}

	// it's a new one
	if (foundit == 0) {
		if (n_mm_bufs >= MAX_MM_BUFS) {
			rterror("OF_buffer_set", "we can only do %d buffers at present, sorry!", MAX_MM_BUFS);
			return;
		}

		bufstart = sound_sample_buf_read(filename, (double)insk, (double)dur, &nframes, &nchans);
		if (bufstart == NULL) {
			rterror("OF_buffer_set", "problem reading soundfile %s into memory", filename);
			return;
		}

		strcpy(mm_bufs[n_mm_bufs].name, bufname);
		mm_bufs[n_mm_bufs].mm_bufstart = bufstart;
		mm_bufs[n_mm_bufs].mm_buf_nframes = nframes;
		mm_bufs[n_mm_bufs].mm_buf_chans = nchans;
		mm_bufs[n_mm_bufs].mm_modtime = 0; // this isn't used in OF right now
		n_mm_bufs++;
	}
}

#endif // OPENFRAMEWORKS

// returns the number of frames in a named buffer
int mm_buf_getframes(char *bufname)
{
   int i;
   int foundit;

   // find the bufname
   foundit = 0;
   for (i = 0; i < n_mm_bufs; i++) {
         if (strcmp(bufname, mm_bufs[i].name) == 0) foundit = 1;
         break;
   }

	return mm_bufs[i].mm_buf_nframes;
}

// returns the number of channels of a named buffer
int mm_buf_getchans(char *bufname)
{
   int i;
   int foundit;

   // find the bufname
   foundit = 0;
   for (i = 0; i < n_mm_bufs; i++) {
         if (strcmp(bufname, mm_bufs[i].name) == 0) foundit = 1;
         break;
   }

	if (foundit == 0) {
		rtcmix_warn("mm_buf_getchans", "there is no buffer named %s", bufname);
		return -1;
	}

	return mm_bufs[i].mm_buf_chans;
}

// called for the [flush] message; deletes and reinstantiates the rtQueue
// and rtHeap, thus flushing all scheduled events in the future
void flush_sched()
{
	app->resetQueueHeap(); // in RTcmixMain.cpp
}

// this is for dynamic loading of RTcmix instruments (for development)
// only one rtcmix~ may be instantiated for this to work
// the scorefile load() system is disabled in rtcmix~
void loadinst(char *dsoname)
{
	// the dsoname should be a fully-qualified pathname to the dynlib
	app->doload(dsoname);
}

void unloadinst()
{
	// it is necessary to unload the dso directly, otherwise the dlopen()
	// system keeps it in memory
	app->unload();
}

} // end of "extern C"  BGG mm
#endif // MAXMSP

<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
//#define DBUG
#define MAIN
#include <pthread.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream.h>
#include <signal.h>
#ifdef LINUX
   #include <sys/soundcard.h>
#endif
#ifdef SGI
   #include <dmedia/audio.h>
#endif
#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include <version.h>
#include "../rtstuff/rt.h"
#include "sockdefs.h"
#include "notetags.h"           // contains defs for note-tagging
#include "../H/dbug.h"
#include "rtcmix_parse.h"

extern "C" {
  int ug_intro();
  int profile();
  void rtprofile();
#ifdef SGI
  void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
  void flush_fpe(int sig);
#endif
}

rt_item *rt_list;     /* can't put this in globals.h because of rt.h trouble */

/* ---------------------------------------------------------------- usage --- */
static void
usage()
{
   printf("\n"
      "Usage:  CMIX [options] [arguments] < minc_script.sco\n"
      "\n"
      "   or, to use Perl instead of Minc:\n"
      "        PCMIX [options] [arguments] < perl_script.pl\n"
      "   or:\n"
      "        PCMIX [options] perl_script.pl [arguments]\n"
      "\n"
      "   or, to use Python:\n"
      "        PYCMIX [options] [arguments] < python_script.py\n"
      "\n"
      "        options:\n"
      "           -i       run in interactive mode\n"
      "           -n       no init script (interactive mode only)\n"
      "           -o NUM   socket offset (interactive mode only)\n"
      "           -c       enable continuous control (rtupdates)\n"
      "          NOTE: -s, -d, and -e are not yet implemented\n"
      "           -s NUM   start time (seconds)\n"
      "           -d NUM   duration (seconds)\n"
      "           -e NUM   end time (seconds)\n"
      "           -f NAME  read score from NAME instead of stdin\n"
      "                      (Minc and Python only)\n"
      "           --debug  enter parser debugger (Perl only)\n"
      "           -q       quiet -- suppress print to screen\n"
      "           -Q       really quiet -- not even peak stats\n"
      "           -h       this help blurb\n"
      "        Other options, and arguments, passed on to parser.\n\n");
   exit(1);
}

/* --------------------------------------------------------- init_globals --- */
static void
init_globals()
{
   int i;

   RTBUFSAMPS = 8192;           /* default, modifiable with rtsetparams */
   NCHANS = 2;
   audioNCHANS = 0;

#ifdef LINUX
   for (i = 0; i < MAXBUS; i++)
      in_port[i] = out_port[i] = 0;
#endif /* LINUX */
#ifdef SGI
   in_port = 0;
   out_port = 0;
#endif /* SGI */

   rtInteractive = 0;
   noParse = 0;
   socknew = 0;
   rtsetparams_called = 0;

   audio_on = 0;
   audio_config = 1;
   play_audio = 1;              /* modified with set_option */
   full_duplex = 0;
   check_peaks = 1;
   report_clipping = 1;

   /* I can't believe these were never initialized */
   baseTime = 0;
   elapsed = 0;
   schedtime = 0;

   output_data_format = -1;
   output_header_type = -1;
   normalize_output_floats = 0;
   is_float_format = 0;
   rtoutsfname = NULL;

   tags_on = 0;

   rtfileit = 0;                /* signal writing to soundfile */
   rtoutfile = 0;

   print_is_on = 1;

   for (i = 0; i < MAXBUS; i++) {
      AuxToAuxPlayList[i] = -1; /* The playback order for AUX buses */
      ToOutPlayList[i] = -1;    /* The playback order for AUX buses */
      ToAuxPlayList[i] =-1;     /* The playback order for AUX buses */
   }

   for (i = 0; i < MAX_INPUT_FDS; i++)
      inputFileTable[i].fd = NO_FD;

   init_buf_ptrs();
}

/* ------------------------------------------------------- signal_handler --- */
static void
signal_handler(int signo)
{
#ifdef DBUG
   printf("Signal handler called (signo %d)\n", signo);
#endif

   if (rtsetparams_called) {
      close_audio_ports();
      rtreportstats();
      rtcloseout();
   }
   else
      closesf();

   exit(1);
}

/* ----------------------------------------------------------------- main --- */
int
main(int argc, char *argv[])
{
   int         i, j, xargc;
   int         retcode;                 /* for mutexes */
   char        *infile;
   char        *xargv[MAXARGS + 1];
   pthread_t   sockitThread, inTraverseThread;

   init_globals();

#ifdef LINUX
   signal(SIGFPE, flush_fpe);          /* Install signal handler */
#endif
#ifdef SGI
   flush_all_underflows_to_zero();
#endif

   /* Call signal_handler on cntl-C. */
   if (signal(SIGINT, signal_handler) == SIG_ERR) {
      fprintf(stderr, "Error installing signal handler.\n");
      exit(1);
   }

   xargv[0] = argv[0];
   for (i = 1; i <= MAXARGS; i++)
      xargv[i] = NULL;
   xargc = 1;

   /* Process command line, copying any args we don't handle into
      <xargv> for parsers to deal with.
   */
   for (i = 1; i < argc; i++) {
      char *arg = argv[i];

      if (arg[0] == '-') {
         switch (arg[1]) {
            case 'h':
               usage();
               break;
            case 'i':               /* for separate parseit thread */
               rtInteractive = 1;
               audio_config = 0;
               break;
            case 'n':               /* for use in rtInteractive mode only */
               noParse = 1;
               break;
            case 'Q':               /* reall quiet */
               report_clipping = 0; /* (then fall through) */
            case 'q':               /* quiet */
               print_is_on = 0;
               break;
            case 'o':               /* NOTE NOTE NOTE: will soon replace -s */
            case 's':               /* set up a socket offset */
               if (++i >= argc) {
                  fprintf(stderr, "You didn't give a socket offset.\n");
                  exit(1);
               }
               socknew = atoi(argv[i]);
               printf("listening on socket: %d\n", MYPORT + socknew);
               break;
//            case 's':               /* start time (unimplemented) */
            case 'd':               /* duration to play for (unimplemented) */
            case 'e':               /* time to stop playing (unimplemented) */
               fprintf(stderr, "-s, -d, -e options not yet implemented\n");
               exit(1);
               break;
            case 'c':     /* set up for continuous control (note tags on) */
               tags_on = 1;
               printf("rtupdates enabled\n");
               curtag = 1;          /* "0" is reserved for all notes */
               for (j = 0; j < MAXPUPS; j++)     /* initialize element 0 */
                  pupdatevals[0][j] = NOPUPDATE;
               break;
            case 'f':     /* use file name arg instead of stdin as score */
               if (++i >= argc) {
                  fprintf(stderr, "You didn't give a file name.\n");
                  exit(1);
               }
               infile = argv[i];
               use_script_file(infile);
               break;
            case '-':           /* accept "--debug" and pass to Perl as "-d" */
               if (strncmp(&arg[2], "debug", 10) == 0)
                  xargv[xargc++] = strdup("-d");
               break;
            default:
               xargv[xargc++] = arg;    /* copy for parser */
         }
      }
      else
         xargv[xargc++] = arg;          /* copy for parser */

      if (xargc >= MAXARGS) {
         fprintf(stderr, "Too many command-line options.\n");
         exit(1);
      }
   }

   /* Banner */
   if (print_is_on)
      printf("--------> %s %s (%s) <--------\n",
                                      RTCMIX_NAME, RTCMIX_VERSION, argv[0]);

   ug_intro();                  /* introduce standard routines */
   profile();                   /* introduce user-written routines etc. */
   rtprofile();                 /* introduce real-time user-written routines */

   setbuf(stdout, NULL);        /*  Want to see stdout errors */

   /* In rtInteractive mode, we set up RTcmix to listen for score data
      over a socket, and then parse this, schedule instruments, and play
      them concurrently. The socket listening and parsing go in one
      thread, and the scheduler and instrument code go in another.

      When not in rtInteractive mode, RTcmix parses the score, schedules
      all instruments, and then plays them -- in that order. No threads.
   */
   if (rtInteractive) {

      if (print_is_on)
         fprintf(stdout, "rtInteractive mode set\n");

      /* Read an initialization score. */
      if (!noParse) {
         int status;

#ifdef DBUG
         cout << "Parsing once ...\n";
#endif
         status = parse_score(xargc, xargv);
         if (status != 0)
            exit(1);
      }

      /* Create parsing thread. */
#ifdef DBUG
      fprintf(stdout, "creating sockit() thread\n");
#endif
      retcode = pthread_create(&sockitThread, NULL, sockit, (void *) "");
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread create failed\n");
      }

      /* Create scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "creating inTraverse() thread\n");
#endif
      retcode = pthread_create(&inTraverseThread, NULL, inTraverse,
                                                             (void *) "");
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread create failed\n");
      }

      /* Join scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "joining inTraverse() thread\n");
#endif
      /* retcode = pthread_join(inTraverseThread, NULL); */
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread join failed\n");
      }

      /* Join parsing thread. */
#ifdef DBUG
      fprintf(stdout, "joining sockit() thread\n");
#endif
      /* retcode = pthread_join(sockitThread, NULL); */
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread join failed\n");
      }

      if (!noParse)
         destroy_parser();
   }
   else {
      int status;

      status = parse_score(xargc, xargv);
      if (status == 0)
         inTraverse(NULL);
      else
         exit(status);

      destroy_parser();
   }

   /* DJT:  this instead of above joins */
   while (rtInteractive) {};

   closesf();

   return 0;
}

<commit_msg>Facility for checking for fpu denormal ops.<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
//#define DBUG
//#define DENORMAL_CHECK
#define MAIN
#include <pthread.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream.h>
#include <signal.h>
#ifdef LINUX
   #include <sys/soundcard.h>
#endif
#ifdef SGI
   #include <dmedia/audio.h>
#endif
#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include <version.h>
#include "../rtstuff/rt.h"
#include "sockdefs.h"
#include "notetags.h"           // contains defs for note-tagging
#include "../H/dbug.h"
#include "rtcmix_parse.h"

extern "C" {
  int ug_intro();
  int profile();
  void rtprofile();
#ifdef SGI
  void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
  void flush_fpe(int sig);
#endif
}

rt_item *rt_list;     /* can't put this in globals.h because of rt.h trouble */

/* ---------------------------------------------------------------- usage --- */
static void
usage()
{
   printf("\n"
      "Usage:  CMIX [options] [arguments] < minc_script.sco\n"
      "\n"
      "   or, to use Perl instead of Minc:\n"
      "        PCMIX [options] [arguments] < perl_script.pl\n"
      "   or:\n"
      "        PCMIX [options] perl_script.pl [arguments]\n"
      "\n"
      "   or, to use Python:\n"
      "        PYCMIX [options] [arguments] < python_script.py\n"
      "\n"
      "        options:\n"
      "           -i       run in interactive mode\n"
      "           -n       no init script (interactive mode only)\n"
      "           -o NUM   socket offset (interactive mode only)\n"
      "           -c       enable continuous control (rtupdates)\n"
      "          NOTE: -s, -d, and -e are not yet implemented\n"
      "           -s NUM   start time (seconds)\n"
      "           -d NUM   duration (seconds)\n"
      "           -e NUM   end time (seconds)\n"
      "           -f NAME  read score from NAME instead of stdin\n"
      "                      (Minc and Python only)\n"
      "           --debug  enter parser debugger (Perl only)\n"
      "           -q       quiet -- suppress print to screen\n"
      "           -Q       really quiet -- not even peak stats\n"
      "           -h       this help blurb\n"
      "        Other options, and arguments, passed on to parser.\n\n");
   exit(1);
}

/* --------------------------------------------------------- init_globals --- */
static void
init_globals()
{
   int i;

   RTBUFSAMPS = 8192;           /* default, modifiable with rtsetparams */
   NCHANS = 2;
   audioNCHANS = 0;

#ifdef LINUX
   for (i = 0; i < MAXBUS; i++)
      in_port[i] = out_port[i] = 0;
#endif /* LINUX */
#ifdef SGI
   in_port = 0;
   out_port = 0;
#endif /* SGI */

   rtInteractive = 0;
   noParse = 0;
   socknew = 0;
   rtsetparams_called = 0;

   audio_on = 0;
   audio_config = 1;
   play_audio = 1;              /* modified with set_option */
   full_duplex = 0;
   check_peaks = 1;
   report_clipping = 1;

   /* I can't believe these were never initialized */
   baseTime = 0;
   elapsed = 0;
   schedtime = 0;

   output_data_format = -1;
   output_header_type = -1;
   normalize_output_floats = 0;
   is_float_format = 0;
   rtoutsfname = NULL;

   tags_on = 0;

   rtfileit = 0;                /* signal writing to soundfile */
   rtoutfile = 0;

   print_is_on = 1;

   for (i = 0; i < MAXBUS; i++) {
      AuxToAuxPlayList[i] = -1; /* The playback order for AUX buses */
      ToOutPlayList[i] = -1;    /* The playback order for AUX buses */
      ToAuxPlayList[i] =-1;     /* The playback order for AUX buses */
   }

   for (i = 0; i < MAX_INPUT_FDS; i++)
      inputFileTable[i].fd = NO_FD;

   init_buf_ptrs();
}

/* ------------------------------------------------------- signal_handler --- */
static void
signal_handler(int signo)
{
#ifdef DBUG
   printf("Signal handler called (signo %d)\n", signo);
#endif

   if (rtsetparams_called) {
      close_audio_ports();
      rtreportstats();
      rtcloseout();
   }
   else
      closesf();

   exit(1);
}

/* ----------------------------------------------------- detect_denormals --- */
/* Unmask "denormalized operand" bit of the x86 FPU control word, so that
   any operations with denormalized numbers will raise a SIGFPE signal,
   and our handler will be called.  NOTE: This is for debugging only!
   This will not tell you how many denormal ops there are, so just because
   the exception is thrown doesn't mean there's a serious problem.  For
   more info, see: http://www.smartelectronix.com/musicdsp/text/other001.txt.
*/
static void
detect_denormals()
{
#ifdef LINUX
   #include <fpu_control.h>
   int cw = 0;
   _FPU_GETCW(cw);
   cw &= ~_FPU_MASK_DM;
   _FPU_SETCW(cw);
#endif
}

/* ----------------------------------------------------------------- main --- */
int
main(int argc, char *argv[])
{
   int         i, j, xargc;
   int         retcode;                 /* for mutexes */
   char        *infile;
   char        *xargv[MAXARGS + 1];
   pthread_t   sockitThread, inTraverseThread;

   init_globals();

#ifdef LINUX
 #ifdef DENORMAL_CHECK
   detect_denormals();
 #endif
   signal(SIGFPE, flush_fpe);          /* Install signal handler */
#endif /* LINUX */
#ifdef SGI
   flush_all_underflows_to_zero();
#endif

   /* Call signal_handler on cntl-C. */
   if (signal(SIGINT, signal_handler) == SIG_ERR) {
      fprintf(stderr, "Error installing signal handler.\n");
      exit(1);
   }

   xargv[0] = argv[0];
   for (i = 1; i <= MAXARGS; i++)
      xargv[i] = NULL;
   xargc = 1;

   /* Process command line, copying any args we don't handle into
      <xargv> for parsers to deal with.
   */
   for (i = 1; i < argc; i++) {
      char *arg = argv[i];

      if (arg[0] == '-') {
         switch (arg[1]) {
            case 'h':
               usage();
               break;
            case 'i':               /* for separate parseit thread */
               rtInteractive = 1;
               audio_config = 0;
               break;
            case 'n':               /* for use in rtInteractive mode only */
               noParse = 1;
               break;
            case 'Q':               /* reall quiet */
               report_clipping = 0; /* (then fall through) */
            case 'q':               /* quiet */
               print_is_on = 0;
               break;
            case 'o':               /* NOTE NOTE NOTE: will soon replace -s */
            case 's':               /* set up a socket offset */
               if (++i >= argc) {
                  fprintf(stderr, "You didn't give a socket offset.\n");
                  exit(1);
               }
               socknew = atoi(argv[i]);
               printf("listening on socket: %d\n", MYPORT + socknew);
               break;
//            case 's':               /* start time (unimplemented) */
            case 'd':               /* duration to play for (unimplemented) */
            case 'e':               /* time to stop playing (unimplemented) */
               fprintf(stderr, "-s, -d, -e options not yet implemented\n");
               exit(1);
               break;
            case 'c':     /* set up for continuous control (note tags on) */
               tags_on = 1;
               printf("rtupdates enabled\n");
               curtag = 1;          /* "0" is reserved for all notes */
               for (j = 0; j < MAXPUPS; j++)     /* initialize element 0 */
                  pupdatevals[0][j] = NOPUPDATE;
               break;
            case 'f':     /* use file name arg instead of stdin as score */
               if (++i >= argc) {
                  fprintf(stderr, "You didn't give a file name.\n");
                  exit(1);
               }
               infile = argv[i];
               use_script_file(infile);
               break;
            case '-':           /* accept "--debug" and pass to Perl as "-d" */
               if (strncmp(&arg[2], "debug", 10) == 0)
                  xargv[xargc++] = strdup("-d");
               break;
            default:
               xargv[xargc++] = arg;    /* copy for parser */
         }
      }
      else
         xargv[xargc++] = arg;          /* copy for parser */

      if (xargc >= MAXARGS) {
         fprintf(stderr, "Too many command-line options.\n");
         exit(1);
      }
   }

   /* Banner */
   if (print_is_on)
      printf("--------> %s %s (%s) <--------\n",
                                      RTCMIX_NAME, RTCMIX_VERSION, argv[0]);

   ug_intro();                  /* introduce standard routines */
   profile();                   /* introduce user-written routines etc. */
   rtprofile();                 /* introduce real-time user-written routines */

   setbuf(stdout, NULL);        /*  Want to see stdout errors */

   /* In rtInteractive mode, we set up RTcmix to listen for score data
      over a socket, and then parse this, schedule instruments, and play
      them concurrently. The socket listening and parsing go in one
      thread, and the scheduler and instrument code go in another.

      When not in rtInteractive mode, RTcmix parses the score, schedules
      all instruments, and then plays them -- in that order. No threads.
   */
   if (rtInteractive) {

      if (print_is_on)
         fprintf(stdout, "rtInteractive mode set\n");

      /* Read an initialization score. */
      if (!noParse) {
         int status;

#ifdef DBUG
         cout << "Parsing once ...\n";
#endif
         status = parse_score(xargc, xargv);
         if (status != 0)
            exit(1);
      }

      /* Create parsing thread. */
#ifdef DBUG
      fprintf(stdout, "creating sockit() thread\n");
#endif
      retcode = pthread_create(&sockitThread, NULL, sockit, (void *) "");
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread create failed\n");
      }

      /* Create scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "creating inTraverse() thread\n");
#endif
      retcode = pthread_create(&inTraverseThread, NULL, inTraverse,
                                                             (void *) "");
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread create failed\n");
      }

      /* Join scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "joining inTraverse() thread\n");
#endif
      /* retcode = pthread_join(inTraverseThread, NULL); */
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread join failed\n");
      }

      /* Join parsing thread. */
#ifdef DBUG
      fprintf(stdout, "joining sockit() thread\n");
#endif
      /* retcode = pthread_join(sockitThread, NULL); */
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread join failed\n");
      }

      if (!noParse)
         destroy_parser();
   }
   else {
      int status;

      status = parse_score(xargc, xargv);
      if (status == 0)
         inTraverse(NULL);
      else
         exit(status);

      destroy_parser();
   }

   /* DJT:  this instead of above joins */
   while (rtInteractive) {};

   closesf();

   return 0;
}

<|endoftext|>


<commit_before>Int_t AliTPCDisplayClusters(Int_t eventn) {
   cerr<<"Displaying clusters...\n";

   TFile *file=TFile::Open("galice.root");
   if (!file->IsOpen()) {cerr<<"Can't open galice.root !\n"; return 1;}

   TFile *cf=TFile::Open("AliTPCclusters.root");
   if (!cf->IsOpen()){cerr<<"Can't open AliTPCclusters.root !\n"; return 3;}

   AliTPCParam *dig=(AliTPCParam *)cf->Get("75x40_100x60");
   if (!dig) {cerr<<"TPC parameters have not been found !\n"; return 2;}

   TCanvas *c1=new TCanvas("cdisplay", "Cluster display",0,0,700,730);
   TView *v=new TView(1);
   v->SetRange(-430,-560,-430,430,560,1710);
   c1->Clear();
   c1->SetFillColor(1);
   c1->SetTheta(90.);
   c1->SetPhi(0.);

   AliTPCClustersArray *ca=new AliTPCClustersArray;
   ca->Setup(dig);
   ca->SetClusterType("AliTPCcluster");
   char  cname[100];
   sprintf(cname,"TreeC_TPC_%d",eventn);

   ca->ConnectTree(cname);
   Int_t nrows=Int_t(ca->GetTree()->GetEntries());
   for (Int_t n=0; n<nrows; n++) {
       AliSegmentID *s=ca->LoadEntry(n);
       Int_t sec,row;
       dig->AdjustSectorRow(s->GetID(),sec,row);
       AliTPCClustersRow &clrow = *ca->GetRow(sec,row);
       Int_t ncl=clrow.GetArray()->GetEntriesFast();
       TPolyMarker3D *pm=new TPolyMarker3D(ncl);
       while (ncl--) {
           AliTPCcluster *cl=(AliTPCcluster*)clrow[ncl];
           Double_t x=dig->GetPadRowRadii(sec,row), y=cl->GetY(), z=cl->GetZ();
           Float_t cs, sn, tmp;
           dig->AdjustCosSin(sec,cs,sn);
           tmp = x*cs-y*sn; y= x*sn+y*cs; x=tmp;
           pm->SetPoint(ncl,x,y,z);
       }
       ca->ClearRow(sec,row);
       pm->SetMarkerSize(1); pm->SetMarkerColor(2); pm->SetMarkerStyle(1);
       pm->Draw();
   }
   delete ca;
   cf->Close();

   TGeometry *geom=(TGeometry*)file->Get("AliceGeom");
   geom->Draw("same");
   c1->Modified(); c1->Update();

   file->Close();
   return 0;
}
<commit_msg>Default event number set to 0<commit_after>Int_t AliTPCDisplayClusters(Int_t eventn=0) {
   cerr<<"Displaying clusters...\n";

   TFile *file=TFile::Open("galice.root");
   if (!file->IsOpen()) {cerr<<"Can't open galice.root !\n"; return 1;}

   TFile *cf=TFile::Open("AliTPCclusters.root");
   if (!cf->IsOpen()){cerr<<"Can't open AliTPCclusters.root !\n"; return 3;}

   AliTPCParam *dig=(AliTPCParam *)cf->Get("75x40_100x60");
   if (!dig) {cerr<<"TPC parameters have not been found !\n"; return 2;}

   TCanvas *c1=new TCanvas("cdisplay", "Cluster display",0,0,700,730);
   TView *v=new TView(1);
   v->SetRange(-430,-560,-430,430,560,1710);
   c1->Clear();
   c1->SetFillColor(1);
   c1->SetTheta(90.);
   c1->SetPhi(0.);

   AliTPCClustersArray *ca=new AliTPCClustersArray;
   ca->Setup(dig);
   ca->SetClusterType("AliTPCcluster");
   char  cname[100];
   sprintf(cname,"TreeC_TPC_%d",eventn);

   ca->ConnectTree(cname);
   Int_t nrows=Int_t(ca->GetTree()->GetEntries());
   for (Int_t n=0; n<nrows; n++) {
       AliSegmentID *s=ca->LoadEntry(n);
       Int_t sec,row;
       dig->AdjustSectorRow(s->GetID(),sec,row);
       AliTPCClustersRow &clrow = *ca->GetRow(sec,row);
       Int_t ncl=clrow.GetArray()->GetEntriesFast();
       TPolyMarker3D *pm=new TPolyMarker3D(ncl);
       while (ncl--) {
           AliTPCcluster *cl=(AliTPCcluster*)clrow[ncl];
           Double_t x=dig->GetPadRowRadii(sec,row), y=cl->GetY(), z=cl->GetZ();
           Float_t cs, sn, tmp;
           dig->AdjustCosSin(sec,cs,sn);
           tmp = x*cs-y*sn; y= x*sn+y*cs; x=tmp;
           pm->SetPoint(ncl,x,y,z);
       }
       ca->ClearRow(sec,row);
       pm->SetMarkerSize(1); pm->SetMarkerColor(2); pm->SetMarkerStyle(1);
       pm->Draw();
   }
   delete ca;
   cf->Close();

   TGeometry *geom=(TGeometry*)file->Get("AliceGeom");
   geom->Draw("same");
   c1->Modified(); c1->Update();

   file->Close();
   return 0;
}
<|endoftext|>


<commit_before>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::emitInstrOpBits(std::ostream &o,
                                     const std::vector<RecordVal> &Vals,
                                     std::map<std::string, unsigned> &OpOrder,
                                     std::map<std::string, bool> &OpContinuous)
{
  for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
    if (Vals[f].getPrefix()) {
      BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();

      // Scan through the field looking for bit initializers of the current
      // variable...
      for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
        Init *I = FieldInitializer->getBit(i);
        if (BitInit *BI = dynamic_cast<BitInit*>(I)) {
          DEBUG(o << "      // bit init: f: " << f << ", i: " << i << "\n");
        } else if (UnsetInit *UI = dynamic_cast<UnsetInit*>(I)) {
          DEBUG(o << "      // unset init: f: " << f << ", i: " << i << "\n");
        } else if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(I)) {
          TypedInit *TI = VBI->getVariable();
          if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
            // If the bits of the field are laid out consecutively in the
            // instruction, then instead of separately ORing in bits, just
            // mask and shift the entire field for efficiency.
            if (OpContinuous[VI->getName()]) {
              // already taken care of in the loop above, thus there is no
              // need to individually OR in the bits

              // for debugging, output the regular version anyway, commented
              DEBUG(o << "      // Value |= getValueBit(op"
                      << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
                      << ")" << " << " << i << ";\n");
            } else {
              o << "      Value |= getValueBit(op" << OpOrder[VI->getName()]
                << ", " << VBI->getBitNum()
                << ")" << " << " << i << ";\n";
            }
          } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
            // FIXME: implement this!
            std::cerr << "Error: FieldInit not implemented!\n";
            abort();
          } else {
            std::cerr << "Error: unimplemented case in "
                      << "CodeEmitterGen::emitInstrOpBits()\n";
            abort();
          }
        }
      }
    }
  }
}

void CodeEmitterGen::run(std::ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  EmitSourceFileHeader("Machine Code Emitter", o);
  o << "namespace llvm {\n\n";
  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  // Emit function declaration
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
    << "  unsigned Value = 0;\n"
    << "  DEBUG(std::cerr << MI);\n"
    << "  switch (MI.getOpcode()) {\n";

  // Emit a case statement for each opcode
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    o << "    case " << Namespace << R->getName() << ": {\n"
      << "      DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    // For little-endian instruction bit encodings, reverse the bit order
    if (Target.isLittleEndianEncoding()) {
      unsigned numBits = BI->getNumBits();
      BitsInit *NewBI = new BitsInit(numBits);
      for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
        unsigned bitSwapIdx = numBits - bit - 1;
        Init *OrigBit = BI->getBit(bit);
        Init *BitSwap = BI->getBit(bitSwapIdx);
        NewBI->setBit(bit, BitSwap);
        NewBI->setBit(bitSwapIdx, OrigBit);
      }
      if (numBits % 2) {
        unsigned middle = (numBits + 1) / 2;
        NewBI->setBit(middle, BI->getBit(middle));
      }
      BI = NewBI;
    }

    unsigned Value = 0;
    const std::vector<RecordVal> &Vals = R->getValues();

    DEBUG(o << "      // prefilling: ");
    // Start by filling in fixed values...
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
        DEBUG(o << B->getValue());
      } else {
        DEBUG(o << "0");
      }
    }
    DEBUG(o << "\n");

    DEBUG(o << "      // " << *R->getValue("Inst") << "\n");
    o << "      Value = " << Value << "U;\n\n";

    // Loop over all of the fields in the instruction, determining which are the
    // operands to the instruction.
    unsigned op = 0;
    std::map<std::string, unsigned> OpOrder;
    std::map<std::string, bool> OpContinuous;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        BitsInit *InstInit = BI;
        int beginBitInVar = -1, endBitInVar = -1;
        int beginBitInInst = -1, endBitInInst = -1;
        bool continuous = true;

        for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
          if (VarBitInit *VBI =
              dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
            TypedInit *TI = VBI->getVariable();
            if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
              // only process the current variable
              if (VI->getName() != Vals[i].getName())
                continue;

              if (beginBitInVar == -1)
                beginBitInVar = VBI->getBitNum();

              if (endBitInVar == -1)
                endBitInVar = VBI->getBitNum();
              else {
                if (endBitInVar == (int)VBI->getBitNum() + 1)
                  endBitInVar = VBI->getBitNum();
                else {
                  continuous = false;
                  break;
                }
              }

              if (beginBitInInst == -1)
                beginBitInInst = bit;
              if (endBitInInst == -1)
                endBitInInst = bit;
              else {
                if (endBitInInst == bit + 1)
                  endBitInInst = bit;
                else {
                  continuous = false;
                  break;
                }
              }

              // maintain same distance between bits in field and bits in
              // instruction. if the relative distances stay the same
              // throughout,
              if (beginBitInVar - (int)VBI->getBitNum() !=
                  beginBitInInst - bit) {
                continuous = false;
                break;
              }
            }
          }
        }

        // If we have found no bit in "Inst" which comes from this field, then
        // this is not an operand!!
        if (beginBitInInst != -1) {
          o << "      // op" << op << ": " << Vals[i].getName() << "\n"
            << "      int64_t op" << op
            <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
          //<< "   MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
          OpOrder[Vals[i].getName()] = op++;

          DEBUG(o << "      // Var: begin = " << beginBitInVar
                  << ", end = " << endBitInVar
                  << "; Inst: begin = " << beginBitInInst
                  << ", end = " << endBitInInst << "\n");

          if (continuous) {
            DEBUG(o << "      // continuous: op" << OpOrder[Vals[i].getName()]
                    << "\n");

            // Mask off the right bits
            // Low mask (ie. shift, if necessary)
            assert(endBitInVar >= 0 && "Negative shift amount in masking!");
            if (endBitInVar != 0) {
              o << "      op" << OpOrder[Vals[i].getName()]
                << " >>= " << endBitInVar << ";\n";
              beginBitInVar -= endBitInVar;
              endBitInVar = 0;
            }

            // High mask
            o << "      op" << OpOrder[Vals[i].getName()]
              << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";

            // Shift the value to the correct place (according to place in inst)
            assert(endBitInInst >= 0 && "Negative shift amount!");
            if (endBitInInst != 0)
              o << "      op" << OpOrder[Vals[i].getName()]
              << " <<= " << endBitInInst << ";\n";

            // Just OR in the result
            o << "      Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
          }

          // otherwise, will be taken care of in the loop below using this
          // value:
          OpContinuous[Vals[i].getName()] = continuous;
        }
      }
    }

    emitInstrOpBits(o, Vals, OpOrder, OpContinuous);

    o << "      break;\n"
      << "    }\n";
  }

  // Default case: unhandled opcode
  o << "  default:\n"
    << "    std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
    << "    abort();\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n\n";

  o << "} // End llvm namespace \n";
}
<commit_msg>The code emitter generator only supports targets with 32-bit instruction words.  There is no way for one of these targets to have a > 32-bit immediate!<commit_after>//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// CodeEmitterGen uses the descriptions of instructions and their fields to
// construct an automated code emitter: a function that, given a MachineInstr,
// returns the (currently, 32-bit unsigned) value of the instruction.
//
//===----------------------------------------------------------------------===//

#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

void CodeEmitterGen::emitInstrOpBits(std::ostream &o,
                                     const std::vector<RecordVal> &Vals,
                                     std::map<std::string, unsigned> &OpOrder,
                                     std::map<std::string, bool> &OpContinuous)
{
  for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
    if (Vals[f].getPrefix()) {
      BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();

      // Scan through the field looking for bit initializers of the current
      // variable...
      for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
        Init *I = FieldInitializer->getBit(i);
        if (BitInit *BI = dynamic_cast<BitInit*>(I)) {
          DEBUG(o << "      // bit init: f: " << f << ", i: " << i << "\n");
        } else if (UnsetInit *UI = dynamic_cast<UnsetInit*>(I)) {
          DEBUG(o << "      // unset init: f: " << f << ", i: " << i << "\n");
        } else if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(I)) {
          TypedInit *TI = VBI->getVariable();
          if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
            // If the bits of the field are laid out consecutively in the
            // instruction, then instead of separately ORing in bits, just
            // mask and shift the entire field for efficiency.
            if (OpContinuous[VI->getName()]) {
              // already taken care of in the loop above, thus there is no
              // need to individually OR in the bits

              // for debugging, output the regular version anyway, commented
              DEBUG(o << "      // Value |= getValueBit(op"
                      << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
                      << ")" << " << " << i << ";\n");
            } else {
              o << "      Value |= getValueBit(op" << OpOrder[VI->getName()]
                << ", " << VBI->getBitNum()
                << ")" << " << " << i << ";\n";
            }
          } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
            // FIXME: implement this!
            std::cerr << "Error: FieldInit not implemented!\n";
            abort();
          } else {
            std::cerr << "Error: unimplemented case in "
                      << "CodeEmitterGen::emitInstrOpBits()\n";
            abort();
          }
        }
      }
    }
  }
}

void CodeEmitterGen::run(std::ostream &o) {
  CodeGenTarget Target;
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  EmitSourceFileHeader("Machine Code Emitter", o);
  o << "namespace llvm {\n\n";
  std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";

  // Emit function declaration
  o << "unsigned " << Target.getName() << "CodeEmitter::"
    << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
    << "  unsigned Value = 0;\n"
    << "  DEBUG(std::cerr << MI);\n"
    << "  switch (MI.getOpcode()) {\n";

  // Emit a case statement for each opcode
  for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
       I != E; ++I) {
    Record *R = *I;
    o << "    case " << Namespace << R->getName() << ": {\n"
      << "      DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";

    BitsInit *BI = R->getValueAsBitsInit("Inst");

    // For little-endian instruction bit encodings, reverse the bit order
    if (Target.isLittleEndianEncoding()) {
      unsigned numBits = BI->getNumBits();
      BitsInit *NewBI = new BitsInit(numBits);
      for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
        unsigned bitSwapIdx = numBits - bit - 1;
        Init *OrigBit = BI->getBit(bit);
        Init *BitSwap = BI->getBit(bitSwapIdx);
        NewBI->setBit(bit, BitSwap);
        NewBI->setBit(bitSwapIdx, OrigBit);
      }
      if (numBits % 2) {
        unsigned middle = (numBits + 1) / 2;
        NewBI->setBit(middle, BI->getBit(middle));
      }
      BI = NewBI;
    }

    unsigned Value = 0;
    const std::vector<RecordVal> &Vals = R->getValues();

    DEBUG(o << "      // prefilling: ");
    // Start by filling in fixed values...
    for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
      if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
        Value |= B->getValue() << (e-i-1);
        DEBUG(o << B->getValue());
      } else {
        DEBUG(o << "0");
      }
    }
    DEBUG(o << "\n");

    DEBUG(o << "      // " << *R->getValue("Inst") << "\n");
    o << "      Value = " << Value << "U;\n\n";

    // Loop over all of the fields in the instruction, determining which are the
    // operands to the instruction.
    unsigned op = 0;
    std::map<std::string, unsigned> OpOrder;
    std::map<std::string, bool> OpContinuous;
    for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
      if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
        // Is the operand continuous? If so, we can just mask and OR it in
        // instead of doing it bit-by-bit, saving a lot in runtime cost.
        BitsInit *InstInit = BI;
        int beginBitInVar = -1, endBitInVar = -1;
        int beginBitInInst = -1, endBitInInst = -1;
        bool continuous = true;

        for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
          if (VarBitInit *VBI =
              dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
            TypedInit *TI = VBI->getVariable();
            if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
              // only process the current variable
              if (VI->getName() != Vals[i].getName())
                continue;

              if (beginBitInVar == -1)
                beginBitInVar = VBI->getBitNum();

              if (endBitInVar == -1)
                endBitInVar = VBI->getBitNum();
              else {
                if (endBitInVar == (int)VBI->getBitNum() + 1)
                  endBitInVar = VBI->getBitNum();
                else {
                  continuous = false;
                  break;
                }
              }

              if (beginBitInInst == -1)
                beginBitInInst = bit;
              if (endBitInInst == -1)
                endBitInInst = bit;
              else {
                if (endBitInInst == bit + 1)
                  endBitInInst = bit;
                else {
                  continuous = false;
                  break;
                }
              }

              // maintain same distance between bits in field and bits in
              // instruction. if the relative distances stay the same
              // throughout,
              if (beginBitInVar - (int)VBI->getBitNum() !=
                  beginBitInInst - bit) {
                continuous = false;
                break;
              }
            }
          }
        }

        // If we have found no bit in "Inst" which comes from this field, then
        // this is not an operand!!
        if (beginBitInInst != -1) {
          o << "      // op" << op << ": " << Vals[i].getName() << "\n"
            << "      int op" << op
            <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
          //<< "   MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
          OpOrder[Vals[i].getName()] = op++;

          DEBUG(o << "      // Var: begin = " << beginBitInVar
                  << ", end = " << endBitInVar
                  << "; Inst: begin = " << beginBitInInst
                  << ", end = " << endBitInInst << "\n");

          if (continuous) {
            DEBUG(o << "      // continuous: op" << OpOrder[Vals[i].getName()]
                    << "\n");

            // Mask off the right bits
            // Low mask (ie. shift, if necessary)
            assert(endBitInVar >= 0 && "Negative shift amount in masking!");
            if (endBitInVar != 0) {
              o << "      op" << OpOrder[Vals[i].getName()]
                << " >>= " << endBitInVar << ";\n";
              beginBitInVar -= endBitInVar;
              endBitInVar = 0;
            }

            // High mask
            o << "      op" << OpOrder[Vals[i].getName()]
              << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";

            // Shift the value to the correct place (according to place in inst)
            assert(endBitInInst >= 0 && "Negative shift amount!");
            if (endBitInInst != 0)
              o << "      op" << OpOrder[Vals[i].getName()]
              << " <<= " << endBitInInst << ";\n";

            // Just OR in the result
            o << "      Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
          }

          // otherwise, will be taken care of in the loop below using this
          // value:
          OpContinuous[Vals[i].getName()] = continuous;
        }
      }
    }

    emitInstrOpBits(o, Vals, OpOrder, OpContinuous);

    o << "      break;\n"
      << "    }\n";
  }

  // Default case: unhandled opcode
  o << "  default:\n"
    << "    std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
    << "    abort();\n"
    << "  }\n"
    << "  return Value;\n"
    << "}\n\n";

  o << "} // End llvm namespace \n";
}
<|endoftext|>