<commit_before>/**
* @version    GrPPI v0.1
* @copyright    Copyright (C) 2017 Universidad Carlos III de Madrid. All rights reserved.
* @license    GNU/GPL, see LICENSE.txt
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You have received a copy of the GNU General Public License in LICENSE.txt
* also available in <http://www.gnu.org/licenses/gpl.html>.
*
* See COPYRIGHT.txt for copyright notices and details.
*/
// Standard library
#include <iostream>
#include <vector>
#include <fstream>
#include <chrono>
#include <string>
#include <numeric>
#include <stdexcept>
#include <random>

// grppi
#include "divideconquer.h"

// Samples shared utilities
#include "../../util/util.h"

struct range {
  std::vector<int>::iterator first, last;

  auto size() const { return distance(first,last); }
  friend std::ostream & operator<<(std::ostream & os, const range & r);
};

std::ostream & operator<<(std::ostream & os, const range & r) {
  os << "(size= " << r.size() << ") ";
  std::copy(r.first, r.last, std::ostream_iterator<int>(std::cerr, " "));
  return os;
}

std::vector<range> divide(range r) {
  auto mid = r.first + distance(r.first,r.last)/2;
  return { {r.first,mid} , {mid, r.last} };
}

void sort_sequence(grppi::polymorphic_execution & exec, int n) {
  using namespace std;

  std::random_device rdev;
  std::uniform_int_distribution<> gen{1,1000};

  vector<int> v;
  for (int i=0; i<n; ++i) {
    v.push_back(gen(rdev));
  }

  range problem{begin(v), end(v)};

/*
  auto res = grppi::divide_conquer(exec,
    problem,
    [](auto r) -> vector<range> {
      if (1>=r.size()) { return {r}; }
      else { return divide(r); }
    },
    [](auto x) { return x; },
    [](auto r1, auto r2) {
      std::inplace_merge(r1.first, r1.last, r2.last);
      return range{r1.first, r2.last};
    }
  );
*/

  copy(begin(v), end(v), ostream_iterator<int>(cout, " "));
  cout << endl;
}

void print_message(const std::string & prog, const std::string & msg) {
  using namespace std;

  cerr << msg << endl;
  cerr << "Usage: " << prog << " size mode" << endl;
  cerr << "  size: Integer value with problem size" << endl;
  cerr << "  mode:" << endl;
  print_available_modes(cerr);
}

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

  using namespace std;

  if(argc < 3){
    print_message(argv[0], "Invalid number of arguments.");
    return -1;
  }

  int n = stoi(argv[1]);
  if(n <= 0){
    print_message(argv[0], "Invalid problem size. Use a positive number.");
    return -1;
  }

  if (!run_test(argv[2], sort_sequence, n)) {
    print_message(argv[0], "Invalid policy.");
    return -1;
  }

  return 0;
}
<commit_msg>Uncomented call to divide/conquer<commit_after>/**
* @version    GrPPI v0.1
* @copyright    Copyright (C) 2017 Universidad Carlos III de Madrid. All rights reserved.
* @license    GNU/GPL, see LICENSE.txt
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You have received a copy of the GNU General Public License in LICENSE.txt
* also available in <http://www.gnu.org/licenses/gpl.html>.
*
* See COPYRIGHT.txt for copyright notices and details.
*/
// Standard library
#include <iostream>
#include <vector>
#include <fstream>
#include <chrono>
#include <string>
#include <numeric>
#include <stdexcept>
#include <random>

// grppi
#include "divideconquer.h"

// Samples shared utilities
#include "../../util/util.h"

struct range {
  std::vector<int>::iterator first, last;

  auto size() const { return distance(first,last); }
  friend std::ostream & operator<<(std::ostream & os, const range & r);
};

std::ostream & operator<<(std::ostream & os, const range & r) {
  os << "(size= " << r.size() << ") ";
  std::copy(r.first, r.last, std::ostream_iterator<int>(std::cerr, " "));
  return os;
}

std::vector<range> divide(range r) {
  auto mid = r.first + distance(r.first,r.last)/2;
  return { {r.first,mid} , {mid, r.last} };
}

void sort_sequence(grppi::polymorphic_execution & exec, int n) {
  using namespace std;

  std::random_device rdev;
  std::uniform_int_distribution<> gen{1,1000};

  vector<int> v;
  for (int i=0; i<n; ++i) {
    v.push_back(gen(rdev));
  }

  range problem{begin(v), end(v)};

  auto res = grppi::divide_conquer(exec,
    problem,
    [](auto r) -> vector<range> {
      if (1>=r.size()) { return {r}; }
      else { return divide(r); }
    },
    [](auto x) { return x; },
    [](auto r1, auto r2) {
      std::inplace_merge(r1.first, r1.last, r2.last);
      return range{r1.first, r2.last};
    }
  );

  copy(begin(v), end(v), ostream_iterator<int>(cout, " "));
  cout << endl;
}

void print_message(const std::string & prog, const std::string & msg) {
  using namespace std;

  cerr << msg << endl;
  cerr << "Usage: " << prog << " size mode" << endl;
  cerr << "  size: Integer value with problem size" << endl;
  cerr << "  mode:" << endl;
  print_available_modes(cerr);
}

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

  using namespace std;

  if(argc < 3){
    print_message(argv[0], "Invalid number of arguments.");
    return -1;
  }

  int n = stoi(argv[1]);
  if(n <= 0){
    print_message(argv[0], "Invalid problem size. Use a positive number.");
    return -1;
  }

  if (!run_test(argv[2], sort_sequence, n)) {
    print_message(argv[0], "Invalid policy.");
    return -1;
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <openssl/evp.h>
#include <openssl/rand.h>

#include <common/factory.h>

#include <crypto/crypto_random.h>

namespace {
	typedef	int (RAND_func)(unsigned char *, int);
}

class CryptoRandomSessionRAND : public CryptoRandomSession {
	LogHandle log_;
	const RAND_func *func_;
public:
	CryptoRandomSessionRAND(const RAND_func *func)
	: log_("/crypto/random/session/openssl"),
	  func_(func)
	{ }

	~CryptoRandomSessionRAND()
	{ }

	Action *generate(size_t len, EventCallback *cb)
	{
		ASSERT(log_, len != 0);

		/*
		 * We process a single, large, linear byte buffer here rather
		 * than going a BufferSegment at a time, even though the byte
		 * buffer is less efficient than some alternatives, because
		 * I am a bad person and I should feel bad.
		 */
		uint8_t bytes[len];
		int rv = func_(bytes, sizeof bytes);
		if (rv == 0) {
			cb->param(Event::Error);
			return (cb->schedule());
		}
		cb->param(Event(Event::Done, Buffer(bytes, sizeof bytes)));
		return (cb->schedule());
	}
};

class CryptoRandomMethodOpenSSL : public CryptoRandomMethod {
	LogHandle log_;
	std::map<CryptoRandomType, const RAND_func *> func_map_;
public:
	CryptoRandomMethodOpenSSL(void)
	: log_("/crypto/random/openssl"),
	  func_map_()
	{
		OpenSSL_add_all_algorithms();

		func_map_[CryptoTypeRNG] = RAND_bytes;
		func_map_[CryptoTypePRNG] = RAND_pseudo_bytes;

		/* XXX Register.  */
	}

	~CryptoRandomMethodOpenSSL()
	{
		/* XXX Unregister.  */
	}

	/*
	 * Synchronous randomness generation.  May not succeed.
	 */
	bool generate(CryptoRandomType func, size_t len, Buffer *out) const
	{
		std::map<CryptoRandomType, const RAND_func *>::const_iterator it;

		it = func_map_.find(func);
		if (it == func_map_.end())
			return (false);

		uint8_t bytes[len];
		int rv = it->second(bytes, sizeof bytes);
		if (rv == 0)
			return (false);

		out->append(bytes, sizeof bytes);
		return (true);
	}

	CryptoRandomSession *session(CryptoRandomType func) const
	{
		std::map<CryptoRandomType, const RAND_func *>::const_iterator it;

		it = func_map_.find(func);
		if (it != func_map_.end())
			return (new CryptoRandomSessionRAND(it->second));
		return (NULL);
	}
};

namespace {
	static CryptoRandomMethodOpenSSL crypto_random_method_openssl;
}
const CryptoRandomMethod *CryptoRandomMethod::default_method = &crypto_random_method_openssl; /* XXX */
<commit_msg>Soothe clang's unease over my gratuitous and flagrant use of the const qualifier.<commit_after>#include <openssl/evp.h>
#include <openssl/rand.h>

#include <common/factory.h>

#include <crypto/crypto_random.h>

namespace {
	typedef	int (RAND_func)(unsigned char *, int);
}

class CryptoRandomSessionRAND : public CryptoRandomSession {
	LogHandle log_;
	RAND_func *func_;
public:
	CryptoRandomSessionRAND(RAND_func *func)
	: log_("/crypto/random/session/openssl"),
	  func_(func)
	{ }

	~CryptoRandomSessionRAND()
	{ }

	Action *generate(size_t len, EventCallback *cb)
	{
		ASSERT(log_, len != 0);

		/*
		 * We process a single, large, linear byte buffer here rather
		 * than going a BufferSegment at a time, even though the byte
		 * buffer is less efficient than some alternatives, because
		 * I am a bad person and I should feel bad.
		 */
		uint8_t bytes[len];
		int rv = func_(bytes, sizeof bytes);
		if (rv == 0) {
			cb->param(Event::Error);
			return (cb->schedule());
		}
		cb->param(Event(Event::Done, Buffer(bytes, sizeof bytes)));
		return (cb->schedule());
	}
};

class CryptoRandomMethodOpenSSL : public CryptoRandomMethod {
	LogHandle log_;
	std::map<CryptoRandomType, RAND_func *> func_map_;
public:
	CryptoRandomMethodOpenSSL(void)
	: log_("/crypto/random/openssl"),
	  func_map_()
	{
		OpenSSL_add_all_algorithms();

		func_map_[CryptoTypeRNG] = RAND_bytes;
		func_map_[CryptoTypePRNG] = RAND_pseudo_bytes;

		/* XXX Register.  */
	}

	~CryptoRandomMethodOpenSSL()
	{
		/* XXX Unregister.  */
	}

	/*
	 * Synchronous randomness generation.  May not succeed.
	 */
	bool generate(CryptoRandomType func, size_t len, Buffer *out) const
	{
		std::map<CryptoRandomType, RAND_func *>::const_iterator it;

		it = func_map_.find(func);
		if (it == func_map_.end())
			return (false);

		uint8_t bytes[len];
		int rv = it->second(bytes, sizeof bytes);
		if (rv == 0)
			return (false);

		out->append(bytes, sizeof bytes);
		return (true);
	}

	CryptoRandomSession *session(CryptoRandomType func) const
	{
		std::map<CryptoRandomType, RAND_func *>::const_iterator it;

		it = func_map_.find(func);
		if (it != func_map_.end())
			return (new CryptoRandomSessionRAND(it->second));
		return (NULL);
	}
};

namespace {
	static CryptoRandomMethodOpenSSL crypto_random_method_openssl;
}
const CryptoRandomMethod *CryptoRandomMethod::default_method = &crypto_random_method_openssl; /* XXX */
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageToStructuredPoints.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkImageToStructuredPoints.h"

#include "vtkCellData.h"
#include "vtkFieldData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkStructuredPoints.h"

#include <math.h>

vtkCxxRevisionMacro(vtkImageToStructuredPoints, "1.54");
vtkStandardNewMacro(vtkImageToStructuredPoints);

//----------------------------------------------------------------------------
vtkImageToStructuredPoints::vtkImageToStructuredPoints()
{
  this->Translate[0] = this->Translate[1] = this->Translate[2] = 0;
  this->NumberOfRequiredInputs = 1;
  this->SetNthOutput(0,vtkStructuredPoints::New());
  this->Outputs[0]->Delete();
}

//----------------------------------------------------------------------------
vtkImageToStructuredPoints::~vtkImageToStructuredPoints()
{
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

//----------------------------------------------------------------------------
vtkStructuredPoints *vtkImageToStructuredPoints::GetOutput()
{
  if (this->NumberOfOutputs < 1)
    {
    return NULL;
    }

  return (vtkStructuredPoints *)(this->Outputs[0]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::SetInput(vtkImageData *input)
{
  this->vtkProcessObject::SetNthInput(0, input);
}

//----------------------------------------------------------------------------
vtkImageData *vtkImageToStructuredPoints::GetInput()
{
  if (this->NumberOfInputs < 1)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[0]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::SetVectorInput(vtkImageData *input)
{
  this->vtkProcessObject::SetNthInput(1, input);
}

//----------------------------------------------------------------------------
vtkImageData *vtkImageToStructuredPoints::GetVectorInput()
{
  if (this->NumberOfInputs < 2)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[1]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::Execute()
{
  int uExtent[6];
  int *wExtent;

  int idxX, idxY, idxZ;
  int maxX = 0;
  int maxY = 0;
  int maxZ = 0;;
  int inIncX, inIncY, inIncZ, rowLength;
  unsigned char *inPtr1, *inPtr, *outPtr;
  vtkStructuredPoints *output = this->GetOutput();
  vtkImageData *data = this->GetInput();
  vtkImageData *vData = this->GetVectorInput();

  if (!data && !vData)
    {
    vtkErrorMacro("Unable to generate data!");
    return;
    }

  output->GetUpdateExtent(uExtent);
  output->SetExtent(uExtent);

  uExtent[0] += this->Translate[0];
  uExtent[1] += this->Translate[0];
  uExtent[2] += this->Translate[1];
  uExtent[3] += this->Translate[1];
  uExtent[4] += this->Translate[2];
  uExtent[5] += this->Translate[2];

  // if the data extent matches the update extent then just pass the data
  // otherwise we must reformat and copy the data
  if (data)
    {
    wExtent = data->GetExtent();
    if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] &&
        wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] &&
        wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5])
      {
      if (data->GetPointData())
        {
        output->GetPointData()->PassData(data->GetPointData());
        }
      if (data->GetCellData())
        {
        output->GetCellData()->PassData(data->GetCellData());
        }
      if (data->GetFieldData())
        {
        output->GetFieldData()->ShallowCopy(data->GetFieldData());
        }
      }
    else
      {
      inPtr = (unsigned char *) data->GetScalarPointerForExtent(uExtent);
      outPtr = (unsigned char *) output->GetScalarPointer();

      // Get increments to march through data
      data->GetIncrements(inIncX, inIncY, inIncZ);

      // find the region to loop over
      rowLength = (uExtent[1] - uExtent[0]+1)*inIncX*data->GetScalarSize();
      maxX = uExtent[1] - uExtent[0];
      maxY = uExtent[3] - uExtent[2];
      maxZ = uExtent[5] - uExtent[4];
      inIncY *= data->GetScalarSize();
      inIncZ *= data->GetScalarSize();

      // Loop through output pixels
      for (idxZ = 0; idxZ <= maxZ; idxZ++)
        {
        inPtr1 = inPtr + idxZ*inIncZ;
        for (idxY = 0; idxY <= maxY; idxY++)
          {
          memcpy(outPtr,inPtr1,rowLength);
          inPtr1 += inIncY;
          outPtr += rowLength;
          }
        }
      }
    }

  if (vData)
    {
    // if the data extent matches the update extent then just pass the data
    // otherwise we must reformat and copy the data
    wExtent = vData->GetExtent();
    if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] &&
        wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] &&
        wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5])
      {
      output->GetPointData()->SetVectors(vData->GetPointData()->GetScalars());
      }
    else
      {
      vtkDataArray *fv = vtkDataArray::CreateDataArray(vData->GetScalarType());
      float *inPtr2 = (float *)(vData->GetScalarPointerForExtent(uExtent));

      fv->SetNumberOfComponents(3);
      fv->SetNumberOfTuples((maxZ+1)*(maxY+1)*(maxX+1));
      vData->GetContinuousIncrements(uExtent, inIncX, inIncY, inIncZ);
      int numComp = vData->GetNumberOfScalarComponents();
      int idx = 0;

      // Loop through ouput pixels
      for (idxZ = 0; idxZ <= maxZ; idxZ++)
        {
        for (idxY = 0; idxY <= maxY; idxY++)
          {
          for (idxX = 0; idxX <= maxX; idxX++)
            {
            fv->SetTuple(idx,inPtr2);
            inPtr2 += numComp;
            idx++;
            }
          inPtr2 += inIncY;
          }
        inPtr2 += inIncZ;
        }
      output->GetPointData()->SetVectors(fv);
      fv->Delete();
      }
    }
}

//----------------------------------------------------------------------------
// Copy WholeExtent, Spacing and Origin.
void vtkImageToStructuredPoints::ExecuteInformation()
{
  vtkImageData *input = this->GetInput();
  vtkImageData *vInput = this->GetVectorInput();
  vtkStructuredPoints *output = this->GetOutput();
  int whole[6], *tmp;
  double *spacing, origin[3];

  if (output == NULL)
    {
    return;
    }

  if (input)
    {
    output->SetScalarType(input->GetScalarType());
    output->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());
    input->GetWholeExtent(whole);
    spacing = input->GetSpacing();
    input->GetOrigin(origin);
    }
  else if (vInput)
    {
    whole[0] = whole[2] = whole[4] = -VTK_LARGE_INTEGER;
    whole[1] = whole[3] = whole[5] = VTK_LARGE_INTEGER;
    spacing = vInput->GetSpacing();
    vInput->GetOrigin(origin);
    }
  else
    {
    return;
    }
  // intersections for whole extent
  if (vInput)
    {
    tmp = vInput->GetWholeExtent();
    if (tmp[0] > whole[0]) {whole[0] = tmp[0];}
    if (tmp[2] > whole[2]) {whole[2] = tmp[2];}
    if (tmp[4] > whole[4]) {whole[4] = tmp[4];}
    if (tmp[1] < whole[1]) {whole[1] = tmp[1];}
    if (tmp[3] < whole[1]) {whole[3] = tmp[3];}
    if (tmp[5] < whole[1]) {whole[5] = tmp[5];}
    }

  // slide min extent to 0,0,0 (I Hate this !!!!)
  this->Translate[0] = whole[0];
  this->Translate[1] = whole[2];
  this->Translate[2] = whole[4];

  origin[0] += spacing[0] * whole[0];
  origin[1] += spacing[1] * whole[2];
  origin[2] += spacing[2] * whole[4];
  whole[1] -= whole[0];
  whole[3] -= whole[2];
  whole[5] -= whole[4];
  whole[0] = whole[2] = whole[4] = 0;

  output->SetWholeExtent(whole);
  // Now should Origin and Spacing really be part of information?
  // How about xyx arrays in RectilinearGrid of Points in StructuredGrid?
  output->SetOrigin(origin);
  output->SetSpacing(spacing);
}

//----------------------------------------------------------------------------
vtkStructuredPoints *vtkImageToStructuredPoints::GetOutput(int idx)
{
  return (vtkStructuredPoints *) this->vtkSource::GetOutput(idx);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::ComputeInputUpdateExtents(vtkDataObject *data)
{
  vtkStructuredPoints *output = (vtkStructuredPoints*)data;
  int ext[6];
  vtkImageData *input;

  output->GetUpdateExtent(ext);
  ext[0] += this->Translate[0];
  ext[1] += this->Translate[0];
  ext[2] += this->Translate[1];
  ext[3] += this->Translate[1];
  ext[4] += this->Translate[2];
  ext[5] += this->Translate[2];

  input = this->GetInput();
  if (input)
    {
    input->SetUpdateExtent(ext);
    }

  input = this->GetVectorInput();
  if (input)
    {
    input->SetUpdateExtent(ext);
    }
}

<commit_msg>BUG: Do not crash if input has no arrays.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageToStructuredPoints.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkImageToStructuredPoints.h"

#include "vtkCellData.h"
#include "vtkFieldData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkStructuredPoints.h"

#include <math.h>

vtkCxxRevisionMacro(vtkImageToStructuredPoints, "1.55");
vtkStandardNewMacro(vtkImageToStructuredPoints);

//----------------------------------------------------------------------------
vtkImageToStructuredPoints::vtkImageToStructuredPoints()
{
  this->Translate[0] = this->Translate[1] = this->Translate[2] = 0;
  this->NumberOfRequiredInputs = 1;
  this->SetNthOutput(0,vtkStructuredPoints::New());
  this->Outputs[0]->Delete();
}

//----------------------------------------------------------------------------
vtkImageToStructuredPoints::~vtkImageToStructuredPoints()
{
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

//----------------------------------------------------------------------------
vtkStructuredPoints *vtkImageToStructuredPoints::GetOutput()
{
  if (this->NumberOfOutputs < 1)
    {
    return NULL;
    }

  return (vtkStructuredPoints *)(this->Outputs[0]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::SetInput(vtkImageData *input)
{
  this->vtkProcessObject::SetNthInput(0, input);
}

//----------------------------------------------------------------------------
vtkImageData *vtkImageToStructuredPoints::GetInput()
{
  if (this->NumberOfInputs < 1)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[0]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::SetVectorInput(vtkImageData *input)
{
  this->vtkProcessObject::SetNthInput(1, input);
}

//----------------------------------------------------------------------------
vtkImageData *vtkImageToStructuredPoints::GetVectorInput()
{
  if (this->NumberOfInputs < 2)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[1]);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::Execute()
{
  int uExtent[6];
  int *wExtent;

  int idxX, idxY, idxZ;
  int maxX = 0;
  int maxY = 0;
  int maxZ = 0;;
  int inIncX, inIncY, inIncZ, rowLength;
  unsigned char *inPtr1, *inPtr, *outPtr;
  vtkStructuredPoints *output = this->GetOutput();
  vtkImageData *data = this->GetInput();
  vtkImageData *vData = this->GetVectorInput();

  if (!data && !vData)
    {
    vtkErrorMacro("Unable to generate data!");
    return;
    }

  output->GetUpdateExtent(uExtent);
  output->SetExtent(uExtent);

  uExtent[0] += this->Translate[0];
  uExtent[1] += this->Translate[0];
  uExtent[2] += this->Translate[1];
  uExtent[3] += this->Translate[1];
  uExtent[4] += this->Translate[2];
  uExtent[5] += this->Translate[2];

  // if the data extent matches the update extent then just pass the data
  // otherwise we must reformat and copy the data
  if (data)
    {
    wExtent = data->GetExtent();
    if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] &&
        wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] &&
        wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5])
      {
      if (data->GetPointData())
        {
        output->GetPointData()->PassData(data->GetPointData());
        }
      if (data->GetCellData())
        {
        output->GetCellData()->PassData(data->GetCellData());
        }
      if (data->GetFieldData())
        {
        output->GetFieldData()->ShallowCopy(data->GetFieldData());
        }
      }
    else
      {
      inPtr = (unsigned char *) data->GetScalarPointerForExtent(uExtent);
      outPtr = (unsigned char *) output->GetScalarPointer();

      // Make sure there are data.
      if(!inPtr || !outPtr)
        {
        output->Initialize();
        return;
        }

      // Get increments to march through data
      data->GetIncrements(inIncX, inIncY, inIncZ);

      // find the region to loop over
      rowLength = (uExtent[1] - uExtent[0]+1)*inIncX*data->GetScalarSize();
      maxX = uExtent[1] - uExtent[0];
      maxY = uExtent[3] - uExtent[2];
      maxZ = uExtent[5] - uExtent[4];
      inIncY *= data->GetScalarSize();
      inIncZ *= data->GetScalarSize();

      // Loop through output pixels
      for (idxZ = 0; idxZ <= maxZ; idxZ++)
        {
        inPtr1 = inPtr + idxZ*inIncZ;
        for (idxY = 0; idxY <= maxY; idxY++)
          {
          memcpy(outPtr,inPtr1,rowLength);
          inPtr1 += inIncY;
          outPtr += rowLength;
          }
        }
      }
    }

  if (vData)
    {
    // if the data extent matches the update extent then just pass the data
    // otherwise we must reformat and copy the data
    wExtent = vData->GetExtent();
    if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] &&
        wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] &&
        wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5])
      {
      output->GetPointData()->SetVectors(vData->GetPointData()->GetScalars());
      }
    else
      {
      vtkDataArray *fv = vtkDataArray::CreateDataArray(vData->GetScalarType());
      float *inPtr2 = (float *)(vData->GetScalarPointerForExtent(uExtent));

      // Make sure there are data.
      if(!inPtr2)
        {
        output->Initialize();
        return;
        }

      fv->SetNumberOfComponents(3);
      fv->SetNumberOfTuples((maxZ+1)*(maxY+1)*(maxX+1));
      vData->GetContinuousIncrements(uExtent, inIncX, inIncY, inIncZ);
      int numComp = vData->GetNumberOfScalarComponents();
      int idx = 0;

      // Loop through ouput pixels
      for (idxZ = 0; idxZ <= maxZ; idxZ++)
        {
        for (idxY = 0; idxY <= maxY; idxY++)
          {
          for (idxX = 0; idxX <= maxX; idxX++)
            {
            fv->SetTuple(idx,inPtr2);
            inPtr2 += numComp;
            idx++;
            }
          inPtr2 += inIncY;
          }
        inPtr2 += inIncZ;
        }
      output->GetPointData()->SetVectors(fv);
      fv->Delete();
      }
    }
}

//----------------------------------------------------------------------------
// Copy WholeExtent, Spacing and Origin.
void vtkImageToStructuredPoints::ExecuteInformation()
{
  vtkImageData *input = this->GetInput();
  vtkImageData *vInput = this->GetVectorInput();
  vtkStructuredPoints *output = this->GetOutput();
  int whole[6], *tmp;
  double *spacing, origin[3];

  if (output == NULL)
    {
    return;
    }

  if (input)
    {
    output->SetScalarType(input->GetScalarType());
    output->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());
    input->GetWholeExtent(whole);
    spacing = input->GetSpacing();
    input->GetOrigin(origin);
    }
  else if (vInput)
    {
    whole[0] = whole[2] = whole[4] = -VTK_LARGE_INTEGER;
    whole[1] = whole[3] = whole[5] = VTK_LARGE_INTEGER;
    spacing = vInput->GetSpacing();
    vInput->GetOrigin(origin);
    }
  else
    {
    return;
    }
  // intersections for whole extent
  if (vInput)
    {
    tmp = vInput->GetWholeExtent();
    if (tmp[0] > whole[0]) {whole[0] = tmp[0];}
    if (tmp[2] > whole[2]) {whole[2] = tmp[2];}
    if (tmp[4] > whole[4]) {whole[4] = tmp[4];}
    if (tmp[1] < whole[1]) {whole[1] = tmp[1];}
    if (tmp[3] < whole[1]) {whole[3] = tmp[3];}
    if (tmp[5] < whole[1]) {whole[5] = tmp[5];}
    }

  // slide min extent to 0,0,0 (I Hate this !!!!)
  this->Translate[0] = whole[0];
  this->Translate[1] = whole[2];
  this->Translate[2] = whole[4];

  origin[0] += spacing[0] * whole[0];
  origin[1] += spacing[1] * whole[2];
  origin[2] += spacing[2] * whole[4];
  whole[1] -= whole[0];
  whole[3] -= whole[2];
  whole[5] -= whole[4];
  whole[0] = whole[2] = whole[4] = 0;

  output->SetWholeExtent(whole);
  // Now should Origin and Spacing really be part of information?
  // How about xyx arrays in RectilinearGrid of Points in StructuredGrid?
  output->SetOrigin(origin);
  output->SetSpacing(spacing);
}

//----------------------------------------------------------------------------
vtkStructuredPoints *vtkImageToStructuredPoints::GetOutput(int idx)
{
  return (vtkStructuredPoints *) this->vtkSource::GetOutput(idx);
}

//----------------------------------------------------------------------------
void vtkImageToStructuredPoints::ComputeInputUpdateExtents(vtkDataObject *data)
{
  vtkStructuredPoints *output = (vtkStructuredPoints*)data;
  int ext[6];
  vtkImageData *input;

  output->GetUpdateExtent(ext);
  ext[0] += this->Translate[0];
  ext[1] += this->Translate[0];
  ext[2] += this->Translate[1];
  ext[3] += this->Translate[1];
  ext[4] += this->Translate[2];
  ext[5] += this->Translate[2];

  input = this->GetInput();
  if (input)
    {
    input->SetUpdateExtent(ext);
    }

  input = this->GetVectorInput();
  if (input)
    {
    input->SetUpdateExtent(ext);
    }
}

<|endoftext|>


<commit_before>/*
*
* Zero-config node ID negotiation
* -------------------------------
*
* A heartbeat message is a message with a 8 byte unique serial number as payload.
* A regular message is any message that is not a heartbeat message.
*
* All nodes MUST obey these four rules:
*
* a) At a given point in time, a node MUST consider a node ID taken (by others)
*   if any of the following is true:
*     - the node received a (not self-emitted) heartbeat message with that node ID
*       within the last second
*     - the node attempted and failed at sending a heartbeat message with that
*       node ID within the last second (failed in the sense of not ACK'd)
*
* b) At a given point in time, a node MUST NOT consider a node ID self-assigned
*   if, within the last second, it did not succeed in sending a heartbeat
*   message with that node ID.
*
* c) At a given point in time, a node MUST NOT send any heartbeat message with
*   a node ID that is taken.
*
* d) At a given point in time, a node MUST NOT send any regular message with
*   a node ID that is not self-assigned.
*
* Hardware allocation
* -------------------
*   RX FIFO0:
*       - filter bank 0: heartbeat messages
*/

#include "interface_can.hpp"
#include <unordered_map>
#include "fibre/crc.hpp"
#include "freertos_vars.h"
#include "utils.h"

#include <can.h>
#include <cmsis_os.h>
#include <stm32f4xx_hal.h>

#include <odrive_main.h>

std::unordered_map<CAN_HandleTypeDef *, ODriveCAN *> ctxMap;

// Constructor is called by communication.cpp and the handle is assigned appropriately
ODriveCAN::ODriveCAN(CAN_HandleTypeDef *handle, ODriveCAN::Config_t &config)
    : handle_{handle},
      config_{config} {
    ctxMap[handle_] = this;
}

void ODriveCAN::can_server_thread() {
    CAN_message_t heartbeat;
    heartbeat.id = 0x700 + config_.node_id;
    uint32_t lastHeartbeatTick = osKernelSysTick();

    for (;;) {
        CAN_message_t rxmsg;

        osSemaphoreWait(sem_can, 10);
        while (available()) {
            read(rxmsg);
            write(rxmsg);
        }

        // Handle heartbeat message
        heartbeat.buf[0] = axes[0]->error_;
        heartbeat.buf[1] = axes[0]->current_state_;
        heartbeat.buf[2] = axes[1]->error_;
        heartbeat.buf[3] = axes[2]->current_state_;
        uint32_t now = osKernelSysTick();
        if(now - lastHeartbeatTick >= 100){
            write(heartbeat);
            lastHeartbeatTick = now;
        }

        HAL_CAN_ActivateNotification(handle_, CAN_IT_RX_FIFO0_MSG_PENDING);
    }
}

static void can_server_thread_wrapper(void *ctx) {
    reinterpret_cast<ODriveCAN *>(ctx)->can_server_thread();
    reinterpret_cast<ODriveCAN *>(ctx)->thread_id_valid_ = false;
}

bool ODriveCAN::start_can_server() {
    HAL_StatusTypeDef status;

    set_baud_rate(config_.baud);
    status = HAL_CAN_Init(handle_);
    if (status != HAL_OK)
        return false;

    CAN_FilterTypeDef filter;
    filter.FilterActivation = ENABLE;
    filter.FilterBank = 0;
    filter.FilterFIFOAssignment = CAN_RX_FIFO0;
    filter.FilterIdHigh = 0x0000;
    filter.FilterIdLow = 0x0000;
    filter.FilterMaskIdHigh = 0x0000;
    filter.FilterMaskIdLow = 0x0000;
    filter.FilterMode = CAN_FILTERMODE_IDMASK;
    filter.FilterScale = CAN_FILTERSCALE_32BIT;

    status = HAL_CAN_ConfigFilter(handle_, &filter);
    if (status != HAL_OK)
        return false;

    status = HAL_CAN_Start(handle_);
    if (status != HAL_OK)
        return false;

    status = HAL_CAN_ActivateNotification(handle_,
                                          //   CAN_IT_TX_MAILBOX_EMPTY |
                                          CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING /* we probably only want this */
                                                                                //   CAN_IT_RX_FIFO0_FULL | CAN_IT_RX_FIFO1_FULL
                                                                                //   CAN_IT_RX_FIFO0_OVERRUN | CAN_IT_RX_FIFO1_OVERRUN |
                                                                                //   CAN_IT_WAKEUP | CAN_IT_SLEEP_ACK |
                                                                                //   CAN_IT_ERROR_WARNING | CAN_IT_ERROR_PASSIVE |
                                                                                //   CAN_IT_BUSOFF | CAN_IT_LAST_ERROR_CODE |
                                                                                //   | CAN_IT_ERROR
    );
    if (status != HAL_OK)
        return false;

    osThreadDef(can_server_thread_def, can_server_thread_wrapper, osPriorityNormal, 0, 512);
    thread_id_ = osThreadCreate(osThread(can_server_thread_def), this);
    thread_id_valid_ = true;

    return true;
}

// Send a CAN message on the bus
uint32_t ODriveCAN::write(CAN_message_t &txmsg) {
    CAN_TxHeaderTypeDef header;
    header.StdId = txmsg.id;
    header.ExtId = txmsg.id;
    header.IDE = txmsg.isExt ? CAN_ID_EXT : CAN_ID_STD;
    header.RTR = CAN_RTR_DATA;
    header.DLC = txmsg.len;
    header.TransmitGlobalTime = FunctionalState::DISABLE;

    uint32_t retTxMailbox;
    if (HAL_CAN_GetTxMailboxesFreeLevel(handle_) > 0)
        HAL_CAN_AddTxMessage(handle_, &header, txmsg.buf, &retTxMailbox);

    return retTxMailbox;
}

uint32_t ODriveCAN::available() {
    return (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO0) + HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO1));
}

bool ODriveCAN::read(CAN_message_t &rxmsg) {
    CAN_RxHeaderTypeDef header;
    bool validRead = false;
    if (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO0) > 0) {
        HAL_CAN_GetRxMessage(handle_, CAN_RX_FIFO0, &header, rxmsg.buf);
        validRead = true;
    } else if (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO1) > 0) {
        HAL_CAN_GetRxMessage(handle_, CAN_RX_FIFO1, &header, rxmsg.buf);
        validRead = true;
    }

    rxmsg.isExt = header.IDE;
    rxmsg.id = rxmsg.isExt ? header.ExtId : header.StdId;  // If it's an extended message, pass the extended ID
    rxmsg.len = header.DLC;

    return validRead;
}

// Set one of only a few common baud rates.  CAN doesn't do arbitrary baud rates well due to the time-quanta issue.
// 21 TQ allows for easy sampling at exactly 80% (recommended by Vector Informatik GmbH for high reliability systems)
// Conveniently, the CAN peripheral's 42MHz clock lets us easily create 21TQs for all common baud rates
void ODriveCAN::set_baud_rate(uint32_t baudRate) {
    switch (baudRate) {
        case CAN_BAUD_125K:
            handle_->Init.Prescaler = 16;  // 21 TQ's
            config_.baud = baudRate;
            break;

        case CAN_BAUD_250K:
            handle_->Init.Prescaler = 8;  // 21 TQ's
            config_.baud = baudRate;
            break;

        case CAN_BAUD_500K:
            handle_->Init.Prescaler = 4;  // 21 TQ's
            config_.baud = baudRate;
            break;

        case CAN_BAUD_1000K:
            handle_->Init.Prescaler = 2;  // 21 TQ's
            config_.baud = baudRate;
            break;

        default:
            break;  // baudRate is invalid, so do nothing
    }
}

void ODriveCAN::set_node_id(uint8_t nodeID) {
    // Allow for future nodeID validation by making this a set function
    config_.node_id = nodeID;
}

void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
    HAL_CAN_DeactivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
    osSemaphoreRelease(sem_can);
}
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) {
    // osSemaphoreRelease(sem_can);
}
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) {
    HAL_CAN_ResetError(hcan);
}
<commit_msg>We don't have an axis 2...<commit_after>/*
*
* Zero-config node ID negotiation
* -------------------------------
*
* A heartbeat message is a message with a 8 byte unique serial number as payload.
* A regular message is any message that is not a heartbeat message.
*
* All nodes MUST obey these four rules:
*
* a) At a given point in time, a node MUST consider a node ID taken (by others)
*   if any of the following is true:
*     - the node received a (not self-emitted) heartbeat message with that node ID
*       within the last second
*     - the node attempted and failed at sending a heartbeat message with that
*       node ID within the last second (failed in the sense of not ACK'd)
*
* b) At a given point in time, a node MUST NOT consider a node ID self-assigned
*   if, within the last second, it did not succeed in sending a heartbeat
*   message with that node ID.
*
* c) At a given point in time, a node MUST NOT send any heartbeat message with
*   a node ID that is taken.
*
* d) At a given point in time, a node MUST NOT send any regular message with
*   a node ID that is not self-assigned.
*
* Hardware allocation
* -------------------
*   RX FIFO0:
*       - filter bank 0: heartbeat messages
*/

#include "interface_can.hpp"
#include <unordered_map>
#include "fibre/crc.hpp"
#include "freertos_vars.h"
#include "utils.h"

#include <can.h>
#include <cmsis_os.h>
#include <stm32f4xx_hal.h>

#include <odrive_main.h>

std::unordered_map<CAN_HandleTypeDef *, ODriveCAN *> ctxMap;

// Constructor is called by communication.cpp and the handle is assigned appropriately
ODriveCAN::ODriveCAN(CAN_HandleTypeDef *handle, ODriveCAN::Config_t &config)
    : handle_{handle},
      config_{config} {
    ctxMap[handle_] = this;
}

void ODriveCAN::can_server_thread() {
    CAN_message_t heartbeat;
    heartbeat.id = 0x700 + config_.node_id;
    uint32_t lastHeartbeatTick = osKernelSysTick();

    for (;;) {
        CAN_message_t rxmsg;

        osSemaphoreWait(sem_can, 10);
        while (available()) {
            read(rxmsg);
            write(rxmsg);
        }

        // Handle heartbeat message
        heartbeat.buf[0] = axes[0]->error_;
        heartbeat.buf[1] = axes[0]->current_state_;
        heartbeat.buf[2] = axes[1]->error_;
        heartbeat.buf[3] = axes[1]->current_state_;
        uint32_t now = osKernelSysTick();
        if(now - lastHeartbeatTick >= 100){
            write(heartbeat);
            lastHeartbeatTick = now;
        }

        HAL_CAN_ActivateNotification(handle_, CAN_IT_RX_FIFO0_MSG_PENDING);
    }
}

static void can_server_thread_wrapper(void *ctx) {
    reinterpret_cast<ODriveCAN *>(ctx)->can_server_thread();
    reinterpret_cast<ODriveCAN *>(ctx)->thread_id_valid_ = false;
}

bool ODriveCAN::start_can_server() {
    HAL_StatusTypeDef status;

    set_baud_rate(config_.baud);
    status = HAL_CAN_Init(handle_);
    if (status != HAL_OK)
        return false;

    CAN_FilterTypeDef filter;
    filter.FilterActivation = ENABLE;
    filter.FilterBank = 0;
    filter.FilterFIFOAssignment = CAN_RX_FIFO0;
    filter.FilterIdHigh = 0x0000;
    filter.FilterIdLow = 0x0000;
    filter.FilterMaskIdHigh = 0x0000;
    filter.FilterMaskIdLow = 0x0000;
    filter.FilterMode = CAN_FILTERMODE_IDMASK;
    filter.FilterScale = CAN_FILTERSCALE_32BIT;

    status = HAL_CAN_ConfigFilter(handle_, &filter);
    if (status != HAL_OK)
        return false;

    status = HAL_CAN_Start(handle_);
    if (status != HAL_OK)
        return false;

    status = HAL_CAN_ActivateNotification(handle_,
                                          //   CAN_IT_TX_MAILBOX_EMPTY |
                                          CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING /* we probably only want this */
                                                                                //   CAN_IT_RX_FIFO0_FULL | CAN_IT_RX_FIFO1_FULL
                                                                                //   CAN_IT_RX_FIFO0_OVERRUN | CAN_IT_RX_FIFO1_OVERRUN |
                                                                                //   CAN_IT_WAKEUP | CAN_IT_SLEEP_ACK |
                                                                                //   CAN_IT_ERROR_WARNING | CAN_IT_ERROR_PASSIVE |
                                                                                //   CAN_IT_BUSOFF | CAN_IT_LAST_ERROR_CODE |
                                                                                //   | CAN_IT_ERROR
    );
    if (status != HAL_OK)
        return false;

    osThreadDef(can_server_thread_def, can_server_thread_wrapper, osPriorityNormal, 0, 512);
    thread_id_ = osThreadCreate(osThread(can_server_thread_def), this);
    thread_id_valid_ = true;

    return true;
}

// Send a CAN message on the bus
uint32_t ODriveCAN::write(CAN_message_t &txmsg) {
    CAN_TxHeaderTypeDef header;
    header.StdId = txmsg.id;
    header.ExtId = txmsg.id;
    header.IDE = txmsg.isExt ? CAN_ID_EXT : CAN_ID_STD;
    header.RTR = CAN_RTR_DATA;
    header.DLC = txmsg.len;
    header.TransmitGlobalTime = FunctionalState::DISABLE;

    uint32_t retTxMailbox;
    if (HAL_CAN_GetTxMailboxesFreeLevel(handle_) > 0)
        HAL_CAN_AddTxMessage(handle_, &header, txmsg.buf, &retTxMailbox);

    return retTxMailbox;
}

uint32_t ODriveCAN::available() {
    return (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO0) + HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO1));
}

bool ODriveCAN::read(CAN_message_t &rxmsg) {
    CAN_RxHeaderTypeDef header;
    bool validRead = false;
    if (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO0) > 0) {
        HAL_CAN_GetRxMessage(handle_, CAN_RX_FIFO0, &header, rxmsg.buf);
        validRead = true;
    } else if (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO1) > 0) {
        HAL_CAN_GetRxMessage(handle_, CAN_RX_FIFO1, &header, rxmsg.buf);
        validRead = true;
    }

    rxmsg.isExt = header.IDE;
    rxmsg.id = rxmsg.isExt ? header.ExtId : header.StdId;  // If it's an extended message, pass the extended ID
    rxmsg.len = header.DLC;

    return validRead;
}

// Set one of only a few common baud rates.  CAN doesn't do arbitrary baud rates well due to the time-quanta issue.
// 21 TQ allows for easy sampling at exactly 80% (recommended by Vector Informatik GmbH for high reliability systems)
// Conveniently, the CAN peripheral's 42MHz clock lets us easily create 21TQs for all common baud rates
void ODriveCAN::set_baud_rate(uint32_t baudRate) {
    switch (baudRate) {
        case CAN_BAUD_125K:
            handle_->Init.Prescaler = 16;  // 21 TQ's
            config_.baud = baudRate;
            break;

        case CAN_BAUD_250K:
            handle_->Init.Prescaler = 8;  // 21 TQ's
            config_.baud = baudRate;
            break;

        case CAN_BAUD_500K:
            handle_->Init.Prescaler = 4;  // 21 TQ's
            config_.baud = baudRate;
            break;

        case CAN_BAUD_1000K:
            handle_->Init.Prescaler = 2;  // 21 TQ's
            config_.baud = baudRate;
            break;

        default:
            break;  // baudRate is invalid, so do nothing
    }
}

void ODriveCAN::set_node_id(uint8_t nodeID) {
    // Allow for future nodeID validation by making this a set function
    config_.node_id = nodeID;
}

void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
    HAL_CAN_DeactivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
    osSemaphoreRelease(sem_can);
}
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) {
    // osSemaphoreRelease(sem_can);
}
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) {}
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) {
    HAL_CAN_ResetError(hcan);
}
<|endoftext|>


<commit_before>#include <mutex>
#include <future>
#include <utility>
#include <atomic>
#include <set>
#include <iostream>
#include <csignal>
#include <thread>
#include <chrono>
#include "zmq.hpp"
#include "json.hpp"
#include "easylogging++.h"
#include "network.hpp"

INITIALIZE_EASYLOGGINGPP

std::atomic<bool> interruptedBySignal;
using json = nlohmann::json;

void handleSignal(int sig)
{
  interruptedBySignal = true;
}

void initialiseSignalHandler()
{
  std::signal(SIGINT, handleSignal);
  std::signal(SIGTERM, handleSignal);
}

// Note that the mutex is intended to lock both the mapData and the ids
void collectClients(zmq::context_t& context, std::set<std::string>& ids,
    std::mutex& mutex, const std::string& mapData)
{
  uint msWait = 1;
  zmq::socket_t socket(context, ZMQ_ROUTER);
  socket.bind("tcp://*:5557");
  std::vector<zmq::pollitem_t> pollList = { {&socket, 0, ZMQ_POLLIN, 0} };

  auto newMsg = [&]() {return pollList[0].revents & ZMQ_POLLIN;};

  while (!interruptedBySignal)
  {
    zmq::poll(&(pollList[0]), pollList.size(), msWait);
    while (newMsg())
    {
      auto msg = receive(socket);
      if (msg.size() == 3)
      {
        std::lock_guard<std::mutex> lock(mutex);
        if (!ids.count(msg[2]))
        {
          ids.insert(msg[2]);
          LOG(INFO) << "New Player! ID: " << msg[2];
          send(socket, {msg[0], "", mapData});
        }
        else
        {
          LOG(INFO) << "Player trying to join with existing ID";
          send(socket,{msg[0], "", "ERROR: ID Taken. Please try something else."});
        }
      }
      else
      {
          LOG(INFO) << "Client sent mal-formed connection message";
          send(socket,{msg[0], "", "ERROR: Please connect with single msg frame as your ID"});
      }
    }
  }
}

int main(int ac, char* av[])
{
  int major, minor, patch;
  zmq::version (&major, &minor, &patch); printf ("Current ØMQ version is %d.%d.%d\n", major, minor, patch);
  zmq::context_t* context = new zmq::context_t(1);

  initialiseSignalHandler();

  LOG(INFO) << "Initialising sockets";

  zmq::socket_t logSocket(*context, ZMQ_PUB);
  zmq::socket_t stateSocket(*context, ZMQ_PUB);

  logSocket.bind("tcp://*:5555");
  stateSocket.bind("tcp://*:5556");

  LOG(INFO) << "Starting main loop";

  std::mutex mapDataMutex;
  std::string nextMapData = "nextMapData";
  std::string currentMapData = "currentMapData";
  std::set<std::string> nextPlayers;
  std::set<std::string> currentPlayers;

  std::future<void> controlThread = std::async(std::launch::async, collectClients,
      std::ref(*context),
      std::ref(nextPlayers),
      std::ref(mapDataMutex),
      std::cref(nextMapData));

  while(!interruptedBySignal)
  {
    // waiting period between games
    std::this_thread::sleep_for(std::chrono::seconds(30));

    //get the game started
    {
      std::lock_guard<std::mutex> lock(mapDataMutex);
      currentPlayers.clear();
      std::swap(currentPlayers, nextPlayers);
      currentMapData = nextMapData;
      nextMapData = "somenewmapdata";
    }

    //now play the game
    // finish off the game
  }

  // auto start = std::chrono::high_resolution_clock::now();
  // uint elapsedTime = 0;
  // while (elapsedTime < timeoutSecs)

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

  controlThread.wait();

  LOG(INFO) << "Closing sockets";

  logSocket.close();
  stateSocket.close();

  LOG(INFO) << "Deleting context";
  delete context;
  context = nullptr; // just in case

  LOG(INFO) << "Thankyou for playing spacerace!";
  return 0;

}
<commit_msg>bugfix: was not creating polllist properly<commit_after>#include <mutex>
#include <future>
#include <utility>
#include <atomic>
#include <set>
#include <iostream>
#include <csignal>
#include <thread>
#include <chrono>
#include "zmq.hpp"
#include "json.hpp"
#include "easylogging++.h"
#include "network.hpp"

INITIALIZE_EASYLOGGINGPP

std::atomic<bool> interruptedBySignal;
using json = nlohmann::json;

void handleSignal(int sig)
{
  interruptedBySignal = true;
}

void initialiseSignalHandler()
{
  std::signal(SIGINT, handleSignal);
  std::signal(SIGTERM, handleSignal);
}

// Note that the mutex is intended to lock both the mapData and the ids
void collectClients(zmq::context_t& context, std::set<std::string>& ids,
    std::mutex& mutex, const std::string& mapData)
{
  LOG(INFO) << "starting player management thread";
  // -1 implies wait until message
  int msWait = -1;
  int linger = 0;

  zmq::socket_t socket(context, ZMQ_ROUTER);
  socket.setsockopt(ZMQ_LINGER, &linger, sizeof(int));
  std::string address = "tcp://*:5557";
  socket.bind(address.c_str());

  // note the void* cast is a weird part of the zmq api
  zmq::pollitem_t pollList [] = {{(void*)socket, 0, ZMQ_POLLIN, 0}};
  while (!interruptedBySignal)
  {
    LOG(INFO) << "polling...";
    zmq::poll(pollList, 1, msWait);

    bool newMsg = pollList[0].revents & ZMQ_POLLIN;
    if (newMsg)
    {
      LOG(INFO) << "New message received!!";
      auto msg = receive(socket);
      if (msg.size() == 3)
      {
        std::lock_guard<std::mutex> lock(mutex);
        if (!ids.count(msg[2]))
        {
          ids.insert(msg[2]);
          LOG(INFO) << "New Player! ID: " << msg[2];
          send(socket, {msg[0], "", mapData});
        }
        else
        {
          LOG(INFO) << "Player trying to join with existing ID";
          send(socket,{msg[0], "", "ERROR: ID Taken. Please try something else."});
        }
      }
      else
      {
          LOG(INFO) << "Client sent mal-formed connection message";
          send(socket,{msg[0], "", "ERROR: Please connect with single msg frame as your ID"});
      }
    }
  }
}

int main(int ac, char* av[])
{
  zmq::context_t* context = new zmq::context_t(1);

  initialiseSignalHandler();

  LOG(INFO) << "Initialising sockets";

  zmq::socket_t logSocket(*context, ZMQ_PUB);
  zmq::socket_t stateSocket(*context, ZMQ_PUB);

  logSocket.bind("tcp://*:5555");
  stateSocket.bind("tcp://*:5556");

  LOG(INFO) << "Starting main loop";

  std::mutex mapDataMutex;
  std::string nextMapData = "nextMapData";
  std::string currentMapData = "currentMapData";
  std::set<std::string> nextPlayers;
  std::set<std::string> currentPlayers;

  std::future<void> controlThread = std::async(std::launch::async, collectClients,
      std::ref(*context),
      std::ref(nextPlayers),
      std::ref(mapDataMutex),
      std::cref(nextMapData));

  while(!interruptedBySignal)
  {
    // waiting period between games
    // need to do lots of short sleeps in a loop else ctrlc doesn't work
    std::this_thread::sleep_for(std::chrono::seconds(30));

    //get the game started
    {
      std::lock_guard<std::mutex> lock(mapDataMutex);
      currentPlayers.clear();
      std::swap(currentPlayers, nextPlayers);
      currentMapData = nextMapData;
      nextMapData = "somenewmapdata";
    }

    //now play the game
    // finish off the game
  }

  // auto start = std::chrono::high_resolution_clock::now();
  // uint elapsedTime = 0;
  // while (elapsedTime < timeoutSecs)

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

  controlThread.wait();

  LOG(INFO) << "Closing sockets";

  logSocket.close();
  stateSocket.close();

  LOG(INFO) << "Deleting context";
  delete context;
  context = nullptr; // just in case

  LOG(INFO) << "Thankyou for playing spacerace!";
  return 0;

}
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------
 This source file is part of Hopsan NG

 Copyright (c) 2011
    Mikael Axin, Robert Braun, Alessandro Dell'Amico, Björn Eriksson,
    Peter Nordin, Karl Pettersson, Petter Krus, Ingo Staack

 This file is provided "as is", with no guarantee or warranty for the
 functionality or reliability of the contents. All contents in this file is
 the original work of the copyright holders at the Division of Fluid and
 Mechatronic Systems (Flumes) at Linköping University. Modifying, using or
 redistributing any part of this file is prohibited without explicit
 permission from the copyright holders.
-----------------------------------------------------------------------------*/

//!
//! @file   GUIPortAppearance.cpp
//! @author Flumes <flumes@lists.iei.liu.se>
//! @date   2010-01-01
//!
//! @brief Contains the GUIPortAppearance class
//!
//$Id$

#include "MainWindow.h"
#include "GUIPortAppearance.h"
#include "common.h"

PortAppearance::PortAppearance()
{
    //Default values
    mVisible = true;
}

//! @brief Contains hardcoded appearance for different hopsancore ports
//! @todo maybe this should be placed in som more generic external .txt file in som way
void PortAppearance::selectPortIcon(QString CQSType, QString porttype, QString nodetype)
{
    mMainIconPath.clear();

    mMainIconPath = QString(PORTICONPATH);
    if (nodetype == "NodeSignal")
    {
        mMainIconPath.append("SignalPort");
        if ( porttype == "READPORT" || porttype == "READMULTIPORT")
        {
            mMainIconPath.append("_read");
        }
        else
        {
            mMainIconPath.append("_write");
        }
        mCQSOverlayPath.clear();
    }
    else
    {
        if (nodetype == "NodeMechanic")
        {
            mMainIconPath.append("MechanicPort");
        }
        else if (nodetype == "NodeMechanicRotational")
        {
            mMainIconPath.append("RotationalMechanicPort");
        }
        else if (nodetype == "NodeHydraulic")
        {
            mMainIconPath.append("HydraulicPort");
        }
        else if (nodetype == "NodeElectric")
        {
            mMainIconPath.append("ElectricPort");
        }
        else
        {
            //SystemPort is a blank port (that is why we use it here)
            mMainIconPath.append("SystemPort");
        }

        //Select cqs overlay icon path depending on cqs type
        if (CQSType == "C")
        {
            mCQSOverlayPath = (QString(PORTICONPATH) + "PortOverlayC.svg");
        }
        else if (CQSType == "Q")
        {
            mCQSOverlayPath = (QString(PORTICONPATH) + "PortOverlayQ.svg");
        }
        else if (CQSType == "UNDEFINEDCQSTYPE")
        {
            mCQSOverlayPath = (QString(PORTICONPATH) + "PortOverlayUnknown.svg");
        }
        else
        {
            mCQSOverlayPath.clear();
        }
    }
    mMainIconPath.append(".svg");

    //Check if we need to add multiport overlay
    if (porttype.contains("MULTIPORT"))
    {
        mMultiPortOverlayPath = (QString(PORTICONPATH) + "MultiPortOverlay.svg");
    }
    else
    {
        mMultiPortOverlayPath.clear();
    }
}

<commit_msg>NodePneumatic added<commit_after>/*-----------------------------------------------------------------------------
 This source file is part of Hopsan NG

 Copyright (c) 2011
    Mikael Axin, Robert Braun, Alessandro Dell'Amico, Björn Eriksson,
    Peter Nordin, Karl Pettersson, Petter Krus, Ingo Staack

 This file is provided "as is", with no guarantee or warranty for the
 functionality or reliability of the contents. All contents in this file is
 the original work of the copyright holders at the Division of Fluid and
 Mechatronic Systems (Flumes) at Linköping University. Modifying, using or
 redistributing any part of this file is prohibited without explicit
 permission from the copyright holders.
-----------------------------------------------------------------------------*/

//!
//! @file   GUIPortAppearance.cpp
//! @author Flumes <flumes@lists.iei.liu.se>
//! @date   2010-01-01
//!
//! @brief Contains the GUIPortAppearance class
//!
//$Id$

#include "MainWindow.h"
#include "GUIPortAppearance.h"
#include "common.h"

PortAppearance::PortAppearance()
{
    //Default values
    mVisible = true;
}

//! @brief Contains hardcoded appearance for different hopsancore ports
//! @todo maybe this should be placed in som more generic external .txt file in som way
void PortAppearance::selectPortIcon(QString CQSType, QString porttype, QString nodetype)
{
    mMainIconPath.clear();

    mMainIconPath = QString(PORTICONPATH);
    if (nodetype == "NodeSignal")
    {
        mMainIconPath.append("SignalPort");
        if ( porttype == "READPORT" || porttype == "READMULTIPORT")
        {
            mMainIconPath.append("_read");
        }
        else
        {
            mMainIconPath.append("_write");
        }
        mCQSOverlayPath.clear();
    }
    else
    {
        if (nodetype == "NodeMechanic")
        {
            mMainIconPath.append("MechanicPort");
        }
        else if (nodetype == "NodeMechanicRotational")
        {
            mMainIconPath.append("RotationalMechanicPort");
        }
        else if (nodetype == "NodeHydraulic")
        {
            mMainIconPath.append("HydraulicPort");
        }
        else if (nodetype == "NodePneumatic")
        {
                mMainIconPath.append("PneumaticPort");
        }
        else if (nodetype == "NodeElectric")
        {
            mMainIconPath.append("ElectricPort");
        }
        else
        {
            //SystemPort is a blank port (that is why we use it here)
            mMainIconPath.append("SystemPort");
        }

        //Select cqs overlay icon path depending on cqs type
        if (CQSType == "C")
        {
            mCQSOverlayPath = (QString(PORTICONPATH) + "PortOverlayC.svg");
        }
        else if (CQSType == "Q")
        {
            mCQSOverlayPath = (QString(PORTICONPATH) + "PortOverlayQ.svg");
        }
        else if (CQSType == "UNDEFINEDCQSTYPE")
        {
            mCQSOverlayPath = (QString(PORTICONPATH) + "PortOverlayUnknown.svg");
        }
        else
        {
            mCQSOverlayPath.clear();
        }
    }
    mMainIconPath.append(".svg");

    //Check if we need to add multiport overlay
    if (porttype.contains("MULTIPORT"))
    {
        mMultiPortOverlayPath = (QString(PORTICONPATH) + "MultiPortOverlay.svg");
    }
    else
    {
        mMultiPortOverlayPath.clear();
    }
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTreeDifferenceFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

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

#include "vtkTreeDifferenceFilter.h"

#include "vtkDataSetAttributes.h"
#include "vtkDoubleArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkStringArray.h"
#include "vtkTree.h"

vtkStandardNewMacro(vtkTreeDifferenceFilter);

//---------------------------------------------------------------------------
vtkTreeDifferenceFilter::vtkTreeDifferenceFilter()
{
  this->SetNumberOfInputPorts(2);
  this->SetNumberOfOutputPorts(1);

  this->IdArrayName = 0;
  this->ComparisonArrayName = 0;
  this->OutputArrayName = 0;
  this->ComparisonArrayIsVertexData = false;
}

//---------------------------------------------------------------------------
vtkTreeDifferenceFilter::~vtkTreeDifferenceFilter()
{
  // release memory
  this->SetIdArrayName(0);
  this->SetComparisonArrayName(0);
  this->SetOutputArrayName(0);
}

//---------------------------------------------------------------------------
int vtkTreeDifferenceFilter::FillInputPortInformation(int port, vtkInformation *info)
{
  if(port == 0)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree");
    }
  else if(port == 1)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree");
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
    }

  return 1;
}

//---------------------------------------------------------------------------
int vtkTreeDifferenceFilter::RequestData(
  vtkInformation*,
  vtkInformationVector** inputVector,
  vtkInformationVector* outputVector)
{
  vtkInformation* tree1_info = inputVector[0]->GetInformationObject(0);
  vtkTree* tree1 = vtkTree::SafeDownCast(
    tree1_info->Get(vtkDataObject::DATA_OBJECT()));

  // Copy the structure into the output.
  vtkTree* outputTree = vtkTree::GetData(outputVector);

  vtkInformation* tree2_info = inputVector[1]->GetInformationObject(0);
  if(!tree2_info)
    {
    // If no second tree provided, we're done
    outputTree->CheckedShallowCopy(tree1);
    return 0;
    }

  vtkTree* tree2 = vtkTree::SafeDownCast(
    tree2_info->Get(vtkDataObject::DATA_OBJECT()));

  if (this->IdArrayName != 0)
    {
    if (!this->GenerateMapping(tree1, tree2))
      {
      return 0;
      }
    }
  else
    {
    this->VertexMap.clear();
    for (vtkIdType vertex = 0; vertex < tree1->GetNumberOfVertices(); ++vertex)
      {
      this->VertexMap[vertex] = vertex;
      }

    this->EdgeMap.clear();
    for (vtkIdType edge = 0; edge < tree1->GetNumberOfEdges(); ++edge)
      {
      this->EdgeMap[edge] = edge;
      }
    }

  this->ComputeDifference(tree1, tree2);

  if (!outputTree->CheckedShallowCopy(tree1))
    {
    vtkErrorMacro(<<"Invalid tree structure.");
    return 0;
    }
  return 1;
}

//---------------------------------------------------------------------------
bool vtkTreeDifferenceFilter::GenerateMapping(vtkTree *tree1, vtkTree *tree2)
{
  this->VertexMap.clear();
  this->VertexMap.assign(tree1->GetNumberOfVertices(), -1);

  this->EdgeMap.clear();
  this->EdgeMap.assign(tree1->GetNumberOfEdges(), -1);

  vtkStringArray *nodeNames1 = vtkStringArray::SafeDownCast(
    tree1->GetVertexData()->GetAbstractArray(this->IdArrayName));
  if (nodeNames1 == NULL)
    {
    vtkErrorMacro("tree #1's VertexData does not have a vtkStringArray named "
      << this->IdArrayName);
    return false;
    }

  vtkStringArray *nodeNames2 = vtkStringArray::SafeDownCast(
    tree2->GetVertexData()->GetAbstractArray(this->IdArrayName));
  if (nodeNames2 == NULL)
    {
    vtkErrorMacro("tree #2's VertexData does not have a vtkStringArray named "
      << this->IdArrayName);
    return false;
    }

  vtkIdType root1 = tree1->GetRoot();
  vtkIdType root2 = tree2->GetRoot();

  vtkIdType edgeId1 = -1;
  vtkIdType edgeId2 = -1;

  // iterate over the vertex names for tree #1, finding the corresponding
  // vertex in tree #2.
  for (vtkIdType vertexItr = 0; vertexItr < nodeNames1->GetNumberOfTuples();
       ++vertexItr)
    {
    vtkIdType vertexId1 = vertexItr;
    std::string nodeName = nodeNames1->GetValue(vertexId1);
    if (nodeName.compare("") == 0)
      {
      continue;
      }

    // record this correspondence in the maps
    vtkIdType vertexId2 = nodeNames2->LookupValue(nodeName);
    if (vertexId2 == -1)
      {
      vtkWarningMacro("tree #2 does not contain a vertex named " << nodeName);
      continue;
      }
    this->VertexMap[vertexId1] = vertexId2;

    if (vertexId1 == root1 || vertexId2 == root2)
      {
      continue;
      }

    edgeId1 = tree1->GetEdgeId(tree1->GetParent(vertexId1), vertexId1);
    edgeId2 = tree2->GetEdgeId(tree2->GetParent(vertexId2), vertexId2);
    this->EdgeMap[edgeId1] = edgeId2;

    // descend the tree until we reach the root, mapping parent vertices to
    // each other along the way.
    while (tree1->GetParent(vertexId1) != root1 &&
           tree2->GetParent(vertexId2) != root2)
      {
      vertexId1 = tree1->GetParent(vertexId1);
      vertexId2 = tree2->GetParent(vertexId2);
      if (this->VertexMap[vertexId1] == -1)
        {
        this->VertexMap[vertexId1] = vertexId2;
        edgeId1 = tree1->GetEdgeId(tree1->GetParent(vertexId1), vertexId1);
        edgeId2 = tree2->GetEdgeId(tree2->GetParent(vertexId2), vertexId2);
        this->EdgeMap[edgeId1] = edgeId2;
        }
      }
    }

  return true;
}

//---------------------------------------------------------------------------
void vtkTreeDifferenceFilter::ComputeDifference(vtkTree *tree1, vtkTree *tree2)
{
  if (this->ComparisonArrayName == 0)
    {
    vtkErrorMacro("ComparisonArrayName has not been set.");
    return;
    }

  vtkDataSetAttributes *treeData1, *treeData2;
  const char *dataName;
  if (this->ComparisonArrayIsVertexData)
    {
    treeData1 = tree1->GetVertexData();
    treeData2 = tree2->GetVertexData();
    dataName = "VertexData";
    }
  else
    {
    treeData1 = tree1->GetEdgeData();
    treeData2 = tree2->GetEdgeData();
    dataName = "EdgeData";
    }

  vtkDoubleArray *arrayToCompare1 = vtkDoubleArray::SafeDownCast(
    treeData1->GetAbstractArray(this->ComparisonArrayName));
  if (arrayToCompare1 == NULL)
    {
    vtkErrorMacro("tree #1's " << dataName <<
      " does not have a vtkDoubleArray named " << this->IdArrayName);
    return;
    }

  vtkDoubleArray *arrayToCompare2 = vtkDoubleArray::SafeDownCast(
    treeData2->GetAbstractArray(this->ComparisonArrayName));
  if (arrayToCompare2 == NULL)
    {
    vtkErrorMacro("tree #2's " << dataName <<
      " does not have a vtkDoubleArray named " << this->IdArrayName);
    return;
    }

  vtkNew<vtkDoubleArray> resultArray;
  resultArray->SetNumberOfValues(arrayToCompare1->GetNumberOfTuples());
  resultArray->FillComponent(0, vtkMath::Nan());

  if (this->OutputArrayName == 0)
    {
    resultArray->SetName("difference");
    }
  else
    {
    resultArray->SetName(this->OutputArrayName);
    }

  vtkIdType treeId2;
  for (vtkIdType treeId1 = 0; treeId1 < arrayToCompare1->GetNumberOfTuples();
       ++treeId1)
    {
    if (this->ComparisonArrayIsVertexData)
      {
      treeId2 = this->VertexMap[treeId1];
      }
    else
      {
      treeId2 = this->EdgeMap[treeId1];
      }
    double result =
      arrayToCompare1->GetValue(treeId1) - arrayToCompare2->GetValue(treeId2);
    resultArray->SetValue(treeId1, result);
    }

  treeData1->AddArray(resultArray.GetPointer());
}

//---------------------------------------------------------------------------
void vtkTreeDifferenceFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}
<commit_msg>address Gerrit feedback<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTreeDifferenceFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

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

#include "vtkTreeDifferenceFilter.h"

#include "vtkDataSetAttributes.h"
#include "vtkDoubleArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkStringArray.h"
#include "vtkTree.h"

vtkStandardNewMacro(vtkTreeDifferenceFilter);

//---------------------------------------------------------------------------
vtkTreeDifferenceFilter::vtkTreeDifferenceFilter()
{
  this->SetNumberOfInputPorts(2);
  this->SetNumberOfOutputPorts(1);

  this->IdArrayName = 0;
  this->ComparisonArrayName = 0;
  this->OutputArrayName = 0;
  this->ComparisonArrayIsVertexData = false;
}

//---------------------------------------------------------------------------
vtkTreeDifferenceFilter::~vtkTreeDifferenceFilter()
{
  // release memory
  this->SetIdArrayName(0);
  this->SetComparisonArrayName(0);
  this->SetOutputArrayName(0);
}

//---------------------------------------------------------------------------
int vtkTreeDifferenceFilter::FillInputPortInformation(int port, vtkInformation *info)
{
  if(port == 0)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree");
    }
  else if(port == 1)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree");
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
    }

  return 1;
}

//---------------------------------------------------------------------------
int vtkTreeDifferenceFilter::RequestData(
  vtkInformation*,
  vtkInformationVector** inputVector,
  vtkInformationVector* outputVector)
{
  vtkInformation* tree1_info = inputVector[0]->GetInformationObject(0);
  vtkTree* tree1 = vtkTree::SafeDownCast(
    tree1_info->Get(vtkDataObject::DATA_OBJECT()));

  // Copy the structure into the output.
  vtkTree* outputTree = vtkTree::GetData(outputVector);

  vtkInformation* tree2_info = inputVector[1]->GetInformationObject(0);
  if(!tree2_info)
    {
    // If no second tree provided, we're done
    outputTree->CheckedShallowCopy(tree1);
    return 0;
    }

  vtkTree* tree2 = vtkTree::SafeDownCast(
    tree2_info->Get(vtkDataObject::DATA_OBJECT()));

  if (this->IdArrayName != 0)
    {
    if (!this->GenerateMapping(tree1, tree2))
      {
      return 0;
      }
    }
  else
    {
    this->VertexMap.clear();
    for (vtkIdType vertex = 0; vertex < tree1->GetNumberOfVertices(); ++vertex)
      {
      this->VertexMap[vertex] = vertex;
      }

    this->EdgeMap.clear();
    for (vtkIdType edge = 0; edge < tree1->GetNumberOfEdges(); ++edge)
      {
      this->EdgeMap[edge] = edge;
      }
    }

  this->ComputeDifference(tree1, tree2);

  if (!outputTree->CheckedShallowCopy(tree1))
    {
    vtkErrorMacro(<<"Invalid tree structure.");
    return 0;
    }
  return 1;
}

//---------------------------------------------------------------------------
bool vtkTreeDifferenceFilter::GenerateMapping(vtkTree *tree1, vtkTree *tree2)
{
  this->VertexMap.clear();
  this->VertexMap.assign(tree1->GetNumberOfVertices(), -1);

  this->EdgeMap.clear();
  this->EdgeMap.assign(tree1->GetNumberOfEdges(), -1);

  vtkStringArray *nodeNames1 = vtkStringArray::SafeDownCast(
    tree1->GetVertexData()->GetAbstractArray(this->IdArrayName));
  if (nodeNames1 == NULL)
    {
    vtkErrorMacro("tree #1's VertexData does not have a vtkStringArray named "
      << this->IdArrayName);
    return false;
    }

  vtkStringArray *nodeNames2 = vtkStringArray::SafeDownCast(
    tree2->GetVertexData()->GetAbstractArray(this->IdArrayName));
  if (nodeNames2 == NULL)
    {
    vtkErrorMacro("tree #2's VertexData does not have a vtkStringArray named "
      << this->IdArrayName);
    return false;
    }

  vtkIdType root1 = tree1->GetRoot();
  vtkIdType root2 = tree2->GetRoot();

  vtkIdType edgeId1 = -1;
  vtkIdType edgeId2 = -1;

  // iterate over the vertex names for tree #1, finding the corresponding
  // vertex in tree #2.
  for (vtkIdType vertexItr = 0; vertexItr < nodeNames1->GetNumberOfTuples();
       ++vertexItr)
    {
    vtkIdType vertexId1 = vertexItr;
    std::string nodeName = nodeNames1->GetValue(vertexId1);
    if (nodeName.compare("") == 0)
      {
      continue;
      }

    // record this correspondence in the maps
    vtkIdType vertexId2 = nodeNames2->LookupValue(nodeName);
    if (vertexId2 == -1)
      {
      vtkWarningMacro("tree #2 does not contain a vertex named " << nodeName);
      continue;
      }
    this->VertexMap[vertexId1] = vertexId2;

    if (vertexId1 == root1 || vertexId2 == root2)
      {
      continue;
      }

    edgeId1 = tree1->GetEdgeId(tree1->GetParent(vertexId1), vertexId1);
    edgeId2 = tree2->GetEdgeId(tree2->GetParent(vertexId2), vertexId2);
    this->EdgeMap[edgeId1] = edgeId2;

    // ascend the tree until we reach the root, mapping parent vertices to
    // each other along the way.
    while (tree1->GetParent(vertexId1) != root1 &&
           tree2->GetParent(vertexId2) != root2)
      {
      vertexId1 = tree1->GetParent(vertexId1);
      vertexId2 = tree2->GetParent(vertexId2);
      if (this->VertexMap[vertexId1] == -1)
        {
        this->VertexMap[vertexId1] = vertexId2;
        edgeId1 = tree1->GetEdgeId(tree1->GetParent(vertexId1), vertexId1);
        edgeId2 = tree2->GetEdgeId(tree2->GetParent(vertexId2), vertexId2);
        this->EdgeMap[edgeId1] = edgeId2;
        }
      }
    }

  return true;
}

//---------------------------------------------------------------------------
void vtkTreeDifferenceFilter::ComputeDifference(vtkTree *tree1, vtkTree *tree2)
{
  if (this->ComparisonArrayName == 0)
    {
    vtkErrorMacro("ComparisonArrayName has not been set.");
    return;
    }

  vtkDataSetAttributes *treeData1, *treeData2;
  const char *dataName;
  if (this->ComparisonArrayIsVertexData)
    {
    treeData1 = tree1->GetVertexData();
    treeData2 = tree2->GetVertexData();
    dataName = "VertexData";
    }
  else
    {
    treeData1 = tree1->GetEdgeData();
    treeData2 = tree2->GetEdgeData();
    dataName = "EdgeData";
    }

  vtkDataArray *arrayToCompare1 =
    treeData1->GetArray(this->ComparisonArrayName);
  if (arrayToCompare1 == NULL)
    {
    vtkErrorMacro("tree #1's " << dataName <<
      " does not have a vtkDoubleArray named " << this->IdArrayName);
    return;
    }

  vtkDataArray *arrayToCompare2 =
    treeData2->GetArray(this->ComparisonArrayName);
  if (arrayToCompare2 == NULL)
    {
    vtkErrorMacro("tree #2's " << dataName <<
      " does not have a vtkDoubleArray named " << this->IdArrayName);
    return;
    }

  vtkNew<vtkDoubleArray> resultArray;
  resultArray->SetNumberOfValues(arrayToCompare1->GetNumberOfTuples());
  resultArray->FillComponent(0, vtkMath::Nan());

  if (this->OutputArrayName == 0)
    {
    resultArray->SetName("difference");
    }
  else
    {
    resultArray->SetName(this->OutputArrayName);
    }

  vtkIdType treeId2;
  for (vtkIdType treeId1 = 0; treeId1 < arrayToCompare1->GetNumberOfTuples();
       ++treeId1)
    {
    if (this->ComparisonArrayIsVertexData)
      {
      treeId2 = this->VertexMap[treeId1];
      }
    else
      {
      treeId2 = this->EdgeMap[treeId1];
      }
    double result =
      arrayToCompare1->GetTuple1(treeId1) - arrayToCompare2->GetTuple1(treeId2);
    resultArray->SetValue(treeId1, result);
    }

  treeData1->AddArray(resultArray.GetPointer());
}

//---------------------------------------------------------------------------
void vtkTreeDifferenceFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "IdArrayName: " << this->IdArrayName << endl;
  os << indent << "ComparisonArrayName: " << this->ComparisonArrayName << endl;
  os << indent << "OutputArrayName: " << this->OutputArrayName << endl;
  os << indent << "ComparisonArrayIsVertexData: " << this->ComparisonArrayIsVertexData << endl;
}
<|endoftext|>


<commit_before>/*
 Print.cpp - Base class that provides print() and println()
 Copyright (c) 2008 David A. Mellis.  All right reserved.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 Modified 23 November 2006 by David A. Mellis
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Arduino.h"

#include "Print.h"

// Public Methods //////////////////////////////////////////////////////////////

/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
  size_t n = 0;
  while (size--) {
    n += write(*buffer++);
  }
  return n;
}

size_t Print::print(const __FlashStringHelper *ifsh)
{
  const char PROGMEM *p = (const char PROGMEM *)ifsh;
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}

size_t Print::print(const String &s)
{
  size_t n = 0;
  for (uint16_t i = 0; i < s.length(); i++) {
    n += write(s[i]);
  }
  return n;
}

size_t Print::print(const char str[])
{
  return write(str);
}

size_t Print::print(char c)
{
  return write(c);
}

size_t Print::print(unsigned char b, int base)
{
  return print((unsigned long) b, base);
}

size_t Print::print(int n, int base)
{
  return print((long) n, base);
}

size_t Print::print(unsigned int n, int base)
{
  return print((unsigned long) n, base);
}

size_t Print::print(long n, int base)
{
  if (base == 0) {
    return write(n);
  } else if (base == 10) {
    if (n < 0) {
      int t = print('-');
      n = -n;
      return printNumber(n, 10) + t;
    }
    return printNumber(n, 10);
  } else {
    return printNumber(n, base);
  }
}

size_t Print::print(unsigned long n, int base)
{
  if (base == 0) return write(n);
  else return printNumber(n, base);
}

size_t Print::print(double n, int digits)
{
  return printFloat(n, digits);
}

size_t Print::println(const __FlashStringHelper *ifsh)
{
  size_t n = print(ifsh);
  n += println();
  return n;
}

size_t Print::print(const Printable& x)
{
  return x.printTo(*this);
}

size_t Print::println(void)
{
  size_t n = print('\r');
  n += print('\n');
  return n;
}

size_t Print::println(const String &s)
{
  size_t n = print(s);
  n += println();
  return n;
}

size_t Print::println(const char c[])
{
  size_t n = print(c);
  n += println();
  return n;
}

size_t Print::println(char c)
{
  size_t n = print(c);
  n += println();
  return n;
}

size_t Print::println(unsigned char b, int base)
{
  size_t n = print(b, base);
  n += println();
  return n;
}

size_t Print::println(int num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(unsigned int num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(long num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(unsigned long num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(double num, int digits)
{
  size_t n = print(num, digits);
  n += println();
  return n;
}

size_t Print::println(const Printable& x)
{
  size_t n = print(x);
  n += println();
  return n;
}

// Private Methods /////////////////////////////////////////////////////////////

size_t Print::printNumber(unsigned long n, uint8_t base) {
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1];

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    unsigned long m = n;
    n /= base;
    char c = m - base * n;
    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);

  return write(str);
}

size_t Print::printFloat(double number, uint8_t digits)
{
  size_t n = 0;

  if (isnan(number)) return print("nan");
  if (isinf(number)) return print("inf");
  if (number > 4294967040.0) return print ("ovf");  // constant determined empirically
  if (number <-4294967040.0) return print ("ovf");  // constant determined empirically

  // Handle negative numbers
  if (number < 0.0)
  {
     n += print('-');
     number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;

  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  n += print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0) {
    n += print(".");
  }

  // Extract digits from the remainder one at a time
  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    n += print(toPrint);
    remainder -= toPrint;
  }

  return n;
}
<commit_msg>Print.print optimization. Closes #1760<commit_after>/*
 Print.cpp - Base class that provides print() and println()
 Copyright (c) 2008 David A. Mellis.  All right reserved.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 Modified 23 November 2006 by David A. Mellis
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Arduino.h"

#include "Print.h"

// Public Methods //////////////////////////////////////////////////////////////

/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
  size_t n = 0;
  while (size--) {
    n += write(*buffer++);
  }
  return n;
}

size_t Print::print(const __FlashStringHelper *ifsh)
{
  const char PROGMEM *p = (const char PROGMEM *)ifsh;
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}

size_t Print::print(const String &s)
{
  return write(reinterpret_cast<const uint8_t*>(s.c_str()), s.length());
}

size_t Print::print(const char str[])
{
  return write(str);
}

size_t Print::print(char c)
{
  return write(c);
}

size_t Print::print(unsigned char b, int base)
{
  return print((unsigned long) b, base);
}

size_t Print::print(int n, int base)
{
  return print((long) n, base);
}

size_t Print::print(unsigned int n, int base)
{
  return print((unsigned long) n, base);
}

size_t Print::print(long n, int base)
{
  if (base == 0) {
    return write(n);
  } else if (base == 10) {
    if (n < 0) {
      int t = print('-');
      n = -n;
      return printNumber(n, 10) + t;
    }
    return printNumber(n, 10);
  } else {
    return printNumber(n, base);
  }
}

size_t Print::print(unsigned long n, int base)
{
  if (base == 0) return write(n);
  else return printNumber(n, base);
}

size_t Print::print(double n, int digits)
{
  return printFloat(n, digits);
}

size_t Print::println(const __FlashStringHelper *ifsh)
{
  size_t n = print(ifsh);
  n += println();
  return n;
}

size_t Print::print(const Printable& x)
{
  return x.printTo(*this);
}

size_t Print::println(void)
{
  size_t n = print('\r');
  n += print('\n');
  return n;
}

size_t Print::println(const String &s)
{
  size_t n = print(s);
  n += println();
  return n;
}

size_t Print::println(const char c[])
{
  size_t n = print(c);
  n += println();
  return n;
}

size_t Print::println(char c)
{
  size_t n = print(c);
  n += println();
  return n;
}

size_t Print::println(unsigned char b, int base)
{
  size_t n = print(b, base);
  n += println();
  return n;
}

size_t Print::println(int num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(unsigned int num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(long num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(unsigned long num, int base)
{
  size_t n = print(num, base);
  n += println();
  return n;
}

size_t Print::println(double num, int digits)
{
  size_t n = print(num, digits);
  n += println();
  return n;
}

size_t Print::println(const Printable& x)
{
  size_t n = print(x);
  n += println();
  return n;
}

// Private Methods /////////////////////////////////////////////////////////////

size_t Print::printNumber(unsigned long n, uint8_t base) {
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1];

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    unsigned long m = n;
    n /= base;
    char c = m - base * n;
    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);

  return write(str);
}

size_t Print::printFloat(double number, uint8_t digits)
{
  size_t n = 0;

  if (isnan(number)) return print("nan");
  if (isinf(number)) return print("inf");
  if (number > 4294967040.0) return print ("ovf");  // constant determined empirically
  if (number <-4294967040.0) return print ("ovf");  // constant determined empirically

  // Handle negative numbers
  if (number < 0.0)
  {
     n += print('-');
     number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;

  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  n += print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0) {
    n += print(".");
  }

  // Extract digits from the remainder one at a time
  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    n += print(toPrint);
    remainder -= toPrint;
  }

  return n;
}
<|endoftext|>