<commit_before>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */
#include <sstream>
#include <cmath>
#include <chrono>

#include "Log.h"
#include "Net.h"

#include "StatLayer.h"

#include "Trainer.h"

namespace Conv {

	Trainer::Trainer(Conv::NetGraph& graph, TrainerSettings settings) :
		graph_(graph), settings_(settings) {
		LOGDEBUG << "Instance created";

		// We need a training layer to select training samples and some kind of
		// loss function to minimize
		if (graph_.GetTrainingNodes().size() == 0 || graph_.GetLossNodes().size() == 0) {
			FATAL("Net doesn't have training layer or loss function layer!");
		}

		// Ask the Net for parameters
		graph_.GetParameters(parameters_);

		LOGDEBUG << "Optimizing " << parameters_.size() << " sets of parameters.";

		unsigned int w = 0;

		for (unsigned int p = 0; p < parameters_.size(); p++) {
			w += parameters_[p]->data.elements();

			// Allocate Tensors for momentum
			Tensor* last_delta = new Tensor();
			Tensor* accumulated_gradient = new Tensor();
			last_delta->Resize(parameters_[p]->data);
			last_delta->Clear();
			accumulated_gradient->Resize(parameters_[p]->data);
			accumulated_gradient->Clear();

			last_deltas_.push_back(last_delta);
			accumulated_gradients_.push_back(accumulated_gradient);
		}

		// Outputs the number of weights
		LOGDEBUG << "Weights: " << w;

		first_training_layer_ = dynamic_cast<TrainingLayer*>(graph_.GetTrainingNodes()[0]->layer);
		sample_count_ = first_training_layer_->GetLabelWidth() * first_training_layer_->GetLabelHeight()
    * first_training_layer_->GetBatchSize();
}

void Trainer::Train (unsigned int epochs) {
  // net_.SetTestOnlyStatDisabled (false);
  graph_.SetIsTesting(false);

  for (unsigned int e = 0; e < epochs; e++)
    Epoch();

  // net_.SetTestOnlyStatDisabled (false);
}

void Trainer::Test() {
	datum aggregate_loss = 0.0;
	datum* loss_sums = new datum[graph_.GetLossNodes().size()];
	for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++)
		loss_sums[n] = 0;

  unsigned int iterations = (first_training_layer_->GetSamplesInTestingSet()
                             / first_training_layer_->GetBatchSize()) + 1;
  iterations = (unsigned int) ( ( (datum) iterations) *
                                settings_.testing_ratio);

	for (NetGraphNode* training_node : graph_.GetTrainingNodes())
		(dynamic_cast<TrainingLayer*>(training_node->layer))->SetTestingMode(true);

  graph_.SetIsTesting(true);

  LOGDEBUG << "Testing, iterations: " << iterations <<
           ", batch size: " << first_training_layer_->GetBatchSize();

  auto t_begin = std::chrono::system_clock::now();

  for (unsigned int i = 0; i < iterations; i++) {
    graph_.FeedForward();
    for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++) {
      LossFunctionLayer* lossfunction_layer = dynamic_cast<LossFunctionLayer*>(graph_.GetLossNodes()[n]->layer);
			loss_sums[n] += lossfunction_layer->CalculateLossFunction();
			aggregate_loss += loss_sums[n];
		}
	}

  auto t_end = std::chrono::system_clock::now();
  std::chrono::duration<double> t_diff = t_end - t_begin;
  LOGINFO << "Testing, sps: " <<
          (datum) (sample_count_ * iterations)
          / (datum) t_diff.count();

  LOGINFO << "Testing, tps: " <<
          1000000.0f * (datum) t_diff.count() /
          (datum) (sample_count_ * iterations) << " us";

	for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++) {
		LossFunctionLayer* lossfunction_layer = dynamic_cast<LossFunctionLayer*>(graph_.GetLossNodes()[n]->layer);
		LOGDEBUG << "Testing, " << graph_.GetLossNodes()[n]->layer->GetLayerDescription() <<  " lps: " << loss_sums[n] / (datum)(iterations * sample_count_);
	}
	LOGDEBUG << "Testing, aggregate lps: " << aggregate_loss / (datum)(iterations * sample_count_);

	for (unsigned int n = 0; n < graph_.GetStatNodes().size(); n++) {
		StatLayer* stat_layer = dynamic_cast<StatLayer*>(graph_.GetStatNodes()[n]->layer);
    std::stringstream epochname;
    epochname << "Testing  - Epoch " << epoch_ << " -";
    stat_layer->Print (epochname.str(), false);
    stat_layer->Reset();
	}

	for (NetGraphNode* training_node : graph_.GetTrainingNodes())
		(dynamic_cast<TrainingLayer*>(training_node->layer))->SetTestingMode(false);

  graph_.SetIsTesting(false);

	delete[] loss_sums;
}

void Trainer::Epoch() {
	datum aggregate_loss = 0.0;
	datum* loss_sums = new datum[graph_.GetLossNodes().size()];
	for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++)
		loss_sums[n] = 0;

  unsigned int iterations =
    settings_.iterations == 0 ?
    first_training_layer_->GetSamplesInTrainingSet() :
    settings_.iterations;
  iterations = (unsigned int) ( ( (datum) iterations) *
                                settings_.epoch_training_ratio);

  unsigned int fiftieth = 0;
  unsigned int tenth = 0;

	for (NetGraphNode* training_node : graph_.GetTrainingNodes())
		(dynamic_cast<TrainingLayer*>(training_node->layer))->SetTestingMode(false);

  LOGDEBUG << "Epoch: " << epoch_ << ", it: " << iterations <<
           ", bsize: " << first_training_layer_->GetBatchSize() * settings_.sbatchsize << ", lr0: " <<
           CalculateLR (epoch_ * iterations) << std::endl;

  auto t_begin = std::chrono::system_clock::now();

  for (unsigned int i = 0; i < iterations; i++) {
    if ( (50 * i / iterations) > fiftieth) {
      fiftieth = 50 * i / iterations;
      std::cout << "." << std::flush;
    }

    if ( (10 * i / iterations) > tenth) {
      tenth = 10 * i / iterations;
      std::cout << tenth << "0%" << std::flush;
    }

    // Reset gradients
    for (unsigned int np = 0; np < accumulated_gradients_.size(); np++)
      accumulated_gradients_[np]->Clear();

    for (unsigned int b = 0; b < settings_.sbatchsize; b++) {
      graph_.FeedForward();

      // Save errors
			for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++) {
				LossFunctionLayer* lossfunction_layer = dynamic_cast<LossFunctionLayer*>(graph_.GetLossNodes()[n]->layer);
				loss_sums[n] += lossfunction_layer->CalculateLossFunction();
				aggregate_loss += loss_sums[n];
			}

      // Correct errors
      graph_.BackPropagate();

      unsigned int np = 0;

      // Accumulate gradients
      for (unsigned int l = 0; l < graph_.GetNodes().size(); l++) {
				Layer* const layer = graph_.GetNodes()[l]->layer;
        for (unsigned int p = 0; p < layer->parameters().size(); p++) {
          Tensor& gradients = layer->parameters() [p]->delta;
#ifdef BUILD_OPENCL
          gradients.MoveToCPU();
#endif

          for (unsigned int e = 0; e < gradients.elements(); e++) {
            (* (accumulated_gradients_[np])) [e] += gradients[e];
          }

          np++;
        }
      }
    }

    // Calculate annealed learning rate
    const datum lr =
      CalculateLR (epoch_ * iterations + i);

    // Apply gradients with new learning rate
    ApplyGradients (lr);
  }

  auto t_end = std::chrono::system_clock::now();
  std::chrono::duration<double> t_diff = t_end - t_begin;
  LOGINFO << "Training, sps: " <<
          (datum) (sample_count_ * settings_.sbatchsize
                   * first_training_layer_->GetLossSamplingProbability() * iterations)
          / (datum) t_diff.count();

  LOGINFO << "Training, tps: " <<
          1000000.0f * (datum) t_diff.count() /
          (datum) (sample_count_ * settings_.sbatchsize
                   * first_training_layer_->GetLossSamplingProbability() * iterations) << " us";

  // Display training epoch_error
	for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++) {
		LossFunctionLayer* lossfunction_layer = dynamic_cast<LossFunctionLayer*>(graph_.GetLossNodes()[n]->layer);
		LOGDEBUG << "Training, " << graph_.GetLossNodes()[n]->layer->GetLayerDescription() <<  " lps: " << loss_sums[n] / (datum)(iterations * sample_count_ * settings_.sbatchsize * first_training_layer_->GetLossSamplingProbability());
	}
	LOGDEBUG << "Training, aggregate lps: " << aggregate_loss / (datum)(iterations * sample_count_ * settings_.sbatchsize * first_training_layer_->GetLossSamplingProbability());

	for (unsigned int n = 0; n < graph_.GetStatNodes().size(); n++) {
		StatLayer* stat_layer = dynamic_cast<StatLayer*>(graph_.GetStatNodes()[n]->layer);
    std::stringstream epochname;
    epochname << "Training  - Epoch " << epoch_ << " -";
    stat_layer->Print (epochname.str(), true);
    stat_layer->Reset();
	}

  delete[] loss_sums;
  epoch_++;
}

void Trainer::ApplyGradients (datum lr) {
  unsigned int dp = 0;

	for (unsigned int l = 0; l < graph_.GetNodes().size(); l++) {
		Layer* const layer = graph_.GetNodes()[l]->layer;
    const datum llr = lr * layer->local_lr_;

    for (unsigned int p = 0; p < layer->parameters().size(); p++) {
      CombinedTensor* const param = layer->parameters_[p];
#ifdef BUILD_OPENCL
      param->data.MoveToCPU();
#endif

      for (unsigned int w = 0; w < param->data.elements(); w++) {
        const datum weight = param->data (w);
        const datum l1_gradient = (weight > 0) - (weight < 0);
        const datum l2_gradient = weight;
        const datum w_gradient = (*accumulated_gradients_[dp]) [w];

        /*
         * http://www.iro.umontreal.ca/~pift6266/H10/notes/gradient.html
         *
         * This site says that one should average the gradient over
         * the minibatch
         */
        const datum last_delta = (*last_deltas_[dp]) (w);
        const datum delta =

          // Average of gradient over minibatch
          llr * (w_gradient / (datum) (sample_count_ * settings_.sbatchsize)) +
          // Regularization
          llr * (settings_.l2_weight * l2_gradient + settings_.l1_weight * l1_gradient);

        const datum step = delta + settings_.momentum * last_delta;
        param->data[w] -= step;

        // Backup delta
        (*last_deltas_[dp]) [w] = step;
      }

      dp++;
    }
  }
}

std::ostream& operator<< (std::ostream & output,
                          const TrainerSettings settings) {
  output << "LR: " << settings.learning_rate << ", ";
  output << "GM: " << settings.gamma << ", ";
  output << "EX: " << settings.exponent << ", ";
  output << "SB: " << settings.sbatchsize << ", ";
  output << "PB: " << settings.pbatchsize << ", ";
  output << "L1: " << settings.l1_weight << ", ";
  output << "L2: " << settings.l2_weight << ", ";
  output << "MM: " << settings.momentum;
  return output;
}

}
<commit_msg>Trainer: Fixed aggregate loss output<commit_after>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */
#include <sstream>
#include <cmath>
#include <chrono>

#include "Log.h"
#include "Net.h"

#include "StatLayer.h"

#include "Trainer.h"

namespace Conv {

	Trainer::Trainer(Conv::NetGraph& graph, TrainerSettings settings) :
		graph_(graph), settings_(settings) {
		LOGDEBUG << "Instance created";

		// We need a training layer to select training samples and some kind of
		// loss function to minimize
		if (graph_.GetTrainingNodes().size() == 0 || graph_.GetLossNodes().size() == 0) {
			FATAL("Net doesn't have training layer or loss function layer!");
		}

		// Ask the Net for parameters
		graph_.GetParameters(parameters_);

		LOGDEBUG << "Optimizing " << parameters_.size() << " sets of parameters.";

		unsigned int w = 0;

		for (unsigned int p = 0; p < parameters_.size(); p++) {
			w += parameters_[p]->data.elements();

			// Allocate Tensors for momentum
			Tensor* last_delta = new Tensor();
			Tensor* accumulated_gradient = new Tensor();
			last_delta->Resize(parameters_[p]->data);
			last_delta->Clear();
			accumulated_gradient->Resize(parameters_[p]->data);
			accumulated_gradient->Clear();

			last_deltas_.push_back(last_delta);
			accumulated_gradients_.push_back(accumulated_gradient);
		}

		// Outputs the number of weights
		LOGDEBUG << "Weights: " << w;

		first_training_layer_ = dynamic_cast<TrainingLayer*>(graph_.GetTrainingNodes()[0]->layer);
		sample_count_ = first_training_layer_->GetLabelWidth() * first_training_layer_->GetLabelHeight()
    * first_training_layer_->GetBatchSize();
}

void Trainer::Train (unsigned int epochs) {
  // net_.SetTestOnlyStatDisabled (false);
  graph_.SetIsTesting(false);

  for (unsigned int e = 0; e < epochs; e++)
    Epoch();

  // net_.SetTestOnlyStatDisabled (false);
}

void Trainer::Test() {
	datum aggregate_loss = 0.0;
	datum* loss_sums = new datum[graph_.GetLossNodes().size()];
	for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++)
		loss_sums[n] = 0;

  unsigned int iterations = (first_training_layer_->GetSamplesInTestingSet()
                             / first_training_layer_->GetBatchSize()) + 1;
  iterations = (unsigned int) ( ( (datum) iterations) *
                                settings_.testing_ratio);

	for (NetGraphNode* training_node : graph_.GetTrainingNodes())
		(dynamic_cast<TrainingLayer*>(training_node->layer))->SetTestingMode(true);

  graph_.SetIsTesting(true);

  LOGDEBUG << "Testing, iterations: " << iterations <<
           ", batch size: " << first_training_layer_->GetBatchSize();

  auto t_begin = std::chrono::system_clock::now();

  for (unsigned int i = 0; i < iterations; i++) {
    graph_.FeedForward();
    for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++) {
      LossFunctionLayer* lossfunction_layer = dynamic_cast<LossFunctionLayer*>(graph_.GetLossNodes()[n]->layer);
			const datum loss = lossfunction_layer->CalculateLossFunction();
			loss_sums[n] += loss;
			aggregate_loss += loss;
		}
	}

  auto t_end = std::chrono::system_clock::now();
  std::chrono::duration<double> t_diff = t_end - t_begin;
  LOGINFO << "Testing, sps: " <<
          (datum) (sample_count_ * iterations)
          / (datum) t_diff.count();

  LOGINFO << "Testing, tps: " <<
          1000000.0f * (datum) t_diff.count() /
          (datum) (sample_count_ * iterations) << " us";

	for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++) {
		LossFunctionLayer* lossfunction_layer = dynamic_cast<LossFunctionLayer*>(graph_.GetLossNodes()[n]->layer);
		LOGDEBUG << "Testing, " << graph_.GetLossNodes()[n]->layer->GetLayerDescription() <<  " lps: " << loss_sums[n] / (datum)(iterations * sample_count_);
	}
	LOGDEBUG << "Testing, aggregate lps: " << aggregate_loss / (datum)(iterations * sample_count_);

	for (unsigned int n = 0; n < graph_.GetStatNodes().size(); n++) {
		StatLayer* stat_layer = dynamic_cast<StatLayer*>(graph_.GetStatNodes()[n]->layer);
    std::stringstream epochname;
    epochname << "Testing  - Epoch " << epoch_ << " -";
    stat_layer->Print (epochname.str(), false);
    stat_layer->Reset();
	}

	for (NetGraphNode* training_node : graph_.GetTrainingNodes())
		(dynamic_cast<TrainingLayer*>(training_node->layer))->SetTestingMode(false);

  graph_.SetIsTesting(false);

	delete[] loss_sums;
}

void Trainer::Epoch() {
	datum aggregate_loss = 0.0;
	datum* loss_sums = new datum[graph_.GetLossNodes().size()];
	for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++)
		loss_sums[n] = 0;

  unsigned int iterations =
    settings_.iterations == 0 ?
    first_training_layer_->GetSamplesInTrainingSet() :
    settings_.iterations;
  iterations = (unsigned int) ( ( (datum) iterations) *
                                settings_.epoch_training_ratio);

  unsigned int fiftieth = 0;
  unsigned int tenth = 0;

	for (NetGraphNode* training_node : graph_.GetTrainingNodes())
		(dynamic_cast<TrainingLayer*>(training_node->layer))->SetTestingMode(false);

  LOGDEBUG << "Epoch: " << epoch_ << ", it: " << iterations <<
           ", bsize: " << first_training_layer_->GetBatchSize() * settings_.sbatchsize << ", lr0: " <<
           CalculateLR (epoch_ * iterations) << std::endl;

  auto t_begin = std::chrono::system_clock::now();

  for (unsigned int i = 0; i < iterations; i++) {
    if ( (50 * i / iterations) > fiftieth) {
      fiftieth = 50 * i / iterations;
      std::cout << "." << std::flush;
    }

    if ( (10 * i / iterations) > tenth) {
      tenth = 10 * i / iterations;
      std::cout << tenth << "0%" << std::flush;
    }

    // Reset gradients
    for (unsigned int np = 0; np < accumulated_gradients_.size(); np++)
      accumulated_gradients_[np]->Clear();

    for (unsigned int b = 0; b < settings_.sbatchsize; b++) {
      graph_.FeedForward();

      // Save errors
			for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++) {
				LossFunctionLayer* lossfunction_layer = dynamic_cast<LossFunctionLayer*>(graph_.GetLossNodes()[n]->layer);
				const datum loss = lossfunction_layer->CalculateLossFunction();
				loss_sums[n] += loss;
				aggregate_loss += loss;
			}

      // Correct errors
      graph_.BackPropagate();

      unsigned int np = 0;

      // Accumulate gradients
      for (unsigned int l = 0; l < graph_.GetNodes().size(); l++) {
				Layer* const layer = graph_.GetNodes()[l]->layer;
        for (unsigned int p = 0; p < layer->parameters().size(); p++) {
          Tensor& gradients = layer->parameters() [p]->delta;
#ifdef BUILD_OPENCL
          gradients.MoveToCPU();
#endif

          for (unsigned int e = 0; e < gradients.elements(); e++) {
            (* (accumulated_gradients_[np])) [e] += gradients[e];
          }

          np++;
        }
      }
    }

    // Calculate annealed learning rate
    const datum lr =
      CalculateLR (epoch_ * iterations + i);

    // Apply gradients with new learning rate
    ApplyGradients (lr);
  }

  auto t_end = std::chrono::system_clock::now();
  std::chrono::duration<double> t_diff = t_end - t_begin;
  LOGINFO << "Training, sps: " <<
          (datum) (sample_count_ * settings_.sbatchsize
                   * first_training_layer_->GetLossSamplingProbability() * iterations)
          / (datum) t_diff.count();

  LOGINFO << "Training, tps: " <<
          1000000.0f * (datum) t_diff.count() /
          (datum) (sample_count_ * settings_.sbatchsize
                   * first_training_layer_->GetLossSamplingProbability() * iterations) << " us";

  // Display training epoch_error
	for (unsigned int n = 0; n < graph_.GetLossNodes().size(); n++) {
		LossFunctionLayer* lossfunction_layer = dynamic_cast<LossFunctionLayer*>(graph_.GetLossNodes()[n]->layer);
		LOGDEBUG << "Training, " << graph_.GetLossNodes()[n]->layer->GetLayerDescription() <<  " lps: " << loss_sums[n] / (datum)(iterations * sample_count_ * settings_.sbatchsize * first_training_layer_->GetLossSamplingProbability());
	}
	LOGDEBUG << "Training, aggregate lps: " << aggregate_loss / (datum)(iterations * sample_count_ * settings_.sbatchsize * first_training_layer_->GetLossSamplingProbability());

	for (unsigned int n = 0; n < graph_.GetStatNodes().size(); n++) {
		StatLayer* stat_layer = dynamic_cast<StatLayer*>(graph_.GetStatNodes()[n]->layer);
    std::stringstream epochname;
    epochname << "Training  - Epoch " << epoch_ << " -";
    stat_layer->Print (epochname.str(), true);
    stat_layer->Reset();
	}

  delete[] loss_sums;
  epoch_++;
}

void Trainer::ApplyGradients (datum lr) {
  unsigned int dp = 0;

	for (unsigned int l = 0; l < graph_.GetNodes().size(); l++) {
		Layer* const layer = graph_.GetNodes()[l]->layer;
    const datum llr = lr * layer->local_lr_;

    for (unsigned int p = 0; p < layer->parameters().size(); p++) {
      CombinedTensor* const param = layer->parameters_[p];
#ifdef BUILD_OPENCL
      param->data.MoveToCPU();
#endif

      for (unsigned int w = 0; w < param->data.elements(); w++) {
        const datum weight = param->data (w);
        const datum l1_gradient = (weight > 0) - (weight < 0);
        const datum l2_gradient = weight;
        const datum w_gradient = (*accumulated_gradients_[dp]) [w];

        /*
         * http://www.iro.umontreal.ca/~pift6266/H10/notes/gradient.html
         *
         * This site says that one should average the gradient over
         * the minibatch
         */
        const datum last_delta = (*last_deltas_[dp]) (w);
        const datum delta =

          // Average of gradient over minibatch
          llr * (w_gradient / (datum) (sample_count_ * settings_.sbatchsize)) +
          // Regularization
          llr * (settings_.l2_weight * l2_gradient + settings_.l1_weight * l1_gradient);

        const datum step = delta + settings_.momentum * last_delta;
        param->data[w] -= step;

        // Backup delta
        (*last_deltas_[dp]) [w] = step;
      }

      dp++;
    }
  }
}

std::ostream& operator<< (std::ostream & output,
                          const TrainerSettings settings) {
  output << "LR: " << settings.learning_rate << ", ";
  output << "GM: " << settings.gamma << ", ";
  output << "EX: " << settings.exponent << ", ";
  output << "SB: " << settings.sbatchsize << ", ";
  output << "PB: " << settings.pbatchsize << ", ";
  output << "L1: " << settings.l1_weight << ", ";
  output << "L2: " << settings.l2_weight << ", ";
  output << "MM: " << settings.momentum;
  return output;
}

}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <node.h>
#include "nan.h"

#include <nanomsg/nn.h>
#include <nanomsg/pubsub.h>
#include <nanomsg/pipeline.h>
#include <nanomsg/bus.h>
#include <nanomsg/pair.h>
#include <nanomsg/reqrep.h>

using namespace v8;

NAN_METHOD(Socket) {
  	NanScope();

	int domain = args[0]->Uint32Value();
	int protocol = args[1]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_socket(domain, protocol);
	if(protocol == NN_SUB)
    	if (nn_setsockopt(domain, NN_SUB, NN_SUB_SUBSCRIBE, "", 0) != 0)
    		return NanThrowError("Could not set subscribe option.");;

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Close) {
  	NanScope();

	int s = args[0]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_close(s);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Setsockopt) {
  	NanScope();

	int s = args[0]->Uint32Value();
	int level = args[1]->Uint32Value();
	int option = args[2]->Uint32Value();
	int optval = args[3]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_setsockopt(s, level, option, &optval, sizeof(optval));

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Getsockopt) {
  	NanScope();

	int s = args[0]->Uint32Value();
	int level = args[1]->Uint32Value();
	int option = args[2]->Uint32Value();
	int optval = args[3]->Uint32Value();

	// Invoke nanomsg function.
	size_t optsize = sizeof(optval);
 	int ret = nn_getsockopt(s, level, option, &optval, &optsize);
 	(void) ret;

 	// TODO this should return ret value too?
    NanReturnValue(Number::New(optval));
}

NAN_METHOD(Bind) {
  	NanScope();

	int s = args[0]->Uint32Value();
	size_t addr_len = 0;
	char* addr = NanCString(args[1], &addr_len);

	// Invoke nanomsg function.
	int ret = nn_bind(s, addr);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Connect) {
  	NanScope();

	int s = args[0]->Uint32Value();
	size_t addr_len = 0;
	char* addr = NanCString(args[1], &addr_len);

	// Invoke nanomsg function.
	int ret = nn_connect(s, addr);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Shutdown) {
  	NanScope();

	int s = args[0]->Uint32Value();
	int how = args[1]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_shutdown(s, how);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Send) {
  	NanScope();

	int s = args[0]->Uint32Value();
	if (!node::Buffer::HasInstance(args[1]))
		return NanThrowError("second Argument must be a Buffer.");
	Local<Object> obj = args[1]->ToObject();
	char* odata = node::Buffer::Data(obj);
	size_t odata_len = node::Buffer::Length(obj);
	int flags = args[2]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_send(s, odata, odata_len, flags);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Recv) {
  	NanScope();

	int s = args[0]->Uint32Value();
	int flags = args[1]->Uint32Value();

	// Invoke nanomsg function.
	void *retbuf = NULL;
	int ret = nn_recv(s, &retbuf, NN_MSG, flags);

	// TODO multiple return args
	if (ret > -1) {
    	NanReturnValue(NanNewBufferHandle((char*) retbuf, ret));
    } else {
    	NanReturnValue(Number::New(ret));
    }
}

NAN_METHOD(Errno) {
  	NanScope();

	// Invoke nanomsg function.
	int ret = nn_errno ();

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Strerr) {
  	NanScope();

  	int errnum = args[0]->Uint32Value();

	// Invoke nanomsg function.
	const char* err = nn_strerror (errnum);

    NanReturnValue(String::New(err));
}

class NanomsgPollWorker : public NanAsyncWorker {
 public:
  NanomsgPollWorker(NanCallback *callback, int s, int events)
    : NanAsyncWorker(callback), s(s), events(events) {}
  ~NanomsgPollWorker() {}

  // Executed inside the worker-thread.
  // It is not safe to access V8, or V8 data structures
  // here, so everything we need for input and output
  // should go on `this`.
  void Execute () {
    struct nn_pollfd fd = { 0, 0, 0 };
	fd.fd = s;
	fd.events = events;
	int rval = nn_poll (&fd, 1, 0);
	err = rval < 0 ? nn_errno() : 0;
	revents = fd.revents;
  }

  // Executed when the async work is complete
  // this function will be run inside the main event loop
  // so it is safe to use V8 again
  void HandleOKCallback () {
    NanScope();

    Local<Value> argv[] = {
        Number::New(err)
      , Number::New(revents)
    };

    callback->Call(2, argv);
  };

 private:
  int s;
  int events;
  int err;
  int revents;
};

// Asynchronous access to the `Estimate()` function
NAN_METHOD(NodeWorker) {
  NanScope();

  int s = args[0]->Uint32Value();
  int events = args[1]->Uint32Value();
  NanCallback *callback = new NanCallback(args[2].As<Function>());

  NanAsyncQueueWorker(new NanomsgPollWorker(callback, s, events));
  NanReturnUndefined();
}

#define EXPORT_METHOD(C, S) C->Set(NanSymbol(# S), FunctionTemplate::New(S)->GetFunction());
#define EXPORT_CONSTANT(C, S) C->Set(NanSymbol(# S), Number::New(S));

void InitAll(Handle<Object> exports) {
	// Export functions.
	EXPORT_METHOD(exports, Socket);
	EXPORT_METHOD(exports, Close);
	EXPORT_METHOD(exports, Setsockopt);
	EXPORT_METHOD(exports, Getsockopt);
	EXPORT_METHOD(exports, Bind);
	EXPORT_METHOD(exports, Connect);
	EXPORT_METHOD(exports, Shutdown);
	EXPORT_METHOD(exports, Send);
	EXPORT_METHOD(exports, Recv);
	EXPORT_METHOD(exports, Errno);
	EXPORT_METHOD(exports, Strerr);
	EXPORT_METHOD(exports, NodeWorker);

	// SP address families.
	EXPORT_CONSTANT(exports, AF_SP);
	EXPORT_CONSTANT(exports, AF_SP_RAW);

	// Socket option levels: Negative numbers are reserved for transports,
	// positive for socket types.
	EXPORT_CONSTANT(exports, NN_SOL_SOCKET);

	//  Generic socket options (NN_SOL_SOCKET level).
	EXPORT_CONSTANT(exports, NN_LINGER);
	EXPORT_CONSTANT(exports, NN_SNDBUF);
	EXPORT_CONSTANT(exports, NN_RCVBUF);
	EXPORT_CONSTANT(exports, NN_SNDTIMEO);
	EXPORT_CONSTANT(exports, NN_RCVTIMEO);
	EXPORT_CONSTANT(exports, NN_RECONNECT_IVL);
	EXPORT_CONSTANT(exports, NN_RECONNECT_IVL_MAX);
	EXPORT_CONSTANT(exports, NN_SNDPRIO);
	EXPORT_CONSTANT(exports, NN_SNDFD);
	EXPORT_CONSTANT(exports, NN_RCVFD);
	EXPORT_CONSTANT(exports, NN_DOMAIN);
	EXPORT_CONSTANT(exports, NN_PROTOCOL);
	EXPORT_CONSTANT(exports, NN_IPV4ONLY);

	// Send/recv options.
	EXPORT_CONSTANT(exports, NN_DONTWAIT);

	// Socket types
	EXPORT_CONSTANT(exports, NN_REQ);
	EXPORT_CONSTANT(exports, NN_REP);
	EXPORT_CONSTANT(exports, NN_PAIR);
	EXPORT_CONSTANT(exports, NN_PUSH);
	EXPORT_CONSTANT(exports, NN_PULL);
	EXPORT_CONSTANT(exports, NN_PUB);
	EXPORT_CONSTANT(exports, NN_SUB);
	EXPORT_CONSTANT(exports, NN_BUS);

	// Polling
	EXPORT_CONSTANT(exports, NN_POLLIN);
	EXPORT_CONSTANT(exports, NN_POLLOUT);
}

NODE_MODULE(node_nanomsg, InitAll)
<commit_msg>Adds options and survey constant.<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <node.h>
#include "nan.h"

#include <nanomsg/nn.h>
#include <nanomsg/pubsub.h>
#include <nanomsg/pipeline.h>
#include <nanomsg/bus.h>
#include <nanomsg/pair.h>
#include <nanomsg/reqrep.h>

using namespace v8;

NAN_METHOD(Socket) {
  	NanScope();

	int domain = args[0]->Uint32Value();
	int protocol = args[1]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_socket(domain, protocol);
	if(protocol == NN_SUB)
    	if (nn_setsockopt(domain, NN_SUB, NN_SUB_SUBSCRIBE, "", 0) != 0)
    		return NanThrowError("Could not set subscribe option.");;

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Close) {
  	NanScope();

	int s = args[0]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_close(s);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Setsockopt) {
  	NanScope();

	int s = args[0]->Uint32Value();
	int level = args[1]->Uint32Value();
	int option = args[2]->Uint32Value();
	int optval = args[3]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_setsockopt(s, level, option, &optval, sizeof(optval));

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Getsockopt) {
  	NanScope();

	int s = args[0]->Uint32Value();
	int level = args[1]->Uint32Value();
	int option = args[2]->Uint32Value();
	int optval = args[3]->Uint32Value();

	// Invoke nanomsg function.
	size_t optsize = sizeof(optval);
 	int ret = nn_getsockopt(s, level, option, &optval, &optsize);
 	(void) ret;

 	// TODO this should return ret value too?
    NanReturnValue(Number::New(optval));
}

NAN_METHOD(Bind) {
  	NanScope();

	int s = args[0]->Uint32Value();
	size_t addr_len = 0;
	char* addr = NanCString(args[1], &addr_len);

	// Invoke nanomsg function.
	int ret = nn_bind(s, addr);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Connect) {
  	NanScope();

	int s = args[0]->Uint32Value();
	size_t addr_len = 0;
	char* addr = NanCString(args[1], &addr_len);

	// Invoke nanomsg function.
	int ret = nn_connect(s, addr);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Shutdown) {
  	NanScope();

	int s = args[0]->Uint32Value();
	int how = args[1]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_shutdown(s, how);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Send) {
  	NanScope();

	int s = args[0]->Uint32Value();
	if (!node::Buffer::HasInstance(args[1]))
		return NanThrowError("second Argument must be a Buffer.");
	Local<Object> obj = args[1]->ToObject();
	char* odata = node::Buffer::Data(obj);
	size_t odata_len = node::Buffer::Length(obj);
	int flags = args[2]->Uint32Value();

	// Invoke nanomsg function.
	int ret = nn_send(s, odata, odata_len, flags);

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Recv) {
  	NanScope();

	int s = args[0]->Uint32Value();
	int flags = args[1]->Uint32Value();

	// Invoke nanomsg function.
	void *retbuf = NULL;
	int ret = nn_recv(s, &retbuf, NN_MSG, flags);

	// TODO multiple return args
	if (ret > -1) {
    	NanReturnValue(NanNewBufferHandle((char*) retbuf, ret));
    } else {
    	NanReturnValue(Number::New(ret));
    }
}

NAN_METHOD(Errno) {
  	NanScope();

	// Invoke nanomsg function.
	int ret = nn_errno ();

    NanReturnValue(Number::New(ret));
}

NAN_METHOD(Strerr) {
  	NanScope();

  	int errnum = args[0]->Uint32Value();

	// Invoke nanomsg function.
	const char* err = nn_strerror (errnum);

    NanReturnValue(String::New(err));
}

class NanomsgPollWorker : public NanAsyncWorker {
 public:
  NanomsgPollWorker(NanCallback *callback, int s, int events)
    : NanAsyncWorker(callback), s(s), events(events) {}
  ~NanomsgPollWorker() {}

  // Executed inside the worker-thread.
  // It is not safe to access V8, or V8 data structures
  // here, so everything we need for input and output
  // should go on `this`.
  void Execute () {
    struct nn_pollfd fd = { 0, 0, 0 };
	fd.fd = s;
	fd.events = events;
	int rval = nn_poll (&fd, 1, 0);
	err = rval < 0 ? nn_errno() : 0;
	revents = fd.revents;
  }

  // Executed when the async work is complete
  // this function will be run inside the main event loop
  // so it is safe to use V8 again
  void HandleOKCallback () {
    NanScope();

    Local<Value> argv[] = {
        Number::New(err)
      , Number::New(revents)
    };

    callback->Call(2, argv);
  };

 private:
  int s;
  int events;
  int err;
  int revents;
};

// Asynchronous access to the `Estimate()` function
NAN_METHOD(NodeWorker) {
  NanScope();

  int s = args[0]->Uint32Value();
  int events = args[1]->Uint32Value();
  NanCallback *callback = new NanCallback(args[2].As<Function>());

  NanAsyncQueueWorker(new NanomsgPollWorker(callback, s, events));
  NanReturnUndefined();
}

#define EXPORT_METHOD(C, S) C->Set(NanSymbol(# S), FunctionTemplate::New(S)->GetFunction());
#define EXPORT_CONSTANT(C, S) C->Set(NanSymbol(# S), Number::New(S));

void InitAll(Handle<Object> exports) {
	// Export functions.
	EXPORT_METHOD(exports, Socket);
	EXPORT_METHOD(exports, Close);
	EXPORT_METHOD(exports, Setsockopt);
	EXPORT_METHOD(exports, Getsockopt);
	EXPORT_METHOD(exports, Bind);
	EXPORT_METHOD(exports, Connect);
	EXPORT_METHOD(exports, Shutdown);
	EXPORT_METHOD(exports, Send);
	EXPORT_METHOD(exports, Recv);
	EXPORT_METHOD(exports, Errno);
	EXPORT_METHOD(exports, Strerr);
	EXPORT_METHOD(exports, NodeWorker);

	// SP address families.
	EXPORT_CONSTANT(exports, AF_SP);
	EXPORT_CONSTANT(exports, AF_SP_RAW);

	// Socket option levels: Negative numbers are reserved for transports,
	// positive for socket types.
	EXPORT_CONSTANT(exports, NN_SOL_SOCKET);

	//  Generic socket options (NN_SOL_SOCKET level).
	EXPORT_CONSTANT(exports, NN_LINGER);
	EXPORT_CONSTANT(exports, NN_SNDBUF);
	EXPORT_CONSTANT(exports, NN_RCVBUF);
	EXPORT_CONSTANT(exports, NN_SNDTIMEO);
	EXPORT_CONSTANT(exports, NN_RCVTIMEO);
	EXPORT_CONSTANT(exports, NN_RECONNECT_IVL);
	EXPORT_CONSTANT(exports, NN_RECONNECT_IVL_MAX);
	EXPORT_CONSTANT(exports, NN_SNDPRIO);
	EXPORT_CONSTANT(exports, NN_SNDFD);
	EXPORT_CONSTANT(exports, NN_RCVFD);
	EXPORT_CONSTANT(exports, NN_DOMAIN);
	EXPORT_CONSTANT(exports, NN_PROTOCOL);
	EXPORT_CONSTANT(exports, NN_IPV4ONLY);

	// Send/recv options.
	EXPORT_CONSTANT(exports, NN_DONTWAIT);

	// Socket types
	EXPORT_CONSTANT(exports, NN_REQ);
	EXPORT_CONSTANT(exports, NN_REP);
	EXPORT_CONSTANT(exports, NN_PAIR);
	EXPORT_CONSTANT(exports, NN_PUSH);
	EXPORT_CONSTANT(exports, NN_PULL);
	EXPORT_CONSTANT(exports, NN_PUB);
	EXPORT_CONSTANT(exports, NN_SUB);
	EXPORT_CONSTANT(exports, NN_BUS);
	EXPORT_CONSTANT(exports, NN_SURVEYOR);
	EXPORT_CONSTANT(exports, NN_RESPONDENT);

	// Socket type options.
	EXPORT_CONSTANT(exports, NN_REQ_RESEND_IVL);
	EXPORT_CONSTANT(exports, NN_SUB_SUBSCRIBE);
	EXPORT_CONSTANT(exports, NN_SUB_UNSUBSCRIBE);
	EXPORT_CONSTANT(exports, NN_SURVEYOR_DEADLINE);

	// Polling
	EXPORT_CONSTANT(exports, NN_POLLIN);
	EXPORT_CONSTANT(exports, NN_POLLOUT);
}

NODE_MODULE(node_nanomsg, InitAll)
<|endoftext|>


<commit_before>#include <random>
#include <chrono>
#include <algorithm>
#include <cmath>
#include <string>
#include <sstream>
#include <fstream>
#include <chrono>
#include <cstdlib>

#include "util.h"
#include "eval.h"

int main(int argc, const char *const argv[]) {
  constexpr size_t max_iterations = 50;
  constexpr unsigned base_trials = 10000;

  auto num_samples = [=](const double eb_no) {
    return std::min(base_trials * pow(10, eb_no / 2), 10e6);
  };

  const float alpha_start = (argc > 1) ? strtof(argv[1], nullptr) : 0.1f;
  const float alpha_max = (argc > 2) ? strtof(argv[2], nullptr) : 1.0f;
  const float alpha_step = (argc > 3) ? strtof(argv[3], nullptr) : 0.01f;

  const float beta_start = (argc > 4) ? strtof(argv[4], nullptr) : 0.1f;
  const float beta_max = (argc > 5) ? strtof(argv[5], nullptr) : 1.0f;
  const float beta_step = (argc > 6) ? strtof(argv[6], nullptr) : 0.01f;

  const float eb_no = (argc > 7) ? strtof(argv[7], nullptr) : 0.0f;

  std::cout << "Calculating for eb_no: " << eb_no << std::endl;
  std::cout << "alpha: " << alpha_start << " to " << alpha_max << " in "
            << alpha_step << " steps" << std::endl;
  std::cout << "beta:  " << beta_start << " to " << beta_max << " in "
            << beta_step << " steps" << std::endl;

  std::mt19937_64 generator;
  const auto seed =
      std::chrono::high_resolution_clock::now().time_since_epoch().count();

  bch code(5, 0x25, 7);
  // bch code(6, 0x45, 7);

  auto parameters = code.parameters();
  auto simulator = std::bind(evaluate, generator, std::placeholders::_1,
                             std::placeholders::_2, std::placeholders::_3,
                             std::get<0>(parameters), std::get<1>(parameters),
                             std::get<2>(parameters));

  std::ostringstream os;
  os << "logs/ebno_" << eb_no;
  std::string fname = os.str();
  if (file_exists(fname)) {
    std::cout << "File " << fname << " exists. Aborting.";
    return -1;
  }

  std::ofstream file(fname, std::ofstream::out);
  std::cout << "Writing to file " << fname << std::endl;
  file << "#eb_no " << eb_no << std::endl;
  file << "#alpha: " << alpha_start << " " << alpha_max << " " << alpha_step
       << std::endl;
  file << "#beta : " << beta_start << " " << beta_max << " " << beta_step
       << std::endl;

  file << std::scientific;

  for (float alpha = alpha_start; alpha < alpha_max; alpha += alpha_step) {
    for (float beta = beta_start; beta < beta_max; beta += beta_step) {
      generator.seed(seed);

      const size_t N = num_samples(eb_no);

      std::cout << "alpha = " << alpha << " beta = " << beta << " N = " << N;
      std::cout.flush();

      auto start = std::chrono::high_resolution_clock::now();
      auto f =
          std::bind(nms_2d<max_iterations, float, float>, std::ref(code.H()),
                    std::placeholders::_1, alpha, beta);
      file << simulator(f, N, eb_no) << " ";

      auto end = std::chrono::high_resolution_clock::now();
      auto seconds =
          std::chrono::duration_cast<std::chrono::seconds>(end - start).count();

      std::cout << seconds << " s" << std::endl;
    }

    file << std::endl;
  }
}
<commit_msg>Write only BER in optimize_2d<commit_after>#include <random>
#include <chrono>
#include <algorithm>
#include <cmath>
#include <string>
#include <sstream>
#include <fstream>
#include <chrono>
#include <cstdlib>

#include "util.h"
#include "eval.h"

int main(int argc, const char *const argv[]) {
  constexpr size_t max_iterations = 50;
  constexpr unsigned base_trials = 10000;

  auto num_samples = [=](const double eb_no) {
    return std::min(base_trials * pow(10, eb_no / 2), 10e6);
  };

  const float alpha_start = (argc > 1) ? strtof(argv[1], nullptr) : 0.1f;
  const float alpha_max = (argc > 2) ? strtof(argv[2], nullptr) : 1.0f;
  const float alpha_step = (argc > 3) ? strtof(argv[3], nullptr) : 0.01f;

  const float beta_start = (argc > 4) ? strtof(argv[4], nullptr) : 0.1f;
  const float beta_max = (argc > 5) ? strtof(argv[5], nullptr) : 1.0f;
  const float beta_step = (argc > 6) ? strtof(argv[6], nullptr) : 0.01f;

  const float eb_no = (argc > 7) ? strtof(argv[7], nullptr) : 0.0f;

  std::cout << "Calculating for eb_no: " << eb_no << std::endl;
  std::cout << "alpha: " << alpha_start << " to " << alpha_max << " in "
            << alpha_step << " steps" << std::endl;
  std::cout << "beta:  " << beta_start << " to " << beta_max << " in "
            << beta_step << " steps" << std::endl;

  std::mt19937_64 generator;
  const auto seed =
      std::chrono::high_resolution_clock::now().time_since_epoch().count();

  bch code(5, 0x25, 7);
  // bch code(6, 0x45, 7);

  auto parameters = code.parameters();
  auto simulator = std::bind(evaluate, generator, std::placeholders::_1,
                             std::placeholders::_2, std::placeholders::_3,
                             std::get<0>(parameters), std::get<1>(parameters),
                             std::get<2>(parameters));

  std::ostringstream os;
  os << "logs/ebno_" << eb_no;
  std::string fname = os.str();
  if (file_exists(fname)) {
    std::cout << "File " << fname << " exists. Aborting.";
    return -1;
  }

  std::ofstream file(fname, std::ofstream::out);
  std::cout << "Writing to file " << fname << std::endl;
  file << "#eb_no " << eb_no << std::endl;
  file << "#alpha: " << alpha_start << " " << alpha_max << " " << alpha_step
       << std::endl;
  file << "#beta : " << beta_start << " " << beta_max << " " << beta_step
       << std::endl;

  file << std::scientific;

  for (float alpha = alpha_start; alpha < alpha_max; alpha += alpha_step) {
    for (float beta = beta_start; beta < beta_max; beta += beta_step) {
      generator.seed(seed);

      const size_t N = num_samples(eb_no);

      std::cout << "alpha = " << alpha << " beta = " << beta << " N = " << N;
      std::cout.flush();

      auto start = std::chrono::high_resolution_clock::now();
      auto f =
          std::bind(nms_2d<max_iterations, float, float>, std::ref(code.H()),
                    std::placeholders::_1, alpha, beta);
      file << simulator(f, N, eb_no).ber() << " ";

      auto end = std::chrono::high_resolution_clock::now();
      auto seconds =
          std::chrono::duration_cast<std::chrono::seconds>(end - start).count();

      std::cout << seconds << " s" << std::endl;
    }

    file << std::endl;
  }
}
<|endoftext|>


<commit_before>#include <random>
#include <algorithm>
#include <string>
#include <fstream>
#include <sstream>
#include <chrono>

#include "eval.h"
#include "util.h"

int main(int argc, const char *const argv[]) {
  constexpr size_t max_iterations = 50;
  constexpr float eb_no_max = 10;
  constexpr float eb_no_step = 0.1f;
  constexpr unsigned base_trials = 10000;

  auto seed =
      std::chrono::high_resolution_clock::now().time_since_epoch().count();

  bch code(5, 0x25, 7);
  std::mt19937_64 generator;

  auto parameters = code.parameters();
  auto simulator = std::bind(evaluate, generator, std::placeholders::_1,
                             std::placeholders::_2, std::placeholders::_3,
                             std::get<0>(parameters), std::get<1>(parameters),
                             std::get<2>(parameters));

  auto algorithms = get_algorithms<max_iterations>(code);

  auto num_samples = [=](const double ber) {
    return std::min(1000 * 1/ber, 10e6);
    //return std::min(base_trials * pow(10, eb_no / 2), 10e6);
  };

  auto run_algorithm = [&](const auto &algorithm) {
    const auto &name = algorithm.first;
    const auto &decoder = algorithm.second;

    if (file_exists(name)) {
      std::cout << "File " << name << " already exists." << std::endl;
      return;
    }

    std::ofstream file(name.c_str(), std::ofstream::out);
    file << "eb_no "
         << "reconstruction_failures "
         << "reconstruction_errors "
         << "wer "
         << "fk_rate "
         << "ber" << std::endl;

    generator.seed(seed);

    double ber = 1;
    for (double eb_no = 0; eb_no < eb_no_max; eb_no += eb_no_step) {
      auto samples = num_samples(ber);
      std::cout << "Calculating for E_b/N_0 = " << eb_no << " with " << samples
                << " … ";
      std::cout.flush();
      auto start = std::chrono::high_resolution_clock::now();

      auto result = simulator(decoder, samples, eb_no);

      auto end = std::chrono::high_resolution_clock::now();
      auto seconds =
          std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
      std::cout << seconds << " s" << std::endl;

      ber = result.ber();

      file << std::setprecision(1) << eb_no << " ";
      file << result;
      file << std::endl;
    }
  };

  if (argc < 2) {
    std::cout << "Running all algorithms" << std::endl;
    for (const auto &algorithm : algorithms) {
      run_algorithm(algorithm);
    }
  } else {
    for (int arg = 1; arg < argc; arg++) {
      unsigned long index = strtoul(argv[arg], nullptr, 0);
      if (index < algorithms.size()) {
        std::cout << "Running algorithm " << algorithms.at(index).first
                  << std::endl;
        run_algorithm(algorithms.at(index));
      } else {
        unsigned index = 0;
        std::cout << "Index " << index
                  << " is out of range. Choose from:" << std::endl;
        for (const auto &algorithm : algorithms)
          std::cout << "[" << index++ << "] " << algorithm.first << std::endl;
      }
    }
  }
}
<commit_msg>Add getopt_long_only cmd line parsing<commit_after>#include <random>
#include <algorithm>
#include <string>
#include <fstream>
#include <sstream>
#include <chrono>

#define _GNU_SOURCE
#include <getopt.h>

#include "eval.h"
#include "util.h"

void usage() {
  int index = 0;
  bch code(5, 0x25, 7);
  std::cout << "--algorithm <num>"
            << "  "
            << "Choose algorithm:" << std::endl;
  for (const auto &algorithm : get_algorithms<0>(code))
    std::cout << "  [" << index++ << "] " << algorithm.first << std::endl;
  std::cout << "--k <num>        "
            << "  "
            << "Choose code length n = 2^k - 1." << std::endl;
  std::cout << "--dmin <num      "
            << "  "
            << "Choose dmin of the code." << std::endl;
  std::cout << "--seed <num>     "
            << "  "
            << "Set seed of the random number generator." << std::endl;

  exit(-1);
}

int main(int argc, char *const argv[]) {
  constexpr size_t max_iterations = 50;
  constexpr float eb_no_max = 10;
  constexpr float eb_no_step = 0.1f;
  constexpr unsigned base_trials = 10000;

  std::vector<int> indices;
  int k;
  int dmin;
  typename std::mt19937_64::result_type seed = 0;
  // std::chrono::high_resolution_clock::now().time_since_epoch().count();

  while (1) {
    static struct option options[] = {
      { "algorithm", required_argument, nullptr, 'a' },
      { "k", required_argument, nullptr, 'k' },
      { "dmin", required_argument, nullptr, 'd' },
      { "seed", required_argument, nullptr, 's' },
      { nullptr, 0, nullptr, 0 },
    };

    int option_index = 0;
    int c = getopt_long_only(argc, argv, "", options, &option_index);
    if (c == -1)
      break;

    switch (c) {
    case 'a':
      indices.push_back(strtoul(optarg, nullptr, 0));
      break;
    case 'k':
      k = strtoul(optarg, nullptr, 0);
      break;
    case 'd':
      dmin = strtoul(optarg, nullptr, 0);
      break;
    case 's':
      seed = strtoull(optarg, nullptr, 0);
      break;
    default:
      std::cerr << "Unkown argument: " << c << " " << std::endl;
      usage();
    }
  }

  bool fail = false;

  if (indices.size() == 0) {
    std::cerr << "Algorithm not set." << std::endl;
    fail = true;
  }

  if (!k) {
    std::cerr << "k not set." << std::endl;
    fail = true;
  }

  if (!dmin) {
    std::cerr << "dmin not set." << std::endl;
    fail = true;
  }

  if (fail)
    usage();

  bch code(k, primitive_polynomial(k), dmin);
  std::mt19937_64 generator;

  auto parameters = code.parameters();
  auto simulator = std::bind(evaluate, generator, std::placeholders::_1,
                             std::placeholders::_2, std::placeholders::_3,
                             std::get<0>(parameters), std::get<1>(parameters),
                             std::get<2>(parameters));

  auto algorithms = get_algorithms<max_iterations>(code);

  auto num_samples = [=](const double ber) {
    return std::min(1000 * 1/ber, 10e6);
    //return std::min(base_trials * pow(10, eb_no / 2), 10e6);
  };

  auto run_algorithm = [&](const auto &algorithm) {
    const auto &name = algorithm.first;
    const auto &decoder = algorithm.second;

    if (file_exists(name)) {
      std::cout << "File " << name << " already exists." << std::endl;
      return;
    }

    std::ofstream file(name.c_str(), std::ofstream::out);
    file << "eb_no "
         << "reconstruction_failures "
         << "reconstruction_errors "
         << "wer "
         << "fk_rate "
         << "ber" << std::endl;

    generator.seed(seed);

    double ber = 1;
    for (double eb_no = 0; eb_no < eb_no_max; eb_no += eb_no_step) {
      auto samples = num_samples(ber);
      std::cout << "Calculating for E_b/N_0 = " << eb_no << " with " << samples
                << " … ";
      std::cout.flush();
      auto start = std::chrono::high_resolution_clock::now();

      auto result = simulator(decoder, samples, eb_no);

      auto end = std::chrono::high_resolution_clock::now();
      auto seconds =
          std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
      std::cout << seconds << " s" << std::endl;

      ber = result.ber();

      file << std::setprecision(1) << eb_no << " ";
      file << result;
      file << std::endl;
    }
  };

  for (const auto &index : indices) {
    if (index < algorithms.size()) {
      std::cout << "Running algorithm " << algorithms.at(index).first
                << std::endl;
      run_algorithm(algorithms.at(index));
    } else {
      std::cout << "Index " << index
                << " is out of range. Choose from:" << std::endl;
      unsigned i = 0;
      for (const auto &algorithm : algorithms)
        std::cout << "[" << i++ << "] " << algorithm.first << std::endl;
    }
  }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cmath>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <vector>
#include <algorithm>

typedef unsigned char uchar;

// The value of a gaussian point spread function at a given distance
float psf_gaussian(float distance) {
    // Amplitude and std
    return 1.0 * exp(-(distance*distance) / 1.0);
}

// Draw a star at given screen coordinates
// Uses a gaussian point spread function
void draw_star(cv::Mat image, float star_x, float star_y) {

    // Max size of the spread to one side in pixels
    // e.g. 1 means the square of pixels modified will be 3x3
    const int spread_size = 5;

    // Closest discrete pixel to the star location
    const int center_x = round(star_x);
    const int center_y = round(star_y);

    // For each pixel around the star
    for (int x = center_x - spread_size; x <= center_x + spread_size; x++) {
        for (int y = center_y - spread_size; y <= center_y + spread_size; y++) {

            // Get the point spread function value at that distance from the star
            float distance = sqrt(pow(star_x - x, 2) + pow(star_y - y, 2));
            image.at<float>(y,x) += psf_gaussian(distance);
        }
    }
}

int main() {
    cv::namedWindow("Planetarium", cv::WINDOW_AUTOSIZE);

    cv::Mat image(600, 800, CV_32FC1);

    draw_star(image, 100, 100.0);
    draw_star(image, 110, 100.1);
    draw_star(image, 120, 100.2);
    draw_star(image, 130, 100.3);
    draw_star(image, 140, 100.4);
    draw_star(image, 150, 100.4);
    draw_star(image, 160, 100.6);
    draw_star(image, 170, 100.7);
    draw_star(image, 180, 100.8);
    draw_star(image, 190, 100.9);
    draw_star(image, 200, 101.0);

    // Threshold to 1.0
    std::cout << image.at<float>(100, 100) << std::endl;
    cv::threshold(image, image, 1.0, 0.0, cv::THRESH_TRUNC);
    std::cout << image.at<float>(100, 100) << std::endl;

    while(cvWaitKey(5) != 27) {
        cv::imshow("Planetarium", image);
    }

    return 0;
}
<commit_msg>added load_catalog<commit_after>#include <iostream>
#include <fstream>
#include <sstream>
#include <cmath>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <vector>
#include <algorithm>

typedef unsigned char uchar;

// Load Hipparcos catalog
cv::Mat load_catalog(const char* filename) {
    cv::Mat catalog(1, 3, CV_32FC1);
    std::ifstream file(filename);
    std::string line, cell;

    if (!file) {
        std::cerr << "Can't open catalog " << filename << std::endl;
        return catalog;
    }

    // Skip first line
    std::getline(file, line);

    // Extract each line data
    while (std::getline(file, line)) {
        std::stringstream line_str(line);

        // Read fields
        double hip(0.0), mag(0.0), ra(0.0), de(0.0);
        line_str >> hip; line_str.get();
        line_str >> mag; line_str.get();
        line_str >> ra; line_str.get();
        line_str >> de; line_str.get();

        cv::Mat catline = (cv::Mat_<float>(1,3) << mag, ra, de);
        catalog.push_back(catline);
    }
    return catalog;
}

// The value of a gaussian point spread function at a given distance
float psf_gaussian(float distance) {
    // Amplitude and std
    return 1.0 * exp(-(distance*distance) / 1.0);
}

// Draw a star at given screen coordinates
// Uses a gaussian point spread function
void draw_star(cv::Mat image, float star_x, float star_y) {

    // Max size of the spread to one side in pixels
    // e.g. 1 means the square of pixels modified will be 3x3
    const int spread_size = 5;

    // Closest discrete pixel to the star location
    const int center_x = round(star_x);
    const int center_y = round(star_y);

    // For each pixel around the star
    for (int x = center_x - spread_size; x <= center_x + spread_size; x++) {
        for (int y = center_y - spread_size; y <= center_y + spread_size; y++) {

            // Get the point spread function value at that distance from the star
            float distance = sqrt(pow(star_x - x, 2) + pow(star_y - y, 2));
            image.at<float>(y,x) += psf_gaussian(distance);
        }
    }
}

int main() {
    cv::namedWindow("Planetarium", cv::WINDOW_AUTOSIZE);

    cv::Mat image(600, 800, CV_32FC1);

    cv::Mat catalog = load_catalog("../hip5.tsv");

    draw_star(image, 100, 100.0);
    draw_star(image, 110, 100.1);
    draw_star(image, 120, 100.2);
    draw_star(image, 130, 100.3);
    draw_star(image, 140, 100.4);
    draw_star(image, 150, 100.4);
    draw_star(image, 160, 100.6);
    draw_star(image, 170, 100.7);
    draw_star(image, 180, 100.8);
    draw_star(image, 190, 100.9);
    draw_star(image, 200, 101.0);

    // Threshold to 1.0
    cv::threshold(image, image, 1.0, 0.0, cv::THRESH_TRUNC);

    while(cvWaitKey(5) != 27) {
        cv::imshow("Planetarium", image);
    }

    return 0;
}
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2009 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "mmapfileinputstream.h"
#include <config.h>
#include <strigi/strigiconfig.h>
#include <fcntl.h>
#include <cerrno>
#include <cstring>
#include <sys/mman.h>

using namespace Strigi;
using namespace std;

MMapFileInputStream::MMapFileInputStream(const char* filepath) :p(0) {
    int fd = ::open(filepath, O_RDONLY);
    struct stat sb;
    if (fd == -1 || fstat(fd, &sb) == -1) {
        // handle error
        buffer = 0;
        m_error = "Could not read file '";
        m_error += filepath;
        m_error += "': ";
        m_error += strerror(errno);
        m_status = Error;
        close(fd);
        return;
    }
    m_size = sb.st_size;
    if (m_size > 0) {
        buffer = (const char*)mmap(NULL, m_size, PROT_READ, MAP_PRIVATE, fd, 0);
    } else {
        buffer = 0;
    }
    close(fd);
    if (buffer == (const char*)MAP_FAILED) {
        // handle error
        buffer = 0;
        m_error = "Could not read file '";
        m_error += filepath;
        m_error += "': ";
        m_error += strerror(errno);
        m_status = Error;
        return;
    }
}
MMapFileInputStream::~MMapFileInputStream() {
    if (buffer) {
        munmap((void*)buffer, m_size);
    }
}
int32_t
MMapFileInputStream::read(const char*& start, int32_t _min, int32_t _max) {
    if (m_status == Error) return -2;
    if (m_status == Eof) return -1;
    int32_t n = max(_min, _max);
    if (n >= m_size - m_position) {
        m_status = Eof;
        n = m_size - m_position;
    }
    start = buffer + m_position;
    m_position += n;
    return n;
}
int64_t
MMapFileInputStream::skip(int64_t ntoskip) {
    if (ntoskip >= m_size - m_position) {
        ntoskip = m_size - m_position;
        m_status = Eof;
    }
    m_position += ntoskip;
    return ntoskip;
}
int64_t
MMapFileInputStream::reset(int64_t pos) {
    if (m_status == Error) return -2;
    if (pos >= m_size) {
        m_status = Eof;
        m_position = m_size;
    } else if (pos < 0) {
        m_position = 0;
        m_status = Ok;
    } else {
        m_position = pos;
        m_status = Ok;
    }
    return m_position;
}
<commit_msg>Compile and link on Mac<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2009 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "mmapfileinputstream.h"
#include <config.h>
#include <strigi/strigiconfig.h>
#include <fcntl.h>
#include <cerrno>
#include <cstring>
#include <sys/mman.h>
#include <sys/stat.h>

using namespace Strigi;
using namespace std;

MMapFileInputStream::MMapFileInputStream(const char* filepath) :p(0) {
    int fd = ::open(filepath, O_RDONLY);
    struct stat sb;
    if (fd == -1 || fstat(fd, &sb) == -1) {
        // handle error
        buffer = 0;
        m_error = "Could not read file '";
        m_error += filepath;
        m_error += "': ";
        m_error += strerror(errno);
        m_status = Error;
        close(fd);
        return;
    }
    m_size = sb.st_size;
    if (m_size > 0) {
        buffer = (const char*)mmap(NULL, m_size, PROT_READ, MAP_PRIVATE, fd, 0);
    } else {
        buffer = 0;
    }
    close(fd);
    if (buffer == (const char*)MAP_FAILED) {
        // handle error
        buffer = 0;
        m_error = "Could not read file '";
        m_error += filepath;
        m_error += "': ";
        m_error += strerror(errno);
        m_status = Error;
        return;
    }
}
MMapFileInputStream::~MMapFileInputStream() {
    if (buffer) {
        munmap((void*)buffer, m_size);
    }
}
int32_t
MMapFileInputStream::read(const char*& start, int32_t _min, int32_t _max) {
    if (m_status == Error) return -2;
    if (m_status == Eof) return -1;
    int32_t n = max(_min, _max);
    if (n >= m_size - m_position) {
        m_status = Eof;
        n = m_size - m_position;
    }
    start = buffer + m_position;
    m_position += n;
    return n;
}
int64_t
MMapFileInputStream::skip(int64_t ntoskip) {
    if (ntoskip >= m_size - m_position) {
        ntoskip = m_size - m_position;
        m_status = Eof;
    }
    m_position += ntoskip;
    return ntoskip;
}
int64_t
MMapFileInputStream::reset(int64_t pos) {
    if (m_status == Error) return -2;
    if (pos >= m_size) {
        m_status = Eof;
        m_position = m_size;
    } else if (pos < 0) {
        m_position = 0;
        m_status = Ok;
    } else {
        m_position = pos;
        m_status = Ok;
    }
    return m_position;
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -fexceptions -fcxx-exceptions -fnew-ms-eh -emit-llvm -o - -std=c++11 | FileCheck %s

int f(int);

void test_catch() {
  try {
    f(1);
  } catch (int) {
    f(2);
  } catch (double) {
    f(3);
  }
}

// CHECK-LABEL: define void @"\01?test_catch@@YAXXZ"(
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 1)
// CHECK:         to label %[[NORMAL:.*]] unwind label %[[CATCH_INT:.*]]

// CHECK: [[CATCH_INT]]
// CHECK:   %[[CATCHPAD_INT:.*]] = catchpad [{{.*}} @llvm.eh.handlertype.H.0, i8* null]
// CHECK:         to label %[[CATCH_INT_HANDLER:.*]] unwind label %[[CATCH_DOUBLE:.*]]

// CHECK: [[CATCH_INT_HANDLER]]
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 2)
// CHECK:           to label %[[CATCH_INT_DONE:.*]] unwind label %[[CATCHENDPAD:.*]]

// CHECK: [[CATCH_INT_DONE]]
// CHECK:   catchret %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]]

// CHECK: [[LEAVE_INT_CATCH]]
// CHECK:   br label %[[LEAVE_FUNC:.*]]

// CHECK: [[LEAVE_FUNC]]
// CHECK:   ret void

// CHECK: [[CATCH_DOUBLE]]
// CHECK:   %[[CATCHPAD_DOUBLE:.*]] = catchpad [{{.*}} @llvm.eh.handlertype.N.0, i8* null]
// CHECK:           to label %[[CATCH_DOUBLE_HANDLER:.*]] unwind label %[[CATCHENDPAD]]

// CHECK: [[CATCH_DOUBLE_HANDLER]]
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 3)
// CHECK:           to label %[[CATCH_DOUBLE_DONE:.*]] unwind label %[[CATCHENDPAD]]

// CHECK: [[CATCH_DOUBLE_DONE]]
// CHECK:   catchret %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]]

// CHECK: [[LEAVE_DOUBLE_CATCH]]
// CHECK:   br label %[[LEAVE_FUNC]]

// CHECK: [[CATCHENDPAD]]
// CHECK:   catchendpad unwind to caller

// CHECK: [[NORMAL]]
// CHECK:   br label %[[LEAVE_FUNC]]

struct Cleanup {
  ~Cleanup() { f(-1); }
};

void test_cleanup() {
  Cleanup C;
  f(1);
}

// CHECK-LABEL: define {{.*}} @"\01?test_cleanup@@YAXXZ"(
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 1)
// CHECK:           to label %[[LEAVE_FUNC:.*]] unwind label %[[CLEANUP:.*]]

// CHECK: [[LEAVE_FUNC]]
// CHECK:   call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"(
// CHECK:   ret void

// CHECK: [[CLEANUP]]
// CHECK:   %[[CLEANUPPAD:.*]] = cleanuppad []
// CHECK:   call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"(
// CHECK:   cleanupret %[[CLEANUPPAD]] unwind to caller

// CHECK-LABEL: define {{.*}} void @"\01??1Cleanup@@QAE@XZ"(
// CHECK: entry:
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 -1)
// CHECK:           to label %[[LEAVE_FUNC:.*]] unwind label %[[TERMINATE:.*]]

// CHECK: [[LEAVE_FUNC]]
// CHECK:   ret void

// CHECK: [[TERMINATE]]
// CHECK:   terminatepad [void ()* @"\01?terminate@@YAXXZ"] unwind to caller

<commit_msg>clang/test/CodeGenCXX/exceptions-cxx-new.cpp: Don't assume the label "entry:".<commit_after>// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -fexceptions -fcxx-exceptions -fnew-ms-eh -emit-llvm -o - -std=c++11 | FileCheck %s

int f(int);

void test_catch() {
  try {
    f(1);
  } catch (int) {
    f(2);
  } catch (double) {
    f(3);
  }
}

// CHECK-LABEL: define void @"\01?test_catch@@YAXXZ"(
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 1)
// CHECK:         to label %[[NORMAL:.*]] unwind label %[[CATCH_INT:.*]]

// CHECK: [[CATCH_INT]]
// CHECK:   %[[CATCHPAD_INT:.*]] = catchpad [{{.*}} @llvm.eh.handlertype.H.0, i8* null]
// CHECK:         to label %[[CATCH_INT_HANDLER:.*]] unwind label %[[CATCH_DOUBLE:.*]]

// CHECK: [[CATCH_INT_HANDLER]]
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 2)
// CHECK:           to label %[[CATCH_INT_DONE:.*]] unwind label %[[CATCHENDPAD:.*]]

// CHECK: [[CATCH_INT_DONE]]
// CHECK:   catchret %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]]

// CHECK: [[LEAVE_INT_CATCH]]
// CHECK:   br label %[[LEAVE_FUNC:.*]]

// CHECK: [[LEAVE_FUNC]]
// CHECK:   ret void

// CHECK: [[CATCH_DOUBLE]]
// CHECK:   %[[CATCHPAD_DOUBLE:.*]] = catchpad [{{.*}} @llvm.eh.handlertype.N.0, i8* null]
// CHECK:           to label %[[CATCH_DOUBLE_HANDLER:.*]] unwind label %[[CATCHENDPAD]]

// CHECK: [[CATCH_DOUBLE_HANDLER]]
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 3)
// CHECK:           to label %[[CATCH_DOUBLE_DONE:.*]] unwind label %[[CATCHENDPAD]]

// CHECK: [[CATCH_DOUBLE_DONE]]
// CHECK:   catchret %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]]

// CHECK: [[LEAVE_DOUBLE_CATCH]]
// CHECK:   br label %[[LEAVE_FUNC]]

// CHECK: [[CATCHENDPAD]]
// CHECK:   catchendpad unwind to caller

// CHECK: [[NORMAL]]
// CHECK:   br label %[[LEAVE_FUNC]]

struct Cleanup {
  ~Cleanup() { f(-1); }
};

void test_cleanup() {
  Cleanup C;
  f(1);
}

// CHECK-LABEL: define {{.*}} @"\01?test_cleanup@@YAXXZ"(
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 1)
// CHECK:           to label %[[LEAVE_FUNC:.*]] unwind label %[[CLEANUP:.*]]

// CHECK: [[LEAVE_FUNC]]
// CHECK:   call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"(
// CHECK:   ret void

// CHECK: [[CLEANUP]]
// CHECK:   %[[CLEANUPPAD:.*]] = cleanuppad []
// CHECK:   call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"(
// CHECK:   cleanupret %[[CLEANUPPAD]] unwind to caller

// CHECK-LABEL: define {{.*}} void @"\01??1Cleanup@@QAE@XZ"(
// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 -1)
// CHECK:           to label %[[LEAVE_FUNC:.*]] unwind label %[[TERMINATE:.*]]

// CHECK: [[LEAVE_FUNC]]
// CHECK:   ret void

// CHECK: [[TERMINATE]]
// CHECK:   terminatepad [void ()* @"\01?terminate@@YAXXZ"] unwind to caller

<|endoftext|>


<commit_before>/**
 * \file
 * \brief MutexOperationsTestCase class implementation
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 *
 * \date 2014-11-18
 */

#include "MutexOperationsTestCase.hpp"

#include "mutexTestTryLockWhenLocked.hpp"
#include "waitForNextTick.hpp"

#include "distortos/Mutex.hpp"
#include "distortos/StaticThread.hpp"
#include "distortos/ThisThread.hpp"

#include <cerrno>

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// single duration used in tests
constexpr auto singleDuration = TickClock::duration{1};

/// priority of current test thread and lock-unlock test thread
constexpr uint8_t testThreadPriority {UINT8_MAX - 1};

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Simple thread that locks and unlocks the mutex, with additional correctness checks.
 *
 * First the mutex is locked and this operation is checked - it must happen immediately and it must return 0. Result of
 * that check can be read from sharedRet. In case of failure, thread returns at this point.
 *
 * Then thread waits for semaphoreMutex to be unlocked.
 *
 * Last operation is unlocking of the mutex, which is checked in the same way as locking. Result can be read from
 * sharedRet after this thread terminates.
 *
 * \param [in] mutex is a reference to mutex that will be locked and unlocked, mut be unlocked
 * \param [out] sharedRet is a reference to variable used to return result of operations
 * \param [in] semaphoreMutex is a mutex used as semaphore, must be locked
 */

void lockUnlockThread(Mutex& mutex, bool& sharedRet, Mutex& semaphoreMutex)
{
	{
		// simple lock - must succeed immediately
		const auto start = TickClock::now();
		const auto ret = mutex.lock();
		sharedRet = ret == 0 && start == TickClock::now();
	}

	if (sharedRet == false)
		return;

	semaphoreMutex.lock();
	semaphoreMutex.unlock();

	{
		// simple unlock - must succeed immediately
		const auto start = TickClock::now();
		const auto ret = mutex.unlock();
		sharedRet = ret == 0 && start == TickClock::now();
	}
}

/**
 * \brief Tests Mutex::unlock() - it must succeed immediately
 *
 * \param [in] mutex is a reference to mutex that will be unlocked
 *
 * \return true if test succeeded, false otherwise
 */

bool testUnlock(Mutex& mutex)
{
	waitForNextTick();
	const auto start = TickClock::now();
	const auto ret = mutex.unlock();
	if (ret != 0 || start != TickClock::now())
		return false;

	return true;
}

/**
 * \brief Phase 1 of test case.
 *
 * Tests whether all tryLock*() functions properly return some error when dealing with locked mutex.
 *
 * \param [in] type is the type of mutex
 * \param [in] protocol is the mutex protocol
 * \param [in] priorityCeiling is the priority ceiling of mutex, ignored when protocol != Protocol::PriorityProtect
 *
 * \return true if test succeeded, false otherwise
 */

bool phase1(const Mutex::Type type, const Mutex::Protocol protocol, const uint8_t priorityCeiling)
{
	constexpr size_t testThreadStackSize {256};

	Mutex mutex {type, protocol, priorityCeiling};
	bool sharedRet {};
	Mutex semaphoreMutex;
	semaphoreMutex.lock();

	auto lockUnlockThreadObject = makeStaticThread<testThreadStackSize>(testThreadPriority, lockUnlockThread,
			std::ref(mutex), std::ref(sharedRet), std::ref(semaphoreMutex));

	waitForNextTick();
	lockUnlockThreadObject.start();
	ThisThread::yield();
	if (sharedRet == false)
	{
		lockUnlockThreadObject.join();
		return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		// mutex is locked, so tryLockFor() should time-out at expected time
		waitForNextTick();
		const auto start = TickClock::now();
		const auto ret = mutex.tryLockFor(singleDuration);
		const auto realDuration = TickClock::now() - start;
		if (ret != ETIMEDOUT || realDuration != singleDuration + decltype(singleDuration){1})
			return false;
	}

	{
		// mutex is locked, so tryLockUntil() should time-out at exact expected time
		waitForNextTick();
		const auto requestedTimePoint = TickClock::now() + singleDuration;
		const auto ret = mutex.tryLockUntil(requestedTimePoint);
		if (ret != ETIMEDOUT || requestedTimePoint != TickClock::now())
			return false;
	}

	waitForNextTick();
	semaphoreMutex.unlock();
	lockUnlockThreadObject.join();

	return sharedRet;
}

/**
 * \brief Phase 2 of test case.
 *
 * Tests whether all tryLock*() functions properly lock unlocked mutex.
 *
 * \param [in] type is the type of mutex
 * \param [in] protocol is the mutex protocol
 * \param [in] priorityCeiling is the priority ceiling of mutex, ignored when protocol != Protocol::PriorityProtect
 *
 * \return true if test succeeded, false otherwise
 */

bool phase2(const Mutex::Type type, const Mutex::Protocol protocol, const uint8_t priorityCeiling)
{
	Mutex mutex {type, protocol, priorityCeiling};

	{
		// mutex is unlocked, so tryLock() must succeed immediately
		waitForNextTick();
		const auto start = TickClock::now();
		const auto ret = mutex.tryLock();
		if (ret != 0 || start != TickClock::now())
			return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		const auto ret = testUnlock(mutex);
		if (ret != true)
			return ret;
	}

	{
		// mutex is unlocked, so tryLockFor() should succeed immediately
		waitForNextTick();
		const auto start = TickClock::now();
		const auto ret = mutex.tryLockFor(singleDuration);
		if (ret != 0 || start != TickClock::now())
			return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		const auto ret = testUnlock(mutex);
		if (ret != true)
			return ret;
	}

	{
		// mutex is unlocked, so tryLockUntil() should succeed immediately
		waitForNextTick();
		const auto start = TickClock::now();
		const auto ret = mutex.tryLockUntil(start + singleDuration);
		if (ret != 0 || start != TickClock::now())
			return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		const auto ret = testUnlock(mutex);
		if (ret != true)
			return ret;
	}

	return true;
}

/**
 * \brief Runs the test case.
 *
 * \attention this function expects the priority of test thread to be testThreadPriority
 *
 * \return true if the test case succeeded, false otherwise
 */

bool testRunner()
{
	using Parameters = std::tuple<Mutex::Type, Mutex::Protocol, uint8_t>;
	static const Parameters parametersArray[]
	{
			Parameters{Mutex::Type::Normal, Mutex::Protocol::None, {}},
			Parameters{Mutex::Type::Normal, Mutex::Protocol::PriorityProtect, UINT8_MAX},
			Parameters{Mutex::Type::Normal, Mutex::Protocol::PriorityProtect, testThreadPriority},
			Parameters{Mutex::Type::Normal, Mutex::Protocol::PriorityInheritance, {}},
			Parameters{Mutex::Type::ErrorChecking, Mutex::Protocol::None, {}},
			Parameters{Mutex::Type::ErrorChecking, Mutex::Protocol::PriorityProtect, UINT8_MAX},
			Parameters{Mutex::Type::ErrorChecking, Mutex::Protocol::PriorityProtect, testThreadPriority},
			Parameters{Mutex::Type::ErrorChecking, Mutex::Protocol::PriorityInheritance, {}},
			Parameters{Mutex::Type::Recursive, Mutex::Protocol::None, {}},
			Parameters{Mutex::Type::Recursive, Mutex::Protocol::PriorityProtect, UINT8_MAX},
			Parameters{Mutex::Type::Recursive, Mutex::Protocol::PriorityProtect, testThreadPriority},
			Parameters{Mutex::Type::Recursive, Mutex::Protocol::PriorityInheritance, {}},
	};

	for (const auto& parameters : parametersArray)
	{
		const auto ret1 = phase1(std::get<0>(parameters), std::get<1>(parameters), std::get<2>(parameters));
		if (ret1 != true)
			return ret1;

		const auto ret2 = phase2(std::get<0>(parameters), std::get<1>(parameters), std::get<2>(parameters));
		if (ret2 != true)
			return ret2;
	}

	return true;
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

bool MutexOperationsTestCase::run_() const
{
	const auto thisThreadPriority = ThisThread::getPriority();
	ThisThread::setPriority(testThreadPriority);
	const auto ret = testRunner();
	ThisThread::setPriority(thisThreadPriority);
	return ret;
}

}	// namespace test

}	// namespace distortos
<commit_msg>test: add another test phase (with testing of lock transfer) to MutexOperationsTestCase<commit_after>/**
 * \file
 * \brief MutexOperationsTestCase class implementation
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 *
 * \date 2014-11-18
 */

#include "MutexOperationsTestCase.hpp"

#include "mutexTestTryLockWhenLocked.hpp"
#include "waitForNextTick.hpp"

#include "distortos/Mutex.hpp"
#include "distortos/StaticThread.hpp"
#include "distortos/ThisThread.hpp"

#include <cerrno>

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// single duration used in tests
constexpr auto singleDuration = TickClock::duration{1};

/// long duration used in tests
constexpr auto longDuration = singleDuration * 10;

/// priority of current test thread and lock-unlock test thread
constexpr uint8_t testThreadPriority {UINT8_MAX - 1};

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Simple thread that locks and unlocks the mutex, with additional correctness checks.
 *
 * First the mutex is locked and this operation is checked - it must happen immediately and it must return 0. Result of
 * that check can be read from sharedRet. In case of failure, thread returns at this point.
 *
 * Then thread waits for semaphoreMutex to be unlocked.
 *
 * Last operation is unlocking of the mutex, which is checked in the same way as locking. Result can be read from
 * sharedRet after this thread terminates.
 *
 * \param [in] mutex is a reference to mutex that will be locked and unlocked, mut be unlocked
 * \param [out] sharedRet is a reference to variable used to return result of operations
 * \param [in] semaphoreMutex is a mutex used as semaphore, must be locked
 */

void lockUnlockThread(Mutex& mutex, bool& sharedRet, Mutex& semaphoreMutex)
{
	{
		// simple lock - must succeed immediately
		const auto start = TickClock::now();
		const auto ret = mutex.lock();
		sharedRet = ret == 0 && start == TickClock::now();
	}

	if (sharedRet == false)
		return;

	semaphoreMutex.lock();
	semaphoreMutex.unlock();

	{
		// simple unlock - must succeed immediately
		const auto start = TickClock::now();
		const auto ret = mutex.unlock();
		sharedRet = ret == 0 && start == TickClock::now();
	}
}

/**
 * \brief Tests Mutex::unlock() - it must succeed immediately
 *
 * \param [in] mutex is a reference to mutex that will be unlocked
 *
 * \return true if test succeeded, false otherwise
 */

bool testUnlock(Mutex& mutex)
{
	waitForNextTick();
	const auto start = TickClock::now();
	const auto ret = mutex.unlock();
	if (ret != 0 || start != TickClock::now())
		return false;

	return true;
}

/**
 * \brief Phase 1 of test case.
 *
 * Tests whether all tryLock*() functions properly return some error when dealing with locked mutex.
 *
 * \param [in] type is the type of mutex
 * \param [in] protocol is the mutex protocol
 * \param [in] priorityCeiling is the priority ceiling of mutex, ignored when protocol != Protocol::PriorityProtect
 *
 * \return true if test succeeded, false otherwise
 */

bool phase1(const Mutex::Type type, const Mutex::Protocol protocol, const uint8_t priorityCeiling)
{
	constexpr size_t testThreadStackSize {256};

	Mutex mutex {type, protocol, priorityCeiling};
	bool sharedRet {};
	Mutex semaphoreMutex;
	semaphoreMutex.lock();

	auto lockUnlockThreadObject = makeStaticThread<testThreadStackSize>(testThreadPriority, lockUnlockThread,
			std::ref(mutex), std::ref(sharedRet), std::ref(semaphoreMutex));

	waitForNextTick();
	lockUnlockThreadObject.start();
	ThisThread::yield();
	if (sharedRet == false)
	{
		lockUnlockThreadObject.join();
		return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		// mutex is locked, so tryLockFor() should time-out at expected time
		waitForNextTick();
		const auto start = TickClock::now();
		const auto ret = mutex.tryLockFor(singleDuration);
		const auto realDuration = TickClock::now() - start;
		if (ret != ETIMEDOUT || realDuration != singleDuration + decltype(singleDuration){1})
			return false;
	}

	{
		// mutex is locked, so tryLockUntil() should time-out at exact expected time
		waitForNextTick();
		const auto requestedTimePoint = TickClock::now() + singleDuration;
		const auto ret = mutex.tryLockUntil(requestedTimePoint);
		if (ret != ETIMEDOUT || requestedTimePoint != TickClock::now())
			return false;
	}

	waitForNextTick();
	semaphoreMutex.unlock();
	lockUnlockThreadObject.join();

	return sharedRet;
}

/**
 * \brief Phase 2 of test case.
 *
 * Tests whether all tryLock*() functions properly lock unlocked mutex.
 *
 * \param [in] type is the type of mutex
 * \param [in] protocol is the mutex protocol
 * \param [in] priorityCeiling is the priority ceiling of mutex, ignored when protocol != Protocol::PriorityProtect
 *
 * \return true if test succeeded, false otherwise
 */

bool phase2(const Mutex::Type type, const Mutex::Protocol protocol, const uint8_t priorityCeiling)
{
	Mutex mutex {type, protocol, priorityCeiling};

	{
		// mutex is unlocked, so tryLock() must succeed immediately
		waitForNextTick();
		const auto start = TickClock::now();
		const auto ret = mutex.tryLock();
		if (ret != 0 || start != TickClock::now())
			return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		const auto ret = testUnlock(mutex);
		if (ret != true)
			return ret;
	}

	{
		// mutex is unlocked, so tryLockFor() should succeed immediately
		waitForNextTick();
		const auto start = TickClock::now();
		const auto ret = mutex.tryLockFor(singleDuration);
		if (ret != 0 || start != TickClock::now())
			return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		const auto ret = testUnlock(mutex);
		if (ret != true)
			return ret;
	}

	{
		// mutex is unlocked, so tryLockUntil() should succeed immediately
		waitForNextTick();
		const auto start = TickClock::now();
		const auto ret = mutex.tryLockUntil(start + singleDuration);
		if (ret != 0 || start != TickClock::now())
			return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		const auto ret = testUnlock(mutex);
		if (ret != true)
			return ret;
	}

	return true;
}

/**
 * \brief Phase 3 of test case.
 *
 * Tests typical lock transfer scenario in lock(), tryLockFor() and tryLockUntil() functions. Mutex is locked in another
 * thread and main (current) thread waits for this mutex to become available. Test thread unlocks the mutex at specified
 * time point, main thread is expected to acquire ownership of this mutex in the same moment.
 *
 * \param [in] type is the type of mutex
 * \param [in] protocol is the mutex protocol
 * \param [in] priorityCeiling is the priority ceiling of mutex, ignored when protocol != Protocol::PriorityProtect
 *
 * \return true if test succeeded, false otherwise
 */

bool phase3(const Mutex::Type type, const Mutex::Protocol protocol, const uint8_t priorityCeiling)
{
	constexpr size_t testThreadStackSize {384};

	Mutex mutex {type, protocol, priorityCeiling};

	const auto sleepUntilFunctor = [&mutex](const TickClock::time_point timePoint)
			{
				mutex.lock();
				ThisThread::sleepUntil(timePoint);
				mutex.unlock();
			};

	{
		const auto wakeUpTimePoint = TickClock::now() + longDuration;
		auto thread = makeStaticThread<testThreadStackSize>(testThreadPriority, sleepUntilFunctor, wakeUpTimePoint);

		waitForNextTick();
		thread.start();
		ThisThread::yield();

		// mutex is currently locked, but lock() should succeed at expected time
		const auto ret = mutex.lock();
		const auto wokenUpTimePoint = TickClock::now();
		thread.join();
		if (ret != 0 || wakeUpTimePoint != wokenUpTimePoint)
			return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		const auto ret = testUnlock(mutex);
		if (ret != true)
			return ret;
	}

	{
		const auto wakeUpTimePoint = TickClock::now() + longDuration;
		auto thread = makeStaticThread<testThreadStackSize>(testThreadPriority, sleepUntilFunctor, wakeUpTimePoint);

		waitForNextTick();
		thread.start();
		ThisThread::yield();

		// mutex is currently locked, but tryLockFor() should succeed at expected time
		const auto ret = mutex.tryLockFor(wakeUpTimePoint - TickClock::now() + longDuration);
		const auto wokenUpTimePoint = TickClock::now();
		thread.join();
		if (ret != 0 || wakeUpTimePoint != wokenUpTimePoint)
			return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		const auto ret = testUnlock(mutex);
		if (ret != true)
			return ret;
	}

	{
		const auto wakeUpTimePoint = TickClock::now() + longDuration;
		auto thread = makeStaticThread<testThreadStackSize>(testThreadPriority, sleepUntilFunctor, wakeUpTimePoint);

		waitForNextTick();
		thread.start();
		ThisThread::yield();

		// mutex is locked, but tryLockUntil() should succeed at expected time
		const auto ret = mutex.tryLockUntil(wakeUpTimePoint + longDuration);
		const auto wokenUpTimePoint = TickClock::now();
		thread.join();
		if (ret != 0 || wakeUpTimePoint != wokenUpTimePoint)
			return false;
	}

	{
		const auto ret = mutexTestTryLockWhenLocked(mutex, testThreadPriority);
		if (ret != true)
			return ret;
	}

	{
		const auto ret = testUnlock(mutex);
		if (ret != true)
			return ret;
	}

	return true;
}

/**
 * \brief Runs the test case.
 *
 * \attention this function expects the priority of test thread to be testThreadPriority
 *
 * \return true if the test case succeeded, false otherwise
 */

bool testRunner()
{
	using Parameters = std::tuple<Mutex::Type, Mutex::Protocol, uint8_t>;
	static const Parameters parametersArray[]
	{
			Parameters{Mutex::Type::Normal, Mutex::Protocol::None, {}},
			Parameters{Mutex::Type::Normal, Mutex::Protocol::PriorityProtect, UINT8_MAX},
			Parameters{Mutex::Type::Normal, Mutex::Protocol::PriorityProtect, testThreadPriority},
			Parameters{Mutex::Type::Normal, Mutex::Protocol::PriorityInheritance, {}},
			Parameters{Mutex::Type::ErrorChecking, Mutex::Protocol::None, {}},
			Parameters{Mutex::Type::ErrorChecking, Mutex::Protocol::PriorityProtect, UINT8_MAX},
			Parameters{Mutex::Type::ErrorChecking, Mutex::Protocol::PriorityProtect, testThreadPriority},
			Parameters{Mutex::Type::ErrorChecking, Mutex::Protocol::PriorityInheritance, {}},
			Parameters{Mutex::Type::Recursive, Mutex::Protocol::None, {}},
			Parameters{Mutex::Type::Recursive, Mutex::Protocol::PriorityProtect, UINT8_MAX},
			Parameters{Mutex::Type::Recursive, Mutex::Protocol::PriorityProtect, testThreadPriority},
			Parameters{Mutex::Type::Recursive, Mutex::Protocol::PriorityInheritance, {}},
	};

	for (const auto& parameters : parametersArray)
	{
		const auto ret1 = phase1(std::get<0>(parameters), std::get<1>(parameters), std::get<2>(parameters));
		if (ret1 != true)
			return ret1;

		const auto ret2 = phase2(std::get<0>(parameters), std::get<1>(parameters), std::get<2>(parameters));
		if (ret2 != true)
			return ret2;

		const auto ret3 = phase3(std::get<0>(parameters), std::get<1>(parameters), std::get<2>(parameters));
		if (ret3 != true)
			return ret3;
	}

	return true;
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

bool MutexOperationsTestCase::run_() const
{
	const auto thisThreadPriority = ThisThread::getPriority();
	ThisThread::setPriority(testThreadPriority);
	const auto ret = testRunner();
	ThisThread::setPriority(thisThreadPriority);
	return ret;
}

}	// namespace test

}	// namespace distortos
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE HitFinderToolsTests

#include <boost/test/unit_test.hpp>

#include "HitFinderTools.h"

BOOST_AUTO_TEST_SUITE (HitFinderToolsSuite)

BOOST_AUTO_TEST_CASE (HitFinder)
{

    // All times are in picoseconds

    JPetBarrelSlot BS(7, true, "string", 1.0, 1);
    JPetScin Scintillator(1);

    JPetPhysSignal sig1;
    sig1.setTime(12452);
    sig1.setTimeWindowIndex(1);

    JPetPM PM1;
    PM1.setSide(JPetPM::SideA);
    PM1.setBarrelSlot(BS);
    PM1.setScin(Scintillator);
    sig1.setPM(PM1);

    JPetPhysSignal sig2;
    sig2.setTime(3146613);
    sig2.setTimeWindowIndex(1);

    JPetPM PM2;
    PM2.setSide(JPetPM::SideA);
    PM2.setBarrelSlot(BS);
    PM2.setScin(Scintillator);
    sig2.setPM(PM2);

    JPetPhysSignal sig3;
    sig3.setTime(87361353);
    sig3.setTimeWindowIndex(1);

    JPetPM PM3;
    PM3.setSide(JPetPM::SideA);
    PM3.setBarrelSlot(BS);
    PM3.setScin(Scintillator);
    sig3.setPM(PM3);

    JPetPhysSignal sig4;
    sig4.setTime(46785);
    sig4.setTimeWindowIndex(1);

    JPetPM PM4;
    PM4.setSide(JPetPM::SideB);
    PM4.setBarrelSlot(BS);
    PM4.setScin(Scintillator);
    sig4.setPM(PM4);

    JPetPhysSignal sig5;
    sig5.setTime(3132169);
    sig5.setTimeWindowIndex(1);

    JPetPM PM5;
    PM5.setSide(JPetPM::SideB);
    PM5.setBarrelSlot(BS);
    PM5.setScin(Scintillator);
    sig5.setPM(PM5);

    JPetPhysSignal sig6;
    sig6.setTime(87338621);
    sig6.setTimeWindowIndex(1);

    JPetPM PM6;
    PM6.setSide(JPetPM::SideB);
    PM6.setBarrelSlot(BS);
    PM6.setScin(Scintillator);
    sig6.setPM(PM6);

    HitFinderTools HitFinder;

    std::vector<JPetPhysSignal> sideA = {sig1, sig2, sig3};
    std::vector<JPetPhysSignal> sideB = {sig4, sig5, sig6};

    HitFinderTools::SignalsContainer container;

    container.emplace(7, std::make_pair(sideA, sideB));

    double expectedHitsTimeWindow1ns = 0;
    double expectedHitsTimeWindow50ns = 3;
    double expectedHitsTimeWindow5000ns = 5;
    double expectedHitsTimeWindow1ms = 9;

    double kTimeWindow1ns = pow(10,3);
    double kTimeWindow50ns = 50*pow(10,3);
    double kTimeWindow5000ns = 5000*pow(10,3);
    double kTimeWindow1ms = pow(10,9);

    BOOST_REQUIRE_EQUAL(HitFinder.createHits(container, kTimeWindow1ns).size(), expectedHitsTimeWindow1ns);
    BOOST_REQUIRE_EQUAL(HitFinder.createHits(container, kTimeWindow50ns).size(), expectedHitsTimeWindow50ns);
    BOOST_REQUIRE_EQUAL(HitFinder.createHits(container, kTimeWindow5000ns).size(), expectedHitsTimeWindow5000ns);
    BOOST_REQUIRE_EQUAL(HitFinder.createHits(container, kTimeWindow1ms).size(), expectedHitsTimeWindow1ms);

}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Remove outdated HitFinderToolsTest<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include "franka/robot_state.h"

#include <algorithm>
#include <cstring>
#include <iterator>

namespace franka {

namespace {

template <class T, size_t N>
std::ostream& operator<<(std::ostream& ostream, const std::array<T, N>& array) {
  ostream << "[";
  std::copy(array.cbegin(), array.cend() - 1, std::ostream_iterator<T>(ostream, ","));
  std::copy(array.cend() - 1, array.cend(), std::ostream_iterator<T>(ostream));
  ostream << "]";
  return ostream;
}

std::ostream& operator<<(std::ostream& ostream, const RobotMode robot_mode) {
  ostream << "\"";
  switch (robot_mode) {
    case (RobotMode::kUserStopped):
      ostream << "User stopped";
      break;
    case (RobotMode::kIdle):
      ostream << "Idle";
      break;
    case (RobotMode::kMove):
      ostream << "Move";
      break;
    case (RobotMode::kGuiding):
      ostream << "Guiding";
      break;
    case (RobotMode::kReflex):
      ostream << "Reflex";
      break;
    case (RobotMode::kAutomaticErrorRecovery):
      ostream << "Automatic error recovery";
      break;
    case (RobotMode::kOther):
      ostream << "Other";
      break;
  }
  ostream << "\"";
  return ostream;
}

}  // anonymous namespace

std::ostream& operator<<(std::ostream& ostream, const franka::RobotState& robot_state) {
  ostream << "{\"O_T_EE\": " << robot_state.O_T_EE << ", \"O_T_EE_d\": " << robot_state.O_T_EE_d
          << ", \"F_T_EE\": " << robot_state.F_T_EE << ", \"EE_T_K\": " << robot_state.EE_T_K
          << ", \"m_ee\": " << robot_state.m_ee << ", \"F_x_Cee\": " << robot_state.F_x_Cee
          << ", \"I_ee\": " << robot_state.I_ee << ", \"m_load\": " << robot_state.m_load
          << ", \"F_x_Cload\": " << robot_state.F_x_Cload << ", \"I_load\": " << robot_state.I_load
          << ", \"m_total\": " << robot_state.m_total
          << ", \"F_x_Ctotal\": " << robot_state.F_x_Ctotal
          << ", \"I_total\": " << robot_state.I_total << ", \"elbow\": " << robot_state.elbow
          << ", \"elbow_d\": " << robot_state.elbow_d
          << ", \"elbow_c\": " << robot_state.elbow_c << ", \"delbow_c\": " << robot_state.delbow_c
          << ", \"ddelbow_c\": " << robot_state.ddelbow_c
          << ", \"tau_J\": " << robot_state.tau_J
          << ", \"tau_J_d\": " << robot_state.tau_J_d << ", \"dtau_J\": " << robot_state.dtau_J
          << ", \"q\": " << robot_state.q << ", \"dq\": " << robot_state.dq
          << ", \"q_d\": " << robot_state.q_d << ", \"dq_d\": " << robot_state.dq_d
          << ", \"ddq_d\": " << robot_state.ddq_d
          << ", \"joint_contact\": " << robot_state.joint_contact
          << ", \"cartesian_contact\": " << robot_state.cartesian_contact
          << ", \"joint_collision\": " << robot_state.joint_collision
          << ", \"cartesian_collision\": " << robot_state.cartesian_collision
          << ", \"tau_ext_hat_filtered\": " << robot_state.tau_ext_hat_filtered
          << ", \"O_F_ext_hat_K\": " << robot_state.O_F_ext_hat_K
          << ", \"K_F_ext_hat_K\": " << robot_state.K_F_ext_hat_K
          << ", \"O_dP_EE_d\": " << robot_state.O_dP_EE_d
          << ", \"O_T_EE_c\": " << robot_state.O_T_EE_c << ", \"O_dP_EE_c\": " << robot_state.O_dP_EE_c
          << ", \"O_ddP_EE_c\": " << robot_state.O_ddP_EE_c
          << ", \"theta\": " << robot_state.theta
          << ", \"dtheta\": " << robot_state.dtheta
          << ", \"current_errors\": " << robot_state.current_errors
          << ", \"last_motion_errors\": " << robot_state.last_motion_errors
          << ", \"control_command_success_rate\": " << robot_state.control_command_success_rate
          << ", \"robot_mode\": " << robot_state.robot_mode
          << ", \"time\": " << robot_state.time.toMSec() << "}";
  return ostream;
}

}  // namespace franka
<commit_msg>Fix formatting<commit_after>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include "franka/robot_state.h"

#include <algorithm>
#include <cstring>
#include <iterator>

namespace franka {

namespace {

template <class T, size_t N>
std::ostream& operator<<(std::ostream& ostream, const std::array<T, N>& array) {
  ostream << "[";
  std::copy(array.cbegin(), array.cend() - 1, std::ostream_iterator<T>(ostream, ","));
  std::copy(array.cend() - 1, array.cend(), std::ostream_iterator<T>(ostream));
  ostream << "]";
  return ostream;
}

std::ostream& operator<<(std::ostream& ostream, const RobotMode robot_mode) {
  ostream << "\"";
  switch (robot_mode) {
    case (RobotMode::kUserStopped):
      ostream << "User stopped";
      break;
    case (RobotMode::kIdle):
      ostream << "Idle";
      break;
    case (RobotMode::kMove):
      ostream << "Move";
      break;
    case (RobotMode::kGuiding):
      ostream << "Guiding";
      break;
    case (RobotMode::kReflex):
      ostream << "Reflex";
      break;
    case (RobotMode::kAutomaticErrorRecovery):
      ostream << "Automatic error recovery";
      break;
    case (RobotMode::kOther):
      ostream << "Other";
      break;
  }
  ostream << "\"";
  return ostream;
}

}  // anonymous namespace

std::ostream& operator<<(std::ostream& ostream, const franka::RobotState& robot_state) {
  ostream << "{\"O_T_EE\": " << robot_state.O_T_EE << ", \"O_T_EE_d\": " << robot_state.O_T_EE_d
          << ", \"F_T_EE\": " << robot_state.F_T_EE << ", \"EE_T_K\": " << robot_state.EE_T_K
          << ", \"m_ee\": " << robot_state.m_ee << ", \"F_x_Cee\": " << robot_state.F_x_Cee
          << ", \"I_ee\": " << robot_state.I_ee << ", \"m_load\": " << robot_state.m_load
          << ", \"F_x_Cload\": " << robot_state.F_x_Cload << ", \"I_load\": " << robot_state.I_load
          << ", \"m_total\": " << robot_state.m_total
          << ", \"F_x_Ctotal\": " << robot_state.F_x_Ctotal
          << ", \"I_total\": " << robot_state.I_total << ", \"elbow\": " << robot_state.elbow
          << ", \"elbow_d\": " << robot_state.elbow_d << ", \"elbow_c\": " << robot_state.elbow_c
          << ", \"delbow_c\": " << robot_state.delbow_c
          << ", \"ddelbow_c\": " << robot_state.ddelbow_c << ", \"tau_J\": " << robot_state.tau_J
          << ", \"tau_J_d\": " << robot_state.tau_J_d << ", \"dtau_J\": " << robot_state.dtau_J
          << ", \"q\": " << robot_state.q << ", \"dq\": " << robot_state.dq
          << ", \"q_d\": " << robot_state.q_d << ", \"dq_d\": " << robot_state.dq_d
          << ", \"ddq_d\": " << robot_state.ddq_d
          << ", \"joint_contact\": " << robot_state.joint_contact
          << ", \"cartesian_contact\": " << robot_state.cartesian_contact
          << ", \"joint_collision\": " << robot_state.joint_collision
          << ", \"cartesian_collision\": " << robot_state.cartesian_collision
          << ", \"tau_ext_hat_filtered\": " << robot_state.tau_ext_hat_filtered
          << ", \"O_F_ext_hat_K\": " << robot_state.O_F_ext_hat_K
          << ", \"K_F_ext_hat_K\": " << robot_state.K_F_ext_hat_K
          << ", \"O_dP_EE_d\": " << robot_state.O_dP_EE_d
          << ", \"O_T_EE_c\": " << robot_state.O_T_EE_c
          << ", \"O_dP_EE_c\": " << robot_state.O_dP_EE_c
          << ", \"O_ddP_EE_c\": " << robot_state.O_ddP_EE_c << ", \"theta\": " << robot_state.theta
          << ", \"dtheta\": " << robot_state.dtheta
          << ", \"current_errors\": " << robot_state.current_errors
          << ", \"last_motion_errors\": " << robot_state.last_motion_errors
          << ", \"control_command_success_rate\": " << robot_state.control_command_success_rate
          << ", \"robot_mode\": " << robot_state.robot_mode
          << ", \"time\": " << robot_state.time.toMSec() << "}";
  return ostream;
}

}  // namespace franka
<|endoftext|>