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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    ImageRegistration11.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.

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

// Software Guide : BeginLatex
//
// This example illustrates how to combine the MutualInformation metric with an
// Evolutionary algorithm for optimization.  Evolutionary algorithms are
// naturally well-suited for optimizing the Mutual Information metric given its
// randomic and noisy behavior.
//
// The structure of the example is almost identical o the one illustrated in
// ImageRegistration4. Therefore we will focus here on the setup that is
// specifically required for the evolutionary optimizer.
//
//
// \index{itk::ImageRegistrationMethod!Multi-Modality}
// \index{itk::OnePlusOneEvolutionaryOptimizer!Multi-Modality}
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkImageRegistrationMethod.h"
#include "itkTranslationTransform.h"
#include "itkMattesMutualInformationImageToImageMetric.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkOnePlusOneEvolutionaryOptimizer.h"
#include "itkNormalVariateGenerator.h"
#include "itkImage.h"
// Software Guide : EndCodeSnippet

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkResampleImageFilter.h"
#include "itkCastImageFilter.h"

//  The following section of code implements a Command observer
//  used to monitor the evolution of the registration process.
//
#include "itkCommand.h"
class CommandIterationUpdate : public itk::Command
{
public:
  typedef  CommandIterationUpdate   Self;
  typedef  itk::Command             Superclass;
  typedef itk::SmartPointer<Self>  Pointer;
  itkNewMacro( Self );
protected:
  CommandIterationUpdate() { m_LastMetricValue = 0.0; };
public:
  typedef itk::OnePlusOneEvolutionaryOptimizer     OptimizerType;
  typedef   const OptimizerType   *    OptimizerPointer;

  void Execute(itk::Object *caller, const itk::EventObject & event)
    {
      Execute( (const itk::Object *)caller, event);
    }

  void Execute(const itk::Object * object, const itk::EventObject & event)
    {
      OptimizerPointer optimizer =
        dynamic_cast< OptimizerPointer >( object );
      if( typeid( event ) != typeid( itk::IterationEvent ) )
        {
        return;
        }
      double currentValue = optimizer->GetValue();
      // Only print out when the Metric value changes
      if( fabs( m_LastMetricValue - currentValue ) > 1e-7 )
        {
        std::cout << optimizer->GetCurrentIteration() << "   ";
        std::cout << currentValue << "   ";
        std::cout << optimizer->GetCurrentPosition() << std::endl;
        m_LastMetricValue = currentValue;
        }
    }
private:
  double m_LastMetricValue;
};

int main( int argc, char *argv[] )
{
  if( argc < 3 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " fixedImageFile  movingImageFile ";
    std::cerr << "outputImagefile [differenceImage]" << std::endl;
    return 1;
    }

  const    unsigned int    Dimension = 2;
  typedef  unsigned short  PixelType;

  typedef itk::Image< PixelType, Dimension >  FixedImageType;
  typedef itk::Image< PixelType, Dimension >  MovingImageType;

  typedef itk::TranslationTransform< double, Dimension > TransformType;
  typedef itk::OnePlusOneEvolutionaryOptimizer       OptimizerType;
  typedef itk::LinearInterpolateImageFunction<
                                    MovingImageType,
                                    double             > InterpolatorType;
  typedef itk::ImageRegistrationMethod<
                                    FixedImageType,
                                    MovingImageType    > RegistrationType;

  //  Software Guide : BeginLatex
  //
  //  In this example the image types and all registration components,
  //  except the metric, are declared as in Section
  //  \ref{sec:IntroductionImageRegistration}.
  //  The Mattes mutual information metric type is
  //  instantiated using the image types.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::MattesMutualInformationImageToImageMetric<
                                          FixedImageType,
                                          MovingImageType >    MetricType;
  // Software Guide : EndCodeSnippet

  TransformType::Pointer      transform     = TransformType::New();
  OptimizerType::Pointer      optimizer     = OptimizerType::New();
  InterpolatorType::Pointer   interpolator  = InterpolatorType::New();
  RegistrationType::Pointer   registration  = RegistrationType::New();

  registration->SetOptimizer(     optimizer     );
  registration->SetTransform(     transform     );
  registration->SetInterpolator(  interpolator  );

  MetricType::Pointer metric = MetricType::New();
  registration->SetMetric( metric  );

  metric->SetNumberOfHistogramBins( 20 );
  metric->SetNumberOfSpatialSamples( 10000 );

  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;

  FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
  MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();

  fixedImageReader->SetFileName(  argv[1] );
  movingImageReader->SetFileName( argv[2] );

  registration->SetFixedImage(    fixedImageReader->GetOutput()    );
  registration->SetMovingImage(   movingImageReader->GetOutput()   );

  fixedImageReader->Update();

  registration->SetFixedImageRegion(
       fixedImageReader->GetOutput()->GetBufferedRegion() );

  typedef RegistrationType::ParametersType ParametersType;
  ParametersType initialParameters( transform->GetNumberOfParameters() );

  initialParameters[0] = 0.0;  // Initial offset in mm along X
  initialParameters[1] = 0.0;  // Initial offset in mm along Y

  registration->SetInitialTransformParameters( initialParameters );

  //  Software Guide : BeginLatex
  //
  //  Evolutionary algorithms are based on testing random variations
  //  of parameters. In order to support the computation of random values,
  //  ITK provides a family of random number generators. In this example, we
  //  use the \doxygen{NormalVariateGenerator} which generates values with a
  //  normal distribution.
  //
  //  \index{itk::NormalVariateGenerator!New()}
  //  \index{itk::NormalVariateGenerator!Pointer}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::Statistics::NormalVariateGenerator  GeneratorType;

  GeneratorType::Pointer generator = GeneratorType::New();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The random number generator must be initialized with a seed.
  //
  //  \index{itk::NormalVariateGenerator!Initialize()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  generator->Initialize(12345);
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Another significant difference in the metric is that it
  //  computes the negative mutual information and hence we
  //  need to minimize the cost function in this case. In this
  //  example we will use the same optimization parameters as in
  //  Section \ref{sec:IntroductionImageRegistration}.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  optimizer->MaximizeOn();

  optimizer->SetNormalVariateGenerator( generator );
  optimizer->Initialize( 10 );
  optimizer->SetEpsilon( 1.0 );
  optimizer->SetMaximumIteration( 4000 );
  // Software Guide : EndCodeSnippet

  // Create the Command observer and register it with the optimizer.
  //
  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
  optimizer->AddObserver( itk::IterationEvent(), observer );

  try
    {
    registration->StartRegistration();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "ExceptionObject caught !" << std::endl;
    std::cout << err << std::endl;
    return -1;
    }

  ParametersType finalParameters = registration->GetLastTransformParameters();

  double TranslationAlongX = finalParameters[0];
  double TranslationAlongY = finalParameters[1];

  unsigned int numberOfIterations = optimizer->GetCurrentIteration();

  double bestValue = optimizer->GetValue();

  // Print out results
  //
  std::cout << "Result = " << std::endl;
  std::cout << " Translation X = " << TranslationAlongX  << std::endl;
  std::cout << " Translation Y = " << TranslationAlongY  << std::endl;
  std::cout << " Iterations    = " << numberOfIterations << std::endl;
  std::cout << " Metric value  = " << bestValue          << std::endl;

  //  Software Guide : BeginLatex
  //
  //  This example is executed using the same multi-modality images as
  //  in the previous one.  The registration converges after $24$ iterations and produces
  //  the following results:
  //
  //  \begin{verbatim}
  //  Translation X = 13.1719
  //  Translation Y = 16.9006
  //  \end{verbatim}
  //  These values are a very close match to
  //  the true misaligment introduced in the moving image.
  //
  //  Software Guide : EndLatex

  typedef itk::ResampleImageFilter<
                            MovingImageType,
                            FixedImageType >    ResampleFilterType;

  TransformType::Pointer finalTransform = TransformType::New();

  finalTransform->SetParameters( finalParameters );

  ResampleFilterType::Pointer resample = ResampleFilterType::New();

  resample->SetTransform( finalTransform );
  resample->SetInput( movingImageReader->GetOutput() );

  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();

  resample->SetSize(    fixedImage->GetLargestPossibleRegion().GetSize() );
  resample->SetOutputOrigin(  fixedImage->GetOrigin() );
  resample->SetOutputSpacing( fixedImage->GetSpacing() );
  resample->SetDefaultPixelValue( 100 );

  typedef  unsigned char  OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::CastImageFilter<
                        FixedImageType,
                        OutputImageType > CastFilterType;
  typedef itk::ImageFileWriter< OutputImageType >  WriterType;

  WriterType::Pointer      writer =  WriterType::New();
  CastFilterType::Pointer  caster =  CastFilterType::New();

  writer->SetFileName( argv[3] );

  caster->SetInput( resample->GetOutput() );
  writer->SetInput( caster->GetOutput()   );
  writer->Update();

  return 0;
}

<commit_msg>FIX: MattesMI is optimal for a minimal value. The optimizer should be set      to MaximizeOff().<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    ImageRegistration11.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.

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

// Software Guide : BeginLatex
//
// This example illustrates how to combine the MutualInformation metric with an
// Evolutionary algorithm for optimization.  Evolutionary algorithms are
// naturally well-suited for optimizing the Mutual Information metric given its
// randomic and noisy behavior.
//
// The structure of the example is almost identical o the one illustrated in
// ImageRegistration4. Therefore we will focus here on the setup that is
// specifically required for the evolutionary optimizer.
//
//
// \index{itk::ImageRegistrationMethod!Multi-Modality}
// \index{itk::OnePlusOneEvolutionaryOptimizer!Multi-Modality}
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkImageRegistrationMethod.h"
#include "itkTranslationTransform.h"
#include "itkMattesMutualInformationImageToImageMetric.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkOnePlusOneEvolutionaryOptimizer.h"
#include "itkNormalVariateGenerator.h"
#include "itkImage.h"
// Software Guide : EndCodeSnippet

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkResampleImageFilter.h"
#include "itkCastImageFilter.h"

//  The following section of code implements a Command observer
//  used to monitor the evolution of the registration process.
//
#include "itkCommand.h"
class CommandIterationUpdate : public itk::Command
{
public:
  typedef  CommandIterationUpdate   Self;
  typedef  itk::Command             Superclass;
  typedef itk::SmartPointer<Self>  Pointer;
  itkNewMacro( Self );
protected:
  CommandIterationUpdate() { m_LastMetricValue = 0.0; };
public:
  typedef itk::OnePlusOneEvolutionaryOptimizer     OptimizerType;
  typedef   const OptimizerType   *    OptimizerPointer;

  void Execute(itk::Object *caller, const itk::EventObject & event)
    {
      Execute( (const itk::Object *)caller, event);
    }

  void Execute(const itk::Object * object, const itk::EventObject & event)
    {
      OptimizerPointer optimizer =
        dynamic_cast< OptimizerPointer >( object );
      if( typeid( event ) != typeid( itk::IterationEvent ) )
        {
        return;
        }
      double currentValue = optimizer->GetValue();
      // Only print out when the Metric value changes
      if( fabs( m_LastMetricValue - currentValue ) > 1e-7 )
        {
        std::cout << optimizer->GetCurrentIteration() << "   ";
        std::cout << currentValue << "   ";
        std::cout << optimizer->GetCurrentPosition() << std::endl;
        m_LastMetricValue = currentValue;
        }
    }
private:
  double m_LastMetricValue;
};

int main( int argc, char *argv[] )
{
  if( argc < 3 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " fixedImageFile  movingImageFile ";
    std::cerr << "outputImagefile [differenceImage]" << std::endl;
    return 1;
    }

  const    unsigned int    Dimension = 2;
  typedef  unsigned short  PixelType;

  typedef itk::Image< PixelType, Dimension >  FixedImageType;
  typedef itk::Image< PixelType, Dimension >  MovingImageType;

  typedef itk::TranslationTransform< double, Dimension > TransformType;
  typedef itk::OnePlusOneEvolutionaryOptimizer       OptimizerType;
  typedef itk::LinearInterpolateImageFunction<
                                    MovingImageType,
                                    double             > InterpolatorType;
  typedef itk::ImageRegistrationMethod<
                                    FixedImageType,
                                    MovingImageType    > RegistrationType;

  //  Software Guide : BeginLatex
  //
  //  In this example the image types and all registration components,
  //  except the metric, are declared as in Section
  //  \ref{sec:IntroductionImageRegistration}.
  //  The Mattes mutual information metric type is
  //  instantiated using the image types.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::MattesMutualInformationImageToImageMetric<
                                          FixedImageType,
                                          MovingImageType >    MetricType;
  // Software Guide : EndCodeSnippet

  TransformType::Pointer      transform     = TransformType::New();
  OptimizerType::Pointer      optimizer     = OptimizerType::New();
  InterpolatorType::Pointer   interpolator  = InterpolatorType::New();
  RegistrationType::Pointer   registration  = RegistrationType::New();

  registration->SetOptimizer(     optimizer     );
  registration->SetTransform(     transform     );
  registration->SetInterpolator(  interpolator  );

  MetricType::Pointer metric = MetricType::New();
  registration->SetMetric( metric  );

  metric->SetNumberOfHistogramBins( 20 );
  metric->SetNumberOfSpatialSamples( 10000 );

  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;

  FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
  MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();

  fixedImageReader->SetFileName(  argv[1] );
  movingImageReader->SetFileName( argv[2] );

  registration->SetFixedImage(    fixedImageReader->GetOutput()    );
  registration->SetMovingImage(   movingImageReader->GetOutput()   );

  fixedImageReader->Update();

  registration->SetFixedImageRegion(
       fixedImageReader->GetOutput()->GetBufferedRegion() );

  typedef RegistrationType::ParametersType ParametersType;
  ParametersType initialParameters( transform->GetNumberOfParameters() );

  initialParameters[0] = 0.0;  // Initial offset in mm along X
  initialParameters[1] = 0.0;  // Initial offset in mm along Y

  registration->SetInitialTransformParameters( initialParameters );

  //  Software Guide : BeginLatex
  //
  //  Evolutionary algorithms are based on testing random variations
  //  of parameters. In order to support the computation of random values,
  //  ITK provides a family of random number generators. In this example, we
  //  use the \doxygen{NormalVariateGenerator} which generates values with a
  //  normal distribution.
  //
  //  \index{itk::NormalVariateGenerator!New()}
  //  \index{itk::NormalVariateGenerator!Pointer}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::Statistics::NormalVariateGenerator  GeneratorType;

  GeneratorType::Pointer generator = GeneratorType::New();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The random number generator must be initialized with a seed.
  //
  //  \index{itk::NormalVariateGenerator!Initialize()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  generator->Initialize(12345);
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Another significant difference in the metric is that it
  //  computes the negative mutual information and hence we
  //  need to minimize the cost function in this case. In this
  //  example we will use the same optimization parameters as in
  //  Section \ref{sec:IntroductionImageRegistration}.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  optimizer->MaximizeOff();

  optimizer->SetNormalVariateGenerator( generator );
  optimizer->Initialize( 10 );
  optimizer->SetEpsilon( 1.0 );
  optimizer->SetMaximumIteration( 4000 );
  // Software Guide : EndCodeSnippet

  // Create the Command observer and register it with the optimizer.
  //
  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
  optimizer->AddObserver( itk::IterationEvent(), observer );

  try
    {
    registration->StartRegistration();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "ExceptionObject caught !" << std::endl;
    std::cout << err << std::endl;
    return -1;
    }

  ParametersType finalParameters = registration->GetLastTransformParameters();

  double TranslationAlongX = finalParameters[0];
  double TranslationAlongY = finalParameters[1];

  unsigned int numberOfIterations = optimizer->GetCurrentIteration();

  double bestValue = optimizer->GetValue();

  // Print out results
  //
  std::cout << "Result = " << std::endl;
  std::cout << " Translation X = " << TranslationAlongX  << std::endl;
  std::cout << " Translation Y = " << TranslationAlongY  << std::endl;
  std::cout << " Iterations    = " << numberOfIterations << std::endl;
  std::cout << " Metric value  = " << bestValue          << std::endl;

  //  Software Guide : BeginLatex
  //
  //  This example is executed using the same multi-modality images as
  //  in the previous one.  The registration converges after $24$ iterations and produces
  //  the following results:
  //
  //  \begin{verbatim}
  //  Translation X = 13.1719
  //  Translation Y = 16.9006
  //  \end{verbatim}
  //  These values are a very close match to
  //  the true misaligment introduced in the moving image.
  //
  //  Software Guide : EndLatex

  typedef itk::ResampleImageFilter<
                            MovingImageType,
                            FixedImageType >    ResampleFilterType;

  TransformType::Pointer finalTransform = TransformType::New();

  finalTransform->SetParameters( finalParameters );

  ResampleFilterType::Pointer resample = ResampleFilterType::New();

  resample->SetTransform( finalTransform );
  resample->SetInput( movingImageReader->GetOutput() );

  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();

  resample->SetSize(    fixedImage->GetLargestPossibleRegion().GetSize() );
  resample->SetOutputOrigin(  fixedImage->GetOrigin() );
  resample->SetOutputSpacing( fixedImage->GetSpacing() );
  resample->SetDefaultPixelValue( 100 );

  typedef  unsigned char  OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::CastImageFilter<
                        FixedImageType,
                        OutputImageType > CastFilterType;
  typedef itk::ImageFileWriter< OutputImageType >  WriterType;

  WriterType::Pointer      writer =  WriterType::New();
  CastFilterType::Pointer  caster =  CastFilterType::New();

  writer->SetFileName( argv[3] );

  caster->SetInput( resample->GetOutput() );
  writer->SetInput( caster->GetOutput()   );
  writer->Update();

  return 0;
}

<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////
//
//                             Pixie
//
// Copyright  1999 - 2003, Okan Arikan
//
// Contact: okan@cs.utexas.edu
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.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 Street, Fifth Floor, Boston, MA  02110-1301  USA
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
//  File				:	file.cpp
//  Classes				:
//  Description			:	This file implements the default output device
//							that sends the image into a file
//
////////////////////////////////////////////////////////////////////////
#include "common/global.h"
#include "common/algebra.h"
#include "common/os.h"
#include "ri/dsply.h"							// The display driver interface

#include <stdlib.h>								// Ensure we have NULL defined before libtiff
#include <tiffio.h>								// Libtiff is required
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

///////////////////////////////////////////////////////////////////////
// Class				:	CRendererbuffer
// Description			:	Holds the framebuffer
// Comments				:
class	CFileFramebuffer {
public:
				///////////////////////////////////////////////////////////////////////
				// Class				:	CRendererbuffer
				// Method				:	CRendererbuffer
				// Description			:	Ctor
				// Return Value			:	-
				// Comments				:
				CFileFramebuffer(const char *name,int width,int height,int numSamples,const char *samples,TDisplayParameterFunction findParameter) {
					int			i;
					float		*tmp;
					float		worldToNDC[16];
					float		worldToCamera[16];
					char		*software;
					const char	*compression	=	NULL;

					// Open the image file
					image				=	TIFFOpen(name,"w");

					// If we could not open the file, there's nothing to do
					if (image == NULL)	return;

					// Copy the quantization data
					if ((tmp = (float *) findParameter("quantize",FLOAT_PARAMETER,4))) {
						qzero			=	tmp[0];
						qone			=	tmp[1];
						qmin			=	tmp[2];
						qmax			=	tmp[3];
					}

					// Get the gamma correction stuff (only if we're not depth)
					if (strcmp(samples,"z") != 0) {

						if ((tmp = (float *) findParameter("dither",FLOAT_PARAMETER,1))) {
							qamp			=	tmp[0];
						}

						if ((tmp = (float *) findParameter("gamma",FLOAT_PARAMETER,1))) {
							gamma			=	tmp[0];
						}

						if ((tmp = (float *) findParameter("gain",FLOAT_PARAMETER,1))) {
							gain			=	tmp[0];
						}
					} else {
						// If we're saving the z channel, we must be HDR
						qmin			=	0;
						qmax			=	0;
						qzero			=	0;
						qone			=	0;
						qamp			=	0;
						gamma			=	1;
						gain			=	1;
					}

					// Camera to world matrix
					if ((tmp = (float *) findParameter("NP",FLOAT_PARAMETER,16))) {
						int	i;

						for (i=0;i<16;i++) {
							worldToNDC[i]	=	tmp[i];
						}
					}

					// Camera to world matrix
					if ((tmp = (float *) findParameter("Nl",FLOAT_PARAMETER,16))) {
						int	i;

						for (i=0;i<16;i++) {
							worldToCamera[i]	=	tmp[i];
						}
					}

					software	=	(char *) findParameter("Software",STRING_PARAMETER,1);

					compression	=	(char *) findParameter("compression",STRING_PARAMETER,1);

					if (qmax == 0) {
						bitspersample	=	32;
						sampleformat	=	SAMPLEFORMAT_IEEEFP;
					} else if (qmax > 65535) {
						bitspersample	=	32;
						sampleformat	=	SAMPLEFORMAT_UINT;
					} else if (qmax > 255) {
						bitspersample	=	16;
						sampleformat	=	SAMPLEFORMAT_UINT;
					} else {
						bitspersample	=	8;
						sampleformat	=	SAMPLEFORMAT_UINT;
					}

					// Set the tiff fields
					TIFFSetField(image, TIFFTAG_IMAGEWIDTH,			(unsigned long) width);
					TIFFSetField(image, TIFFTAG_IMAGELENGTH,		(unsigned long) height);
					TIFFSetField(image, TIFFTAG_ORIENTATION,		ORIENTATION_TOPLEFT);
					TIFFSetField(image, TIFFTAG_PLANARCONFIG,		PLANARCONFIG_CONTIG);
					TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT,		RESUNIT_NONE);
					TIFFSetField(image, TIFFTAG_XRESOLUTION,		(float) 1.0);
					TIFFSetField(image, TIFFTAG_YRESOLUTION,		(float) 1.0);
					TIFFSetField(image, TIFFTAG_BITSPERSAMPLE,		(unsigned short) bitspersample);
					TIFFSetField(image, TIFFTAG_SAMPLEFORMAT,		(unsigned short) sampleformat);
					TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL,	(unsigned short) numSamples);
					TIFFSetField(image, TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN,	worldToNDC);
					TIFFSetField(image, TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA,	worldToCamera);

					// Compute the size of a pixel
					pixelSize	=	numSamples*bitspersample / 8;

					// The default compression is LZW
					if (compression != NULL) {
						if (strcmp(compression,"LZW") == 0) {
							TIFFSetField(image, TIFFTAG_COMPRESSION,	COMPRESSION_LZW);
						} else if (strcmp(compression,"JPEG") == 0) {
							TIFFSetField(image, TIFFTAG_COMPRESSION,	COMPRESSION_JPEG);
						} else if (strcmp(compression,"Deflate") == 0) {
							TIFFSetField(image, TIFFTAG_COMPRESSION,	COMPRESSION_DEFLATE);
						}
					}

					if (numSamples == 1)
						TIFFSetField(image, TIFFTAG_PHOTOMETRIC,	PHOTOMETRIC_MINISBLACK);
					else
						TIFFSetField(image, TIFFTAG_PHOTOMETRIC,	PHOTOMETRIC_RGB);

					if (numSamples == 4) {
						unsigned short sampleinfo = EXTRASAMPLE_ASSOCALPHA;
						TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, &sampleinfo);
					}

					if (software != NULL)	TIFFSetField(image, TIFFTAG_SOFTWARE,		software);

					lastSavedLine	=	0;
					scanlines		=	new unsigned char*[height];
					scanlineUsage	=	new int[height];

					for (i=0;i<height;i++) {
						scanlines[i]		=	NULL;
						scanlineUsage[i]	=	width;
					}

					this->width			=	width;
					this->height		=	height;
					this->numSamples	=	numSamples;

					osCreateMutex(fileMutex);
				}

				///////////////////////////////////////////////////////////////////////
				// Class				:	CRendererbuffer
				// Method				:	~CRendererbuffer
				// Description			:	Dtor
				// Return Value			:	-
				// Comments				:
				~CFileFramebuffer() {
					int	i;

					if (image != NULL)	TIFFClose(image);
					else	return;

					osDeleteMutex(fileMutex);

					for (i=0;i<height;i++) {
						if (scanlines[i] != NULL)	delete [] (unsigned char *) scanlines[i];
					}

					delete [] scanlines;
					delete [] scanlineUsage;
				}

				///////////////////////////////////////////////////////////////////////
				// Class				:	CRendererbuffer
				// Method				:	write
				// Description			:	Swrite some data to the out file
				// Return Value			:	-
				// Comments				:
	void		write(int x,int y,int w,int h,float *data) {
					int				i,j;
					int				check		=	FALSE;
					int				numChannels	=	w*h*numSamples;

					if (image == NULL)	return;

					// Apply the gamma correction if applicable
					if ((gamma != 1) || (gain != 1)) {
						float	invGamma	=	1 / gamma;

						for (i=0;i<numChannels;i++) {
							data[i]	=	powf(gain*data[i],invGamma);
						}
					}

					// Apply the quantization if applicable
					if (qmax > 0) {
						for (i=0;i<numChannels;i++) {
							float	dither	=	qamp*(2*(rand() / (float) RAND_MAX)-1);
							data[i]			=	qzero + (qone - qzero)*data[i] + dither;
							if (data[i] < qmin)			data[i]	=	qmin;
							else if (data[i] > qmax)	data[i]	=	qmax;
						}
					}

					// Lock the file
					osLock(fileMutex);

					// Record the data
					for (i=0;i<h;i++) {
						unsigned char	*scan;

						if (scanlines[i+y] == NULL) {
							scanlines[i+y]	=	scan	=	new unsigned char[width*pixelSize];
						} else {
							scan			=	(unsigned char *) scanlines[i+y];
						}

						switch(bitspersample) {
						case 8:
							{
								const float		*src	=	&data[i*w*numSamples];
								unsigned char	*dest	=	&((unsigned char *) scan)[x*numSamples];

								for (j=0;j<w*numSamples;j++) {
									*dest++		=	(unsigned char) *src++;
								}
							}
							break;
						case 16:
							{
								const float		*src	=	&data[i*w*numSamples];
								unsigned short	*dest	=	&((unsigned short *) scan)[x*numSamples];

								for (j=0;j<w*numSamples;j++) {
									*dest++		=	(unsigned short) *src++;
								}
							}
							break;
						case 32:
							if (sampleformat == SAMPLEFORMAT_IEEEFP) {
								const float	*src	=	&data[i*w*numSamples];
								float		*dest	=	&((float *) scan)[x*numSamples];

								for (j=0;j<w*numSamples;j++) {
									*dest++		=	*src++;
								}
							} else {
								const float		*src	=	&data[i*w*numSamples];
								unsigned int	*dest	=	&((unsigned int *) scan)[x*numSamples];

								for (j=0;j<w*numSamples;j++) {
									*dest++		=	(unsigned int) *src++;
								}
							}
							break;
						default:
							break;
						}

						scanlineUsage[i+y]	-=	w;
						if (scanlineUsage[i+y] <= 0)	check	=	TRUE;
					}

					if (check) {
						for (;lastSavedLine<height;lastSavedLine++) {
							if (scanlineUsage[lastSavedLine] == 0) {
								if (scanlines[lastSavedLine] != NULL) {
									TIFFWriteScanline(image,scanlines[lastSavedLine],lastSavedLine,0);
									delete [] scanlines[lastSavedLine];
									scanlines[lastSavedLine]	=	NULL;
								}
							} else {
								break;
							}
						}
					}

					// Release the file
					osUnlock(fileMutex);
				}

	unsigned char	**scanlines;
	int				*scanlineUsage;
	int				width,height;
	TIFF			*image;
	int				pixelSize;
	int				numSamples;
	int				lastSavedLine;
	TMutex			fileMutex;

	float			qmin,qmax,qone,qzero,qamp;
	float			gamma,gain;
	int				bitspersample,sampleformat;
};

///////////////////////////////////////////////////////////////////////
// Function				:	displayStart
// Description			:	Begin receiving an image
// Return Value			:	The handle to the image on success, NULL othervise
// Comments				:
void	*displayStart(const char *name,int width,int height,int numSamples,const char *samples,TDisplayParameterFunction findParameter) {
	CFileFramebuffer	*fb	=	new CFileFramebuffer(name,width,height,numSamples,samples,findParameter);

	if (fb->image == NULL) {	// If we could not open the image, return NULL
		delete fb;
		return NULL;
	}

	return fb;
}

///////////////////////////////////////////////////////////////////////
// Function				:	displayData
// Description			:	Receive image data
// Return Value			:	TRUE on success, FALSE otherwise
// Comments				:
int		displayData(void *im,int x,int y,int w,int h,float *data) {
	CFileFramebuffer	*fb	=	(CFileFramebuffer *) im;

	assert(fb != NULL);

	fb->write(x,y,w,h,data);

	return TRUE;
}

///////////////////////////////////////////////////////////////////////
// Function				:	displayFinish
// Description			:	Finish receiving an image
// Return Value			:	TRUE on success, FALSE othervise
// Comments				:
void	displayFinish(void *im) {
	CFileFramebuffer	*fb	=	(CFileFramebuffer *) im;

	assert(fb != NULL);

	delete fb;
}

<commit_msg>cleanup quantize for depth<commit_after>//////////////////////////////////////////////////////////////////////
//
//                             Pixie
//
// Copyright  1999 - 2003, Okan Arikan
//
// Contact: okan@cs.utexas.edu
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.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 Street, Fifth Floor, Boston, MA  02110-1301  USA
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
//  File				:	file.cpp
//  Classes				:
//  Description			:	This file implements the default output device
//							that sends the image into a file
//
////////////////////////////////////////////////////////////////////////
#include "common/global.h"
#include "common/algebra.h"
#include "common/os.h"
#include "ri/dsply.h"							// The display driver interface

#include <stdlib.h>								// Ensure we have NULL defined before libtiff
#include <tiffio.h>								// Libtiff is required
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

///////////////////////////////////////////////////////////////////////
// Class				:	CRendererbuffer
// Description			:	Holds the framebuffer
// Comments				:
class	CFileFramebuffer {
public:
				///////////////////////////////////////////////////////////////////////
				// Class				:	CRendererbuffer
				// Method				:	CRendererbuffer
				// Description			:	Ctor
				// Return Value			:	-
				// Comments				:
				CFileFramebuffer(const char *name,int width,int height,int numSamples,const char *samples,TDisplayParameterFunction findParameter) {
					int			i;
					float		*tmp;
					float		worldToNDC[16];
					float		worldToCamera[16];
					char		*software;
					const char	*compression	=	NULL;

					// Open the image file
					image				=	TIFFOpen(name,"w");

					// If we could not open the file, there's nothing to do
					if (image == NULL)	return;

					// Copy the quantization data
					if ((tmp = (float *) findParameter("quantize",FLOAT_PARAMETER,4))) {
						qzero			=	tmp[0];
						qone			=	tmp[1];
						qmin			=	tmp[2];
						qmax			=	tmp[3];
					}

					// Get the gamma correction stuff (only if we're not depth)
					if (strcmp(samples,"z") != 0) {

						if ((tmp = (float *) findParameter("dither",FLOAT_PARAMETER,1))) {
							qamp			=	tmp[0];
						}

						if ((tmp = (float *) findParameter("gamma",FLOAT_PARAMETER,1))) {
							gamma			=	tmp[0];
						}

						if ((tmp = (float *) findParameter("gain",FLOAT_PARAMETER,1))) {
							gain			=	tmp[0];
						}
					} else {
						// If we're saving the z channel, we must be HDR
						qamp			=	0;
						gamma			=	1;
						gain			=	1;
					}

					// Camera to world matrix
					if ((tmp = (float *) findParameter("NP",FLOAT_PARAMETER,16))) {
						int	i;

						for (i=0;i<16;i++) {
							worldToNDC[i]	=	tmp[i];
						}
					}

					// Camera to world matrix
					if ((tmp = (float *) findParameter("Nl",FLOAT_PARAMETER,16))) {
						int	i;

						for (i=0;i<16;i++) {
							worldToCamera[i]	=	tmp[i];
						}
					}

					software	=	(char *) findParameter("Software",STRING_PARAMETER,1);

					compression	=	(char *) findParameter("compression",STRING_PARAMETER,1);

					if (qmax == 0) {
						bitspersample	=	32;
						sampleformat	=	SAMPLEFORMAT_IEEEFP;
					} else if (qmax > 65535) {
						bitspersample	=	32;
						sampleformat	=	SAMPLEFORMAT_UINT;
					} else if (qmax > 255) {
						bitspersample	=	16;
						sampleformat	=	SAMPLEFORMAT_UINT;
					} else {
						bitspersample	=	8;
						sampleformat	=	SAMPLEFORMAT_UINT;
					}

					// Set the tiff fields
					TIFFSetField(image, TIFFTAG_IMAGEWIDTH,			(unsigned long) width);
					TIFFSetField(image, TIFFTAG_IMAGELENGTH,		(unsigned long) height);
					TIFFSetField(image, TIFFTAG_ORIENTATION,		ORIENTATION_TOPLEFT);
					TIFFSetField(image, TIFFTAG_PLANARCONFIG,		PLANARCONFIG_CONTIG);
					TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT,		RESUNIT_NONE);
					TIFFSetField(image, TIFFTAG_XRESOLUTION,		(float) 1.0);
					TIFFSetField(image, TIFFTAG_YRESOLUTION,		(float) 1.0);
					TIFFSetField(image, TIFFTAG_BITSPERSAMPLE,		(unsigned short) bitspersample);
					TIFFSetField(image, TIFFTAG_SAMPLEFORMAT,		(unsigned short) sampleformat);
					TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL,	(unsigned short) numSamples);
					TIFFSetField(image, TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN,	worldToNDC);
					TIFFSetField(image, TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA,	worldToCamera);

					// Compute the size of a pixel
					pixelSize	=	numSamples*bitspersample / 8;

					// The default compression is LZW
					if (compression != NULL) {
						if (strcmp(compression,"LZW") == 0) {
							TIFFSetField(image, TIFFTAG_COMPRESSION,	COMPRESSION_LZW);
						} else if (strcmp(compression,"JPEG") == 0) {
							TIFFSetField(image, TIFFTAG_COMPRESSION,	COMPRESSION_JPEG);
						} else if (strcmp(compression,"Deflate") == 0) {
							TIFFSetField(image, TIFFTAG_COMPRESSION,	COMPRESSION_DEFLATE);
						}
					}

					if (numSamples == 1)
						TIFFSetField(image, TIFFTAG_PHOTOMETRIC,	PHOTOMETRIC_MINISBLACK);
					else
						TIFFSetField(image, TIFFTAG_PHOTOMETRIC,	PHOTOMETRIC_RGB);

					if (numSamples == 4) {
						unsigned short sampleinfo = EXTRASAMPLE_ASSOCALPHA;
						TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, &sampleinfo);
					}

					if (software != NULL)	TIFFSetField(image, TIFFTAG_SOFTWARE,		software);

					lastSavedLine	=	0;
					scanlines		=	new unsigned char*[height];
					scanlineUsage	=	new int[height];

					for (i=0;i<height;i++) {
						scanlines[i]		=	NULL;
						scanlineUsage[i]	=	width;
					}

					this->width			=	width;
					this->height		=	height;
					this->numSamples	=	numSamples;

					osCreateMutex(fileMutex);
				}

				///////////////////////////////////////////////////////////////////////
				// Class				:	CRendererbuffer
				// Method				:	~CRendererbuffer
				// Description			:	Dtor
				// Return Value			:	-
				// Comments				:
				~CFileFramebuffer() {
					int	i;

					if (image != NULL)	TIFFClose(image);
					else	return;

					osDeleteMutex(fileMutex);

					for (i=0;i<height;i++) {
						if (scanlines[i] != NULL)	delete [] (unsigned char *) scanlines[i];
					}

					delete [] scanlines;
					delete [] scanlineUsage;
				}

				///////////////////////////////////////////////////////////////////////
				// Class				:	CRendererbuffer
				// Method				:	write
				// Description			:	Swrite some data to the out file
				// Return Value			:	-
				// Comments				:
	void		write(int x,int y,int w,int h,float *data) {
					int				i,j;
					int				check		=	FALSE;
					int				numChannels	=	w*h*numSamples;

					if (image == NULL)	return;

					// Apply the gamma correction if applicable
					if ((gamma != 1) || (gain != 1)) {
						float	invGamma	=	1 / gamma;

						for (i=0;i<numChannels;i++) {
							data[i]	=	powf(gain*data[i],invGamma);
						}
					}

					// Apply the quantization if applicable
					if (qmax > 0) {
						for (i=0;i<numChannels;i++) {
							float	dither	=	qamp*(2*(rand() / (float) RAND_MAX)-1);
							data[i]			=	qzero + (qone - qzero)*data[i] + dither;
							if (data[i] < qmin)			data[i]	=	qmin;
							else if (data[i] > qmax)	data[i]	=	qmax;
						}
					}

					// Lock the file
					osLock(fileMutex);

					// Record the data
					for (i=0;i<h;i++) {
						unsigned char	*scan;

						if (scanlines[i+y] == NULL) {
							scanlines[i+y]	=	scan	=	new unsigned char[width*pixelSize];
						} else {
							scan			=	(unsigned char *) scanlines[i+y];
						}

						switch(bitspersample) {
						case 8:
							{
								const float		*src	=	&data[i*w*numSamples];
								unsigned char	*dest	=	&((unsigned char *) scan)[x*numSamples];

								for (j=0;j<w*numSamples;j++) {
									*dest++		=	(unsigned char) *src++;
								}
							}
							break;
						case 16:
							{
								const float		*src	=	&data[i*w*numSamples];
								unsigned short	*dest	=	&((unsigned short *) scan)[x*numSamples];

								for (j=0;j<w*numSamples;j++) {
									*dest++		=	(unsigned short) *src++;
								}
							}
							break;
						case 32:
							if (sampleformat == SAMPLEFORMAT_IEEEFP) {
								const float	*src	=	&data[i*w*numSamples];
								float		*dest	=	&((float *) scan)[x*numSamples];

								for (j=0;j<w*numSamples;j++) {
									*dest++		=	*src++;
								}
							} else {
								const float		*src	=	&data[i*w*numSamples];
								unsigned int	*dest	=	&((unsigned int *) scan)[x*numSamples];

								for (j=0;j<w*numSamples;j++) {
									*dest++		=	(unsigned int) *src++;
								}
							}
							break;
						default:
							break;
						}

						scanlineUsage[i+y]	-=	w;
						if (scanlineUsage[i+y] <= 0)	check	=	TRUE;
					}

					if (check) {
						for (;lastSavedLine<height;lastSavedLine++) {
							if (scanlineUsage[lastSavedLine] == 0) {
								if (scanlines[lastSavedLine] != NULL) {
									TIFFWriteScanline(image,scanlines[lastSavedLine],lastSavedLine,0);
									delete [] scanlines[lastSavedLine];
									scanlines[lastSavedLine]	=	NULL;
								}
							} else {
								break;
							}
						}
					}

					// Release the file
					osUnlock(fileMutex);
				}

	unsigned char	**scanlines;
	int				*scanlineUsage;
	int				width,height;
	TIFF			*image;
	int				pixelSize;
	int				numSamples;
	int				lastSavedLine;
	TMutex			fileMutex;

	float			qmin,qmax,qone,qzero,qamp;
	float			gamma,gain;
	int				bitspersample,sampleformat;
};

///////////////////////////////////////////////////////////////////////
// Function				:	displayStart
// Description			:	Begin receiving an image
// Return Value			:	The handle to the image on success, NULL othervise
// Comments				:
void	*displayStart(const char *name,int width,int height,int numSamples,const char *samples,TDisplayParameterFunction findParameter) {
	CFileFramebuffer	*fb	=	new CFileFramebuffer(name,width,height,numSamples,samples,findParameter);

	if (fb->image == NULL) {	// If we could not open the image, return NULL
		delete fb;
		return NULL;
	}

	return fb;
}

///////////////////////////////////////////////////////////////////////
// Function				:	displayData
// Description			:	Receive image data
// Return Value			:	TRUE on success, FALSE otherwise
// Comments				:
int		displayData(void *im,int x,int y,int w,int h,float *data) {
	CFileFramebuffer	*fb	=	(CFileFramebuffer *) im;

	assert(fb != NULL);

	fb->write(x,y,w,h,data);

	return TRUE;
}

///////////////////////////////////////////////////////////////////////
// Function				:	displayFinish
// Description			:	Finish receiving an image
// Return Value			:	TRUE on success, FALSE othervise
// Comments				:
void	displayFinish(void *im) {
	CFileFramebuffer	*fb	=	(CFileFramebuffer *) im;

	assert(fb != NULL);

	delete fb;
}

<|endoftext|>


<commit_before>#include <UnitTest++/src/UnitTest++.h>
#include "rdestl/fixed_substring.h"

namespace
{
	TEST(DefaultCtorGivesEmptyString)
	{
		rde::fixed_substring<char, 16> str;
		CHECK(str.empty());
	}
	TEST(FromCStrNotEmpty)
	{
		rde::fixed_substring<char, 16> str("Hello world");
		CHECK(!str.empty());
	}
	TEST(FromCStrCopiesContents)
	{
		rde::fixed_substring<char, 16> str("Hello world");
		CHECK_EQUAL(0, rde::strcompare(str.data(), "Hello world"));
	}
	TEST(CopyCtorGivesEqualStrings)
	{
		rde::fixed_substring<char, 16> str("Hello world");
		rde::fixed_substring<char, 16> str2(str);
		CHECK(!str2.empty());
		CHECK(str == str2);
	}
}

<commit_msg>append() test<commit_after>#include <UnitTest++/src/UnitTest++.h>
#include "rdestl/fixed_substring.h"

namespace
{
	TEST(DefaultCtorGivesEmptyString)
	{
		rde::fixed_substring<char, 16> str;
		CHECK(str.empty());
	}
	TEST(FromCStrNotEmpty)
	{
		rde::fixed_substring<char, 16> str("Hello world");
		CHECK(!str.empty());
	}
	TEST(FromCStrCopiesContents)
	{
		rde::fixed_substring<char, 16> str("Hello world");
		CHECK_EQUAL(0, rde::strcompare(str.data(), "Hello world"));
	}
	TEST(CopyCtorGivesEqualStrings)
	{
		rde::fixed_substring<char, 16> str("Hello world");
		rde::fixed_substring<char, 16> str2(str);
		CHECK(!str2.empty());
		CHECK(str == str2);
	}
	TEST(Append)
	{
		rde::fixed_substring<char, 9> str("Hello ");
		str.append("world");
		CHECK_EQUAL(0, rde::strcompare(str.data(), "Hello wor"));
	}
}

<|endoftext|>


<commit_before>#pragma once

#include "amd64.h"
#ifdef XV6_KERNEL
#include "atomic.hh"
#else
#include <atomic>
#endif

/**
 * A seqcount is a synchronization primitive that, in conjunction with
 * some form of mutual exclusion, provides write-free optimistic reads
 * of shared data.
 */
template<typename T = unsigned>
class seqcount
{
  std::atomic<T> seq_;

public:
  constexpr seqcount() : seq_(0) { }

  /**
   * An RAII object representing a read section protected by a
   * seqcount.
   */
  class reader
  {
    seqcount * const sc_;
    T init_;

  public:
    constexpr reader(seqcount *sc, T init) : sc_(sc), init_(init) { }

    /**
     * Return true if this read section needs to be retried because of
     * an intervening write section.
     */
    bool need_retry() const
    {
      // The release fence prevents code (specifically, reads) from
      // sinking below the check.
      std::atomic_thread_fence(std::memory_order_release);
      return sc_->seq_.load(std::memory_order_relaxed) != init_;
    }
  };

  /**
   * Signal the beginning of a read of the shared data protected by
   * this seqcount.  This read is opportunistic, so after reading the
   * data, the caller must call #reader::need_retry() on the returned
   * object and, if it returns true, restart the read (including the
   * read_begin()).  Note that the reader must assume that any data
   * returned before need_retry() returns false may be garbage (for
   * example, it's not safe to follow pointers without additional
   * protection from something like RCU).
   */
  reader read_begin()
  {
  retry:
    // Acquire order disables code hoisting so that reads in the
    // caller don't move before our counter snapshot.  Furthermore,
    // this synchronizes with the release store in writer::done such
    // that, if we observe its write, we will observe all writes
    // before it.
    auto s = seq_.load(std::memory_order_acquire);
    if (s & 1) {
      nop_pause();
      goto retry;
    }
    return reader(this, s);
  }

  /**
   * An RAII section representing a write section that may conflict
   * with read sections managed by a seqcount.
   */
  class writer
  {
    seqcount *sc_;
    T val_;

  public:
    constexpr writer(seqcount *sc, T val) : sc_(sc), val_(val) { }

    /**
     * End the write section.
     */
    ~writer()
    {
      done();
    }

    /**
     * End the write section.
     */
    void done() __attribute__((always_inline))
    {
      if (sc_) {
        // This is the mirror of write_begin: writes are not allowed
        // to move after this, but reads are.
        sc_->seq_.store(val_ + 1, std::memory_order_release);
        sc_ = nullptr;
      }
    }
  };

  /**
   * Begin a write section.  This alone does not synchronize write
   * sections; the caller is responsible for acquiring some other form
   * of mutual exclusion before this and releasing it after ending the
   * write section.
   *
   * Another thread attempting to start a reads will spin until this
   * write section ends.  If another thread is currently in a read
   * section, it will be forced to retry.
   */
  writer write_begin()
  {
    // Writes are not allowed to move before this because they may be
    // observed by a reader that thinks the value is stable.  Reads
    // are allowed to move before this because they cannot affect the
    // value observed by readers (and the caller is required to
    // precede this with a lock acquire, which is a stronger barrier).
    // Furthermore, because the caller provides mutual exclusion, we
    // don't have to worry about competing writes, so we don't need an
    // interlocked increment.
    //
    // Because of the surrounding synchronization, we use relaxed
    // ordering for the load and store (the stronger barrier of the
    // lock will prevent even these from hoisting).  To ensure nothing
    // after the store hoists, we follow it with an acquire fence.
    T val = seq_.load(std::memory_order_relaxed);
    seq_.store(val + 1, std::memory_order_relaxed);
    std::atomic_thread_fence(std::memory_order_acquire);
    return writer(this, val + 1);
  }
};
<commit_msg>export count from seqcount::reader<commit_after>#pragma once

#include "amd64.h"
#ifdef XV6_KERNEL
#include "atomic.hh"
#else
#include <atomic>
#endif

/**
 * A seqcount is a synchronization primitive that, in conjunction with
 * some form of mutual exclusion, provides write-free optimistic reads
 * of shared data.
 */
template<typename T = unsigned>
class seqcount
{
  std::atomic<T> seq_;

public:
  constexpr seqcount() : seq_(0) { }

  /**
   * An RAII object representing a read section protected by a
   * seqcount.
   */
  class reader
  {
    seqcount * const sc_;
    T init_;

  public:
    constexpr reader(seqcount *sc, T init) : sc_(sc), init_(init) { }

    /**
     * Return true if this read section needs to be retried because of
     * an intervening write section.
     */
    bool need_retry() const
    {
      // The release fence prevents code (specifically, reads) from
      // sinking below the check.
      std::atomic_thread_fence(std::memory_order_release);
      return sc_->seq_.load(std::memory_order_relaxed) != init_;
    }

    T count() const
    {
      return init_;
    }
  };

  /**
   * Signal the beginning of a read of the shared data protected by
   * this seqcount.  This read is opportunistic, so after reading the
   * data, the caller must call #reader::need_retry() on the returned
   * object and, if it returns true, restart the read (including the
   * read_begin()).  Note that the reader must assume that any data
   * returned before need_retry() returns false may be garbage (for
   * example, it's not safe to follow pointers without additional
   * protection from something like RCU).
   */
  reader read_begin()
  {
  retry:
    // Acquire order disables code hoisting so that reads in the
    // caller don't move before our counter snapshot.  Furthermore,
    // this synchronizes with the release store in writer::done such
    // that, if we observe its write, we will observe all writes
    // before it.
    auto s = seq_.load(std::memory_order_acquire);
    if (s & 1) {
      nop_pause();
      goto retry;
    }
    return reader(this, s);
  }

  /**
   * An RAII section representing a write section that may conflict
   * with read sections managed by a seqcount.
   */
  class writer
  {
    seqcount *sc_;
    T val_;

  public:
    constexpr writer(seqcount *sc, T val) : sc_(sc), val_(val) { }

    /**
     * End the write section.
     */
    ~writer()
    {
      done();
    }

    /**
     * End the write section.
     */
    void done() __attribute__((always_inline))
    {
      if (sc_) {
        // This is the mirror of write_begin: writes are not allowed
        // to move after this, but reads are.
        sc_->seq_.store(val_ + 1, std::memory_order_release);
        sc_ = nullptr;
      }
    }
  };

  /**
   * Begin a write section.  This alone does not synchronize write
   * sections; the caller is responsible for acquiring some other form
   * of mutual exclusion before this and releasing it after ending the
   * write section.
   *
   * Another thread attempting to start a reads will spin until this
   * write section ends.  If another thread is currently in a read
   * section, it will be forced to retry.
   */
  writer write_begin()
  {
    // Writes are not allowed to move before this because they may be
    // observed by a reader that thinks the value is stable.  Reads
    // are allowed to move before this because they cannot affect the
    // value observed by readers (and the caller is required to
    // precede this with a lock acquire, which is a stronger barrier).
    // Furthermore, because the caller provides mutual exclusion, we
    // don't have to worry about competing writes, so we don't need an
    // interlocked increment.
    //
    // Because of the surrounding synchronization, we use relaxed
    // ordering for the load and store (the stronger barrier of the
    // lock will prevent even these from hoisting).  To ensure nothing
    // after the store hoists, we follow it with an acquire fence.
    T val = seq_.load(std::memory_order_relaxed);
    seq_.store(val + 1, std::memory_order_relaxed);
    std::atomic_thread_fence(std::memory_order_acquire);
    return writer(this, val + 1);
  }
};
<|endoftext|>


<commit_before>//
//  language_bootstrap.cpp
//  Parse
//
//  Created by Andrew Hunter on 30/05/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <string>
#include <sstream>
#include <iostream>

#include "language_bootstrap.h"
#include "Language/bootstrap.h"
#include "Language/formatter.h"
#include "Lr/conflict.h"

using namespace std;
using namespace dfa;
using namespace contextfree;
using namespace language;
using namespace lr;

// Checks that a given phrase is lexed as gthe specified symbol
static bool test_lex(string phrase, const lexer& lex, int expectedSymbol, const terminal_dictionary& terms) {
    // Create a lexeme stream
    stringstream source(phrase);
    lexeme_stream* lxs = lex.create_stream_from(source);

    // Get the next lexeme
    lexeme* match;
    (*lxs) >> match;

    bool result = true;
    if (match->content().size() != phrase.size()) {
        for (int x=0; x<match->content().size(); x++) {
            cerr << (char)match->content()[x];
        }
        cerr << endl;
        result = false;
    }
    if (match->matched() != expectedSymbol) {
        wcerr << terms.name_for_symbol(match->matched()) << endl;
        result = false;
    }

    // Finished with the stream
    delete match;
    delete lxs;

    return result;
}

void test_language_bootstrap::run_tests() {
    // Create a bootstrap object
    bootstrap bs;

    // Write out the language to test things
    wcerr << formatter::to_string(bs.get_builder(), bs.get_grammar(), bs.get_terminals()) << endl;

    // Verify that the weak symbols have a higher priority than the strong symbols
    report("WeakSymbols1", bs.get_terminal_items().identifier->symbol() > bs.get_terminal_items().language->symbol());

    // Verify that the lexer looks like a DFA
    ndfa* bsDfa = bs.create_dfa();

    report("DfaIsDfa", bsDfa->is_dfa());
    report("DfaVerifyDfa", bsDfa->verify_is_dfa());
    report("DfaNoOverlap", bsDfa->verify_no_symbol_overlap());

    // The 'identifier' symbol should share its actions with some of the weak symbols in the language
    const item_container& icIdentifier  = bs.get_terminal_items().identifier;
    const item_container& icLanguage    = bs.get_terminal_items().language;
    const item_container& icLexer       = bs.get_terminal_items().lexer;
    const item_container& icEquals      = bs.get_terminal_items().equals;

    bool anyIds         = false;
    bool anyLanguage    = false;
    bool anyLexer       = false;
    bool idAndLanguage  = false;
    bool idAndLexer     = false;
    bool idAndAnything  = false;
    bool idAndEquals    = false;

    for (int stateId = 0; stateId < bsDfa->count_states(); stateId++) {
        typedef ndfa::accept_action_list aal;

        const aal& actions = bsDfa->actions_for_state(stateId);
        if (actions.empty()) continue;

        bool hasId          = false;
        bool hasLanguage    = false;
        bool hasLexer       = false;
        bool hasEquals      = false;

        for (aal::const_iterator nextAction = actions.begin(); nextAction != actions.end(); nextAction++) {
            if ((*nextAction)->symbol() == icIdentifier->symbol())  hasId = true;
            if ((*nextAction)->symbol() == icLanguage->symbol())    hasLanguage = true;
            if ((*nextAction)->symbol() == icLexer->symbol())       hasLexer = true;
            if ((*nextAction)->symbol() == icEquals->symbol())      hasEquals = true;
        }

        if (hasLanguage) {
            anyLanguage = true;
            if (!idAndLanguage) idAndLanguage = hasId;
        }

        if (hasLexer) {
            anyLexer = true;
            if (!idAndLexer) idAndLexer = hasId;
        }

        if (hasEquals) {
            if (!idAndEquals) idAndEquals = hasId;
        }

        if (hasId) {
            anyIds = true;
            if (actions.size() > 1) {
                idAndAnything = true;
            }
        }
    }

    report("AnyIdentifiers", anyIds);
    report("AnyLanguage", anyLanguage);
    report("AnyLexer", anyLexer);
    report("IdentifierAndAnything", idAndAnything);
    report("IdentifierAndLanguage", idAndLanguage);
    report("IdentifierAndLexer", idAndLexer);
    report("IdentifierAndNotEquals", !idAndEquals);

    // Finished looking at the DFA
    delete bsDfa;

    // Test that the lexer can match some particular symbols
    report("MatchIdentifier1", test_lex("fdsu", bs.get_lexer(), bs.get_terminal_items().identifier->symbol(), bs.get_terminals()));
    report("MatchIdentifier2", test_lex("some-identifier", bs.get_lexer(), bs.get_terminal_items().identifier->symbol(), bs.get_terminals()));
    report("MatchIdentifier3", test_lex("id128", bs.get_lexer(), bs.get_terminal_items().identifier->symbol(), bs.get_terminals()));
    report("MatchIdentifier4", test_lex("identifier", bs.get_lexer(), bs.get_terminal_items().identifier->symbol(), bs.get_terminals()));
    report("MatchNonterminal1", test_lex("<nonterminal>", bs.get_lexer(), bs.get_terminal_items().nonterminal->symbol(), bs.get_terminals()));
    report("MatchRegex1", test_lex("/regex/", bs.get_lexer(), bs.get_terminal_items().regex->symbol(), bs.get_terminals()));
    report("MatchString1", test_lex("\"string\"", bs.get_lexer(), bs.get_terminal_items().string->symbol(), bs.get_terminals()));
    report("MatchCharacter1", test_lex("'c'", bs.get_lexer(), bs.get_terminal_items().character->symbol(), bs.get_terminals()));

    report("MatchLanguage", test_lex("language", bs.get_lexer(), bs.get_terminal_items().language->symbol(), bs.get_terminals()));
    report("MatchGrammar", test_lex("grammar", bs.get_lexer(), bs.get_terminal_items().grammar->symbol(), bs.get_terminals()));
    report("MatchLexer", test_lex("lexer", bs.get_lexer(), bs.get_terminal_items().lexer->symbol(), bs.get_terminals()));
    report("MatchLexerSymbols", test_lex("lexer-symbols", bs.get_lexer(), bs.get_terminal_items().lexersymbols->symbol(), bs.get_terminals()));
    report("MatchWeakLexer", test_lex("weaklexer", bs.get_lexer(), bs.get_terminal_items().weaklexer->symbol(), bs.get_terminals()));
    report("MatchIgnore", test_lex("ignore", bs.get_lexer(), bs.get_terminal_items().ignore->symbol(), bs.get_terminals()));
    report("MatchKeywords", test_lex("keywords", bs.get_lexer(), bs.get_terminal_items().keywords->symbol(), bs.get_terminals()));
    report("MatchWhitespace", test_lex("  ", bs.get_lexer(), bs.get_terminal_items().whitespace->symbol(), bs.get_terminals()));
    report("MatchNewline", test_lex("\n", bs.get_lexer(), bs.get_terminal_items().newline->symbol(), bs.get_terminals()));
    report("MatchComment", test_lex("// Comment", bs.get_lexer(), bs.get_terminal_items().comment->symbol(), bs.get_terminals()));

    // Get the conflicts in the grammar
    conflict_list conflicts;
    conflict::find_conflicts(bs.get_builder(), conflicts);

    report("NoConflicts", conflicts.size() == 0);

    // Write out the conflicts to the standard I/O if there were any
    if (conflicts.size() > 0) {
        for (conflict_list::const_iterator it = conflicts.begin(); it != conflicts.end(); it++) {
            wcerr << endl << L"===" << endl << formatter::to_string(**it, bs.get_grammar(), bs.get_terminals()) << endl << L"===" << endl;
        }
    }
}
<commit_msg>Added tests for the quoted form of the character terminal<commit_after>//
//  language_bootstrap.cpp
//  Parse
//
//  Created by Andrew Hunter on 30/05/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <string>
#include <sstream>
#include <iostream>

#include "language_bootstrap.h"
#include "Language/bootstrap.h"
#include "Language/formatter.h"
#include "Lr/conflict.h"

using namespace std;
using namespace dfa;
using namespace contextfree;
using namespace language;
using namespace lr;

// Checks that a given phrase is lexed as gthe specified symbol
static bool test_lex(string phrase, const lexer& lex, int expectedSymbol, const terminal_dictionary& terms) {
    // Create a lexeme stream
    stringstream source(phrase);
    lexeme_stream* lxs = lex.create_stream_from(source);

    // Get the next lexeme
    lexeme* match;
    (*lxs) >> match;

    bool result = true;
    if (match->content().size() != phrase.size()) {
        for (int x=0; x<match->content().size(); x++) {
            cerr << (char)match->content()[x];
        }
        cerr << endl;
        result = false;
    }
    if (match->matched() != expectedSymbol) {
        wcerr << terms.name_for_symbol(match->matched()) << endl;
        result = false;
    }

    // Finished with the stream
    delete match;
    delete lxs;

    return result;
}

void test_language_bootstrap::run_tests() {
    // Create a bootstrap object
    bootstrap bs;

    // Write out the language to test things
    wcerr << formatter::to_string(bs.get_builder(), bs.get_grammar(), bs.get_terminals()) << endl;

    // Verify that the weak symbols have a higher priority than the strong symbols
    report("WeakSymbols1", bs.get_terminal_items().identifier->symbol() > bs.get_terminal_items().language->symbol());

    // Verify that the lexer looks like a DFA
    ndfa* bsDfa = bs.create_dfa();

    report("DfaIsDfa", bsDfa->is_dfa());
    report("DfaVerifyDfa", bsDfa->verify_is_dfa());
    report("DfaNoOverlap", bsDfa->verify_no_symbol_overlap());

    // The 'identifier' symbol should share its actions with some of the weak symbols in the language
    const item_container& icIdentifier  = bs.get_terminal_items().identifier;
    const item_container& icLanguage    = bs.get_terminal_items().language;
    const item_container& icLexer       = bs.get_terminal_items().lexer;
    const item_container& icEquals      = bs.get_terminal_items().equals;

    bool anyIds         = false;
    bool anyLanguage    = false;
    bool anyLexer       = false;
    bool idAndLanguage  = false;
    bool idAndLexer     = false;
    bool idAndAnything  = false;
    bool idAndEquals    = false;

    for (int stateId = 0; stateId < bsDfa->count_states(); stateId++) {
        typedef ndfa::accept_action_list aal;

        const aal& actions = bsDfa->actions_for_state(stateId);
        if (actions.empty()) continue;

        bool hasId          = false;
        bool hasLanguage    = false;
        bool hasLexer       = false;
        bool hasEquals      = false;

        for (aal::const_iterator nextAction = actions.begin(); nextAction != actions.end(); nextAction++) {
            if ((*nextAction)->symbol() == icIdentifier->symbol())  hasId = true;
            if ((*nextAction)->symbol() == icLanguage->symbol())    hasLanguage = true;
            if ((*nextAction)->symbol() == icLexer->symbol())       hasLexer = true;
            if ((*nextAction)->symbol() == icEquals->symbol())      hasEquals = true;
        }

        if (hasLanguage) {
            anyLanguage = true;
            if (!idAndLanguage) idAndLanguage = hasId;
        }

        if (hasLexer) {
            anyLexer = true;
            if (!idAndLexer) idAndLexer = hasId;
        }

        if (hasEquals) {
            if (!idAndEquals) idAndEquals = hasId;
        }

        if (hasId) {
            anyIds = true;
            if (actions.size() > 1) {
                idAndAnything = true;
            }
        }
    }

    report("AnyIdentifiers", anyIds);
    report("AnyLanguage", anyLanguage);
    report("AnyLexer", anyLexer);
    report("IdentifierAndAnything", idAndAnything);
    report("IdentifierAndLanguage", idAndLanguage);
    report("IdentifierAndLexer", idAndLexer);
    report("IdentifierAndNotEquals", !idAndEquals);

    // Finished looking at the DFA
    delete bsDfa;

    // Test that the lexer can match some particular symbols
    report("MatchIdentifier1", test_lex("fdsu", bs.get_lexer(), bs.get_terminal_items().identifier->symbol(), bs.get_terminals()));
    report("MatchIdentifier2", test_lex("some-identifier", bs.get_lexer(), bs.get_terminal_items().identifier->symbol(), bs.get_terminals()));
    report("MatchIdentifier3", test_lex("id128", bs.get_lexer(), bs.get_terminal_items().identifier->symbol(), bs.get_terminals()));
    report("MatchIdentifier4", test_lex("identifier", bs.get_lexer(), bs.get_terminal_items().identifier->symbol(), bs.get_terminals()));
    report("MatchNonterminal1", test_lex("<nonterminal>", bs.get_lexer(), bs.get_terminal_items().nonterminal->symbol(), bs.get_terminals()));
    report("MatchRegex1", test_lex("/regex/", bs.get_lexer(), bs.get_terminal_items().regex->symbol(), bs.get_terminals()));
    report("MatchString1", test_lex("\"string\"", bs.get_lexer(), bs.get_terminal_items().string->symbol(), bs.get_terminals()));
    report("MatchCharacter1", test_lex("'c'", bs.get_lexer(), bs.get_terminal_items().character->symbol(), bs.get_terminals()));
    report("MatchCharacter2", test_lex("'\n'", bs.get_lexer(), bs.get_terminal_items().character->symbol(), bs.get_terminals()));

    report("MatchLanguage", test_lex("language", bs.get_lexer(), bs.get_terminal_items().language->symbol(), bs.get_terminals()));
    report("MatchGrammar", test_lex("grammar", bs.get_lexer(), bs.get_terminal_items().grammar->symbol(), bs.get_terminals()));
    report("MatchLexer", test_lex("lexer", bs.get_lexer(), bs.get_terminal_items().lexer->symbol(), bs.get_terminals()));
    report("MatchLexerSymbols", test_lex("lexer-symbols", bs.get_lexer(), bs.get_terminal_items().lexersymbols->symbol(), bs.get_terminals()));
    report("MatchWeakLexer", test_lex("weaklexer", bs.get_lexer(), bs.get_terminal_items().weaklexer->symbol(), bs.get_terminals()));
    report("MatchIgnore", test_lex("ignore", bs.get_lexer(), bs.get_terminal_items().ignore->symbol(), bs.get_terminals()));
    report("MatchKeywords", test_lex("keywords", bs.get_lexer(), bs.get_terminal_items().keywords->symbol(), bs.get_terminals()));
    report("MatchWhitespace", test_lex("  ", bs.get_lexer(), bs.get_terminal_items().whitespace->symbol(), bs.get_terminals()));
    report("MatchNewline", test_lex("\n", bs.get_lexer(), bs.get_terminal_items().newline->symbol(), bs.get_terminals()));
    report("MatchComment", test_lex("// Comment", bs.get_lexer(), bs.get_terminal_items().comment->symbol(), bs.get_terminals()));

    // Get the conflicts in the grammar
    conflict_list conflicts;
    conflict::find_conflicts(bs.get_builder(), conflicts);

    report("NoConflicts", conflicts.size() == 0);

    // Write out the conflicts to the standard I/O if there were any
    if (conflicts.size() > 0) {
        for (conflict_list::const_iterator it = conflicts.begin(); it != conflicts.end(); it++) {
            wcerr << endl << L"===" << endl << formatter::to_string(**it, bs.get_grammar(), bs.get_terminals()) << endl << L"===" << endl;
        }
    }
}
<|endoftext|>


<commit_before>#include "attributeconstraints.h"

#include <model/devisertypes.h>

#include <util.h>

AttributeConstraints::AttributeConstraints(DeviserValidator* validator)
  : DeviserConstraint(validator)
  , mKnownElementTypes()
  , mKnownTypes(Util::getKnownTypes())
{

  mKnownElementTypes << "enum"
              << "array"
              << "element"
              << "lo_element"
              << "inline_lo_element"
              << "vector"
                 ;

}

int AttributeConstraints::analyzePackage(DeviserPackage *package)
{
  if (package == NULL) return 0;

  int count = 0;

  foreach (DeviserVersion* version, package->getVersions())
  {
    foreach (DeviserClass* element, version->getElements())
    {
      if (element->getName().isEmpty())
      {
        ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR,
                                  "There is an unnamed class in version '"
                                  << version->toString()
                                  << "', this is a required attribute");
        ++count;
      }

      foreach(DeviserAttribute* attribute, element->getAttributes())
      {
        if (checkAttribute(attribute, element->getName()))
          ++count;
      }

      foreach (DeviserListOfAttribute* attribute, element->getListOfAttributes()) {
        if (checkAttribute(attribute, element->getName()))
          ++count;
      }

    }

    foreach (DeviserPlugin* element, version->getPlugins())
    {
      if (element->getExtensionPoint().isEmpty())
      {
        ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR,
                                  "There is a plugin without extensionpoint in version '"
                                  << version->toString()
                                  << "', this is a required attribute");
        ++count;
      }

      foreach(DeviserAttribute* attribute, element->getAttributes())
      {
        if (checkAttribute(attribute, element->getExtensionPoint()))
          ++count;
      }
    }
  }

  return count;

}

bool AttributeConstraints::checkAttribute(DeviserAttribute *attribute,
                                      const QString& name)
{
  bool result = false;

  if (attribute->getName().isEmpty())
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR, "The element '"
                << name
                << "' has an unnamed attribute. This is a required attribute.");

    result = true;
  }
  else if (attribute->getName() == "level" || attribute->getName() == "version")
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR, "The attribute '"
      << attribute->getName()
      << "' of element '"
      << name
      << "' uses the name 'level' or 'version' which will cause compilation issues.");

  }

  if (attribute->getType() == "SIdRef" && attribute->getElement().isEmpty())
  {

    ADD_MESSAGE("The attribute '"
                << attribute->getName()
                << "' of element '"
                << name
                << "' is of type SIdRef, but has no element set. This is needed for validation purposes.");

    return true;
  }
  else if (attribute->getType() == "SIdRef")
    return false;

  if (attribute->getType().isEmpty())
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR,
                              "The attribute '"
                              << attribute->getName()
                              << "' has no type defined, this is a required attribute.");
    return true;
  }

  if (mKnownElementTypes.contains(attribute->getType().toLower(), Qt::CaseInsensitive))
  {
    if (attribute->getElement().isEmpty())
    {

      ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR,
                                "The attribute '"
                                << attribute->getName()
                                << "' is of type '"
                                << attribute->getType()
                                << "' but has no element defined, this is a required attribute.");
      result = true;

    }
  }
  else if (!attribute->getElement().isEmpty())
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_WARNING,
                              "The attribute '"
                              << attribute->getName()
                              << "' is of type '"
                              << attribute->getType()
                              << "' but has an element '"
                              << attribute->getElement()
                              << "' defined, this attribute will not be used.");
    result = true;
  }

  if (!mKnownTypes.contains(attribute->getType().toLower(), Qt::CaseInsensitive))
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_WARNING,
                              "The attribute '"
                              << attribute->getName()
                              << "' is of type '"
                              << attribute->getType()
                              << "', this type is not known by DEVISER and will have to be changed manually in the generated code.");
    result = true;
  }

  return result;
}

<commit_msg>restrict attribute names to avoid any SBase clashes<commit_after>#include "attributeconstraints.h"

#include <model/devisertypes.h>

#include <util.h>

AttributeConstraints::AttributeConstraints(DeviserValidator* validator)
  : DeviserConstraint(validator)
  , mKnownElementTypes()
  , mKnownTypes(Util::getKnownTypes())
{

  mKnownElementTypes << "enum"
              << "array"
              << "element"
              << "lo_element"
              << "inline_lo_element"
              << "vector"
                 ;

}

int AttributeConstraints::analyzePackage(DeviserPackage *package)
{
  if (package == NULL) return 0;

  int count = 0;

  foreach (DeviserVersion* version, package->getVersions())
  {
    foreach (DeviserClass* element, version->getElements())
    {
      if (element->getName().isEmpty())
      {
        ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR,
                                  "There is an unnamed class in version '"
                                  << version->toString()
                                  << "', this is a required attribute");
        ++count;
      }

      foreach(DeviserAttribute* attribute, element->getAttributes())
      {
        if (checkAttribute(attribute, element->getName()))
          ++count;
      }

      foreach (DeviserListOfAttribute* attribute, element->getListOfAttributes()) {
        if (checkAttribute(attribute, element->getName()))
          ++count;
      }

    }

    foreach (DeviserPlugin* element, version->getPlugins())
    {
      if (element->getExtensionPoint().isEmpty())
      {
        ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR,
                                  "There is a plugin without extensionpoint in version '"
                                  << version->toString()
                                  << "', this is a required attribute");
        ++count;
      }

      foreach(DeviserAttribute* attribute, element->getAttributes())
      {
        if (checkAttribute(attribute, element->getExtensionPoint()))
          ++count;
      }
    }
  }

  return count;

}

bool AttributeConstraints::checkAttribute(DeviserAttribute *attribute,
                                      const QString& name)
{
  bool result = false;
  QString lowerName = attribute->getName().toLower();

  if (attribute->getName().isEmpty())
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR, "The element '"
                << name
                << "' has an unnamed attribute. This is a required attribute.");

    result = true;
  }
  else if (lowerName == "level" || lowerName == "version"
    || lowerName == "packageversion" || lowerName == "metaid"
    || lowerName == "notes" || lowerName == "annotation"
    || lowerName == "sboterm" || lowerName == "line"
    || lowerName == "column" || lowerName == "model"
    || lowerName == "modelhistory" || lowerName == "cvterms"
    || lowerName == "attribute" || lowerName == "uri" || lowerName == "prefix")
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR, "The attribute '"
      << attribute->getName()
      << "' of element '"
      << name
      << "' uses a restricted name which will cause compilation issues.");

  }

  if (attribute->getType() == "SIdRef" && attribute->getElement().isEmpty())
  {

    ADD_MESSAGE("The attribute '"
                << attribute->getName()
                << "' of element '"
                << name
                << "' is of type SIdRef, but has no element set. This is needed for validation purposes.");

    return true;
  }
  else if (attribute->getType() == "SIdRef")
    return false;

  if (attribute->getType().isEmpty())
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR,
                              "The attribute '"
                              << attribute->getName()
                              << "' has no type defined, this is a required attribute.");
    return true;
  }

  if (mKnownElementTypes.contains(attribute->getType().toLower(), Qt::CaseInsensitive))
  {
    if (attribute->getElement().isEmpty())
    {

      ADD_MESSAGE_WITH_SEVERITY(DEVISER_ERROR,
                                "The attribute '"
                                << attribute->getName()
                                << "' is of type '"
                                << attribute->getType()
                                << "' but has no element defined, this is a required attribute.");
      result = true;

    }
  }
  else if (!attribute->getElement().isEmpty())
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_WARNING,
                              "The attribute '"
                              << attribute->getName()
                              << "' is of type '"
                              << attribute->getType()
                              << "' but has an element '"
                              << attribute->getElement()
                              << "' defined, this attribute will not be used.");
    result = true;
  }

  if (!mKnownTypes.contains(attribute->getType().toLower(), Qt::CaseInsensitive))
  {
    ADD_MESSAGE_WITH_SEVERITY(DEVISER_WARNING,
                              "The attribute '"
                              << attribute->getName()
                              << "' is of type '"
                              << attribute->getType()
                              << "', this type is not known by DEVISER and will have to be changed manually in the generated code.");
    result = true;
  }

  return result;
}

<|endoftext|>


<commit_before>#ifndef UNIT_CONFIG_HPP_
#define UNIT_CONFIG_HPP_

namespace unit_config {

const float DT = 0.001;

const double PI = 3.14159265358979323846;

// Maximum angular position in the roll and pitch axes (rad)
const float MAX_PITCH_ROLL_POS = 30.0 * PI / 180.0;

// Maximum angular velocity in the roll and pitch axes (rad/s)
const float MAX_PITCH_ROLL_VEL = 100.0 * PI / 180.0;

// Maximum angular acceleration (rad/s^2)
const float MAX_PITCH_ROLL_ACC = 4.0;   // TODO: calculate properly

// Sensor offsets
const float GYR_X_OFFSET = -0.033;
const float GYR_Y_OFFSET =  0.011;
const float GYR_Z_OFFSET =  0.023;
const float ACC_X_OFFSET =  0.026;
const float ACC_Y_OFFSET = -0.005;
const float ACC_Z_OFFSET =  0.025;

// Initial angular position controller gains
const float ANGPOS_X_KP = 1.0;
const float ANGPOS_X_KI = 0.0;
const float ANGPOS_X_KD = 0.0;
const float ANGPOS_Y_KP = 1.0;
const float ANGPOS_Y_KI = 0.0;
const float ANGPOS_Y_KD = 0.0;
const float ANGPOS_Z_KP = 1.0;
const float ANGPOS_Z_KI = 0.0;
const float ANGPOS_Z_KD = 0.0;

// Initial angular velocity controller gains
const float ANGVEL_X_KP = 1.0;
const float ANGVEL_X_KI = 0.0;
const float ANGVEL_X_KD = 0.0;
const float ANGVEL_Y_KP = 1.0;
const float ANGVEL_Y_KI = 0.0;
const float ANGVEL_Y_KD = 0.0;
const float ANGVEL_Z_KP = 1.0;
const float ANGVEL_Z_KI = 0.0;
const float ANGVEL_Z_KD = 0.0;

// Initial angular acceleration controller gains
const float ANGACC_X_KP = 1.0;
const float ANGACC_X_KI = 0.0;
const float ANGACC_X_KD = 0.0;
const float ANGACC_Y_KP = 1.0;
const float ANGACC_Y_KI = 0.0;
const float ANGACC_Y_KD = 0.0;
const float ANGACC_Z_KP = 1.0;
const float ANGACC_Z_KI = 0.0;
const float ANGACC_Z_KD = 0.0;

// Pin configuration
const uint8_t PIN_MAIN_CH   = 1;   // PA5
const uint8_t PIN_DROGUE_CH = 2;   // PC4
const uint8_t PIN_EXT_TEMP_THERM_CH = 1;   // PC1

}

#endif // UNIT_CONFIG_HPP_
<commit_msg>Add payload pin configs to hera.<commit_after>#ifndef UNIT_CONFIG_HPP_
#define UNIT_CONFIG_HPP_

namespace unit_config {

const float DT = 0.001;

const double PI = 3.14159265358979323846;

// Maximum angular position in the roll and pitch axes (rad)
const float MAX_PITCH_ROLL_POS = 30.0 * PI / 180.0;

// Maximum angular velocity in the roll and pitch axes (rad/s)
const float MAX_PITCH_ROLL_VEL = 100.0 * PI / 180.0;

// Maximum angular acceleration (rad/s^2)
const float MAX_PITCH_ROLL_ACC = 4.0;   // TODO: calculate properly

// Sensor offsets
const float GYR_X_OFFSET = -0.033;
const float GYR_Y_OFFSET =  0.011;
const float GYR_Z_OFFSET =  0.023;
const float ACC_X_OFFSET =  0.026;
const float ACC_Y_OFFSET = -0.005;
const float ACC_Z_OFFSET =  0.025;

// Initial angular position controller gains
const float ANGPOS_X_KP = 1.0;
const float ANGPOS_X_KI = 0.0;
const float ANGPOS_X_KD = 0.0;
const float ANGPOS_Y_KP = 1.0;
const float ANGPOS_Y_KI = 0.0;
const float ANGPOS_Y_KD = 0.0;
const float ANGPOS_Z_KP = 1.0;
const float ANGPOS_Z_KI = 0.0;
const float ANGPOS_Z_KD = 0.0;

// Initial angular velocity controller gains
const float ANGVEL_X_KP = 1.0;
const float ANGVEL_X_KI = 0.0;
const float ANGVEL_X_KD = 0.0;
const float ANGVEL_Y_KP = 1.0;
const float ANGVEL_Y_KI = 0.0;
const float ANGVEL_Y_KD = 0.0;
const float ANGVEL_Z_KP = 1.0;
const float ANGVEL_Z_KI = 0.0;
const float ANGVEL_Z_KD = 0.0;

// Initial angular acceleration controller gains
const float ANGACC_X_KP = 1.0;
const float ANGACC_X_KI = 0.0;
const float ANGACC_X_KD = 0.0;
const float ANGACC_Y_KP = 1.0;
const float ANGACC_Y_KI = 0.0;
const float ANGACC_Y_KD = 0.0;
const float ANGACC_Z_KP = 1.0;
const float ANGACC_Z_KI = 0.0;
const float ANGACC_Z_KD = 0.0;

// PWM pin config
const uint8_t PIN_FIN_SWITCH_CH = 5;   // PB7
const uint8_t PIN_MOTOR_CH = 7;   // PB9

// ADC pin config
const uint8_t PIN_ESC_TEMP_THERM_CH = 0;   // PC0

// Digital pin config
const uint8_t PIN_SHUTTLE2_CH = 0;   // PA4
const uint8_t PIN_DROGUE_CH = 1;   // PA5
const uint8_t PIN_SHUTTLE1_CH = 3;   // PC5

// Unused config
// TODO(yoos): This is a hack to make rocket and payload build.
const uint8_t PIN_MAIN_CH = 255;

}

#endif // UNIT_CONFIG_HPP_
<|endoftext|>