<commit_before>#include "FVNormalizedCutGUI.h"

FVNormCutGUI::FVNormCutGUI(QWidget* Parent, FiberDisplay* FVDisplay):FVPanelGUI(Parent,FVDisplay)
{
	m_L_Cluster=new QLabel("Number of Cluster", this);
	m_SB_Cluster=new QSpinBox(this);
	m_SB_Cluster->setSingleStep(1);
	m_SB_Cluster->setRange(2,1000);
	m_SB_Cluster->setValue(2);

	QGridLayout* GL_NormCut=new QGridLayout;
	QHBoxLayout* HL_Navigation=new QHBoxLayout;

	GL_NormCut->addWidget(m_L_Cluster,0,0,1,0);
	GL_NormCut->addWidget(m_SB_Cluster,1,0,1,0);
	HL_Navigation->addWidget(m_PB_Undo);
	HL_Navigation->addWidget(m_PB_Next);
	GL_NormCut->addLayout(HL_Navigation,2,0,1,0);
	GL_NormCut->setRowStretch(3,1);

	setLayout(GL_NormCut);

	connect(m_PB_Undo, SIGNAL(clicked()), this, SLOT(UndoAction()));
	connect(m_PB_Next, SIGNAL(clicked()), this, SLOT(NextAction()));
}

void FVNormCutGUI::InitWeight()
{
	m_Weight.clear();
	int NbFibers=m_Display->GetNbModifiedFibers();
	for (int i = 0 ; i < NbFibers ; i++)
	{
		std::vector<double> Line;
		//for all the other fibers
		for (int j = 0 ; j < NbFibers ; j++)
			Line.push_back(0);
		m_Weight.push_back(Line);
	}
}

void FVNormCutGUI::ApplyWeight(bool Type)
{
	std::vector<int> Alpha=m_Display->GetLastAlpha(FiberDisplay::Previous);
	vtkSmartPointer<vtkPolyData> PolyData;
	PolyData=m_Display->GetOriginalPolyData();
	vtkIdType NbSourcePoints, NbTargetPoints;
	vtkIdType* SourceIds;
	vtkIdType* TargetIds;
	vtkCellArray* LinesSource=PolyData->GetLines();
	vtkCellArray* LinesTarget=PolyData->GetLines();
	int NbFibers=PolyData->GetNumberOfCells();
	int CountProgress=0;
	int RelevantSourceFiberCount=0, RelevantTargetFiberCount=0;
	InitWeight();
	for(int i=0; i<NbFibers; i++)
	{
		if(Alpha[i]==1)
		{
			PolyData->GetCellPoints(i,NbSourcePoints,SourceIds);
			RelevantTargetFiberCount=RelevantSourceFiberCount+1;
			for(int j=i+1; j<NbFibers; j++)
			{
				if(Alpha[j]==1)
				{
					PolyData->GetCellPoints(j,NbTargetPoints,TargetIds);
					double x1, x2;
					if(Type)
					{
						x1 = ComputeMeanDistance(j,NbSourcePoints,SourceIds);
						x2 = ComputeMeanDistance(i,NbTargetPoints,TargetIds);
					}
					else
					{
						x1 = ComputeMeanDistance(NbTargetPoints,TargetIds,NbSourcePoints,SourceIds);
						x2 = ComputeMeanDistance(NbSourcePoints,SourceIds,NbTargetPoints,TargetIds);
					}
					double MeanVal = (x1 + x2) / 2;
					if(MeanVal!=0)
					{
						m_Weight[RelevantSourceFiberCount][RelevantTargetFiberCount] = 1/(MeanVal*m_Display->GetSpacing());
						m_Weight[RelevantTargetFiberCount][RelevantSourceFiberCount] = 1/(MeanVal*m_Display->GetSpacing());
					}
					else
					{
						m_Weight[RelevantSourceFiberCount][RelevantTargetFiberCount]=0;
						m_Weight[RelevantTargetFiberCount][RelevantSourceFiberCount]=0;
					}
					CountProgress++;
					emit Progress(CountProgress*200/(NbFibers*NbFibers));
					RelevantTargetFiberCount++;
				}
			}
			RelevantSourceFiberCount++;
		}
	}
}

//Compute the MaxMin between two fibers
double FVNormCutGUI::ComputeMeanDistance(int NbSourcePoints,vtkIdType* SourceIds,int NbTargetPoints,vtkIdType* TargetIds)
{
	double x,y,z;
	double xs,ys,zs;
	double xt,yt,zt;

	double MeanDist, Distance, MinDist, TotalDist = 0;

	vtkSmartPointer<vtkPolyData> PolyData;
	PolyData=m_Display->GetOriginalPolyData();
	vtkPoints* Points=PolyData->GetPoints();
	for (int i=0;i<NbSourcePoints;i++)
	{
		double SourcePoint[3]={0,0,0};
		Points->GetPoint(SourceIds[i],SourcePoint);
		MinDist = 999999999;
		//For each point of the target fiber
		xs=SourcePoint[0];
		ys=SourcePoint[1];
		zs=SourcePoint[2];

		for (int j=0;j<NbTargetPoints;j++)
		{
			//calculate distance between the two points
			double TargetPoint[3]={0,0,0};
			Points->GetPoint(TargetIds[j],TargetPoint);
			xt = TargetPoint[0];
			yt = TargetPoint[1];
			zt = TargetPoint[2];

			x = (xs - xt);
			y = (ys - yt);
			z = (zs - zt);
			Distance = (x*x+y*y+z*z);
			//Keep the minimum distance of the distances between the whole points
			//of the target fiber and one point of the source fiber
			if (Distance<MinDist)
				MinDist = Distance;
		}
		//Finaly, sum all min
		TotalDist += MinDist;
	}
	MeanDist = TotalDist/NbSourcePoints;
	//return the Meanmin to have the Mean distance
	//it just remains to take the mean between the couple i,j end j,i
	return sqrt(MeanDist);
}

//Compute the MaxMin between two fibers
double FVNormCutGUI::ComputeMeanDistance(int SourceId,int NbTargetPoints,vtkIdType* TargetIds)
{
	double MeanDist, Distance, TotalDist = 0;

	vtkSmartPointer<vtkPolyData> PolyData;
	PolyData=m_Display->GetOriginalPolyData();
	vtkPoints* Points=PolyData->GetPoints();
	RealImageType::Pointer DistanceMap=m_Display->GetDTVector(SourceId);

	for (int j=0;j<NbTargetPoints;j++)
	{
		double TargetPoint[3]={0,0,0};
		Points->GetPoint(TargetIds[j],TargetPoint);
		itk::Point<double,3> ITKPoint;
		ITKPoint[0]=TargetPoint[0];
		ITKPoint[1]=TargetPoint[1];
		ITKPoint[2]=TargetPoint[2];

		ContinuousIndexType ContId;
		itk::Index<3> Index;

		DistanceMap->TransformPhysicalPointToContinuousIndex(ITKPoint, ContId);
		Index[0]=static_cast<long int>(vnl_math_rnd_halfinttoeven(ContId[0]));
		Index[1]=static_cast<long int>(vnl_math_rnd_halfinttoeven(ContId[1]));
		Index[2]=static_cast<long int>(vnl_math_rnd_halfinttoeven(ContId[2]));
		Distance=DistanceMap->GetPixel(Index);
		TotalDist += Distance;
	}
	MeanDist = TotalDist/NbTargetPoints;
	return MeanDist;
}

double FVNormCutGUI::Assoc(int BeginId, int EndId, bool All)
{
	double SumWeight=0;
	for(int i=BeginId; i<=EndId; i++)
	{
		if(!All)
		{
			for(int j=BeginId; j<=EndId; j++)
				SumWeight+=m_Weight[i][j];
		}
		else
		{
			for(unsigned int j=0; j<m_Weight.size() ; j++)
				SumWeight+=m_Weight[i][j];
		}
	}
	return SumWeight;
}

void FVNormCutGUI::GenerateClass()
{
	int ClusterDone=1;
	m_Mark=FillMark(m_Weight,ClusterDone,m_SB_Cluster->value());
}

std::vector<int> FVNormCutGUI::FillMark(std::vector<std::vector<double> > Weight, int& ClusterDone, int NumberOfCluster)
{
	std::vector<int> Mark;
	if(Weight.size()==1 || NumberOfCluster==1)
	{
		for(unsigned int i=0; i<Weight.size(); i++)
			Mark.push_back(ClusterDone);
		return Mark;
	}
	else
	{
		double MinCut=1000;
		int CutId=-1;
		for(unsigned int i=0; i<Weight.size()-1; i++)
		{
			double cut=Cut(i,i+1);
			double NCut=cut/Assoc(0,i,true)+cut/Assoc(i+1,Weight.size()-1,true);
			if(NCut<MinCut)
			{
				CutId=i;
				MinCut=NCut;
			}
		}
		std::vector<std::vector<double> > SubWeight;
		for(int i=0; i<=CutId; i++)
		{
			std::vector<double>Line;
			for(int j=0; j<=CutId; j++)
				Line.push_back(Weight[i][j]);
			SubWeight.push_back(Line);
		}
		Mark=FillMark(SubWeight,ClusterDone,NumberOfCluster/2);

		ClusterDone++;
		SubWeight.clear();
		for(unsigned int i=CutId+1; i<Weight.size(); i++)
		{
			std::vector<double>Line;
			for(unsigned int j=CutId+1; j<=Weight.size(); j++)
				Line.push_back(Weight[i][j]);
			SubWeight.push_back(Line);
		}
		std::vector<int> MarkTemp;

		if(NumberOfCluster%2==0)
			MarkTemp=FillMark(SubWeight,ClusterDone,NumberOfCluster/2);
		else
			MarkTemp=FillMark(SubWeight,ClusterDone,NumberOfCluster/2+1);
		for(unsigned int i=0; i<MarkTemp.size(); i++)
			Mark.push_back(MarkTemp[i]);
		return Mark;
	}
}

double FVNormCutGUI::Cut(int Previous, int Next)
{
	double Cut=0;
	for(int i=0; i<=Previous; i++)
	{
		for(unsigned int j=Next; j<m_Weight.size(); j++)
			Cut+=m_Weight[i][j];
	}
	return Cut;
}

int FVNormCutGUI::GetNumberOfClasse()
{
	//Get the max of the mark vector which is the number of classe
	int nbclasse = 0;
	for(unsigned int i = 0 ; i < m_Mark.size() ; i++)
		if(m_Mark[i] > nbclasse)
			nbclasse = m_Mark[i];
	return nbclasse;
}

void FVNormCutGUI::UndoAction()
{
	emit Exit(FVPanelGUI::Undo);
}

void FVNormCutGUI::NextAction()
{
	GenerateClass();
	emit Exit(FVPanelGUI::Ok);
}
<commit_msg>COMP: FVNormalizedCutGUI: Fix unused variable warnings<commit_after>#include "FVNormalizedCutGUI.h"

FVNormCutGUI::FVNormCutGUI(QWidget* Parent, FiberDisplay* FVDisplay):FVPanelGUI(Parent,FVDisplay)
{
	m_L_Cluster=new QLabel("Number of Cluster", this);
	m_SB_Cluster=new QSpinBox(this);
	m_SB_Cluster->setSingleStep(1);
	m_SB_Cluster->setRange(2,1000);
	m_SB_Cluster->setValue(2);

	QGridLayout* GL_NormCut=new QGridLayout;
	QHBoxLayout* HL_Navigation=new QHBoxLayout;

	GL_NormCut->addWidget(m_L_Cluster,0,0,1,0);
	GL_NormCut->addWidget(m_SB_Cluster,1,0,1,0);
	HL_Navigation->addWidget(m_PB_Undo);
	HL_Navigation->addWidget(m_PB_Next);
	GL_NormCut->addLayout(HL_Navigation,2,0,1,0);
	GL_NormCut->setRowStretch(3,1);

	setLayout(GL_NormCut);

	connect(m_PB_Undo, SIGNAL(clicked()), this, SLOT(UndoAction()));
	connect(m_PB_Next, SIGNAL(clicked()), this, SLOT(NextAction()));
}

void FVNormCutGUI::InitWeight()
{
	m_Weight.clear();
	int NbFibers=m_Display->GetNbModifiedFibers();
	for (int i = 0 ; i < NbFibers ; i++)
	{
		std::vector<double> Line;
		//for all the other fibers
		for (int j = 0 ; j < NbFibers ; j++)
			Line.push_back(0);
		m_Weight.push_back(Line);
	}
}

void FVNormCutGUI::ApplyWeight(bool Type)
{
	std::vector<int> Alpha=m_Display->GetLastAlpha(FiberDisplay::Previous);
	vtkSmartPointer<vtkPolyData> PolyData;
	PolyData=m_Display->GetOriginalPolyData();
	vtkIdType NbSourcePoints, NbTargetPoints;
	vtkIdType* SourceIds;
	vtkIdType* TargetIds;
	int NbFibers=PolyData->GetNumberOfCells();
	int CountProgress=0;
	int RelevantSourceFiberCount=0, RelevantTargetFiberCount=0;
	InitWeight();
	for(int i=0; i<NbFibers; i++)
	{
		if(Alpha[i]==1)
		{
			PolyData->GetCellPoints(i,NbSourcePoints,SourceIds);
			RelevantTargetFiberCount=RelevantSourceFiberCount+1;
			for(int j=i+1; j<NbFibers; j++)
			{
				if(Alpha[j]==1)
				{
					PolyData->GetCellPoints(j,NbTargetPoints,TargetIds);
					double x1, x2;
					if(Type)
					{
						x1 = ComputeMeanDistance(j,NbSourcePoints,SourceIds);
						x2 = ComputeMeanDistance(i,NbTargetPoints,TargetIds);
					}
					else
					{
						x1 = ComputeMeanDistance(NbTargetPoints,TargetIds,NbSourcePoints,SourceIds);
						x2 = ComputeMeanDistance(NbSourcePoints,SourceIds,NbTargetPoints,TargetIds);
					}
					double MeanVal = (x1 + x2) / 2;
					if(MeanVal!=0)
					{
						m_Weight[RelevantSourceFiberCount][RelevantTargetFiberCount] = 1/(MeanVal*m_Display->GetSpacing());
						m_Weight[RelevantTargetFiberCount][RelevantSourceFiberCount] = 1/(MeanVal*m_Display->GetSpacing());
					}
					else
					{
						m_Weight[RelevantSourceFiberCount][RelevantTargetFiberCount]=0;
						m_Weight[RelevantTargetFiberCount][RelevantSourceFiberCount]=0;
					}
					CountProgress++;
					emit Progress(CountProgress*200/(NbFibers*NbFibers));
					RelevantTargetFiberCount++;
				}
			}
			RelevantSourceFiberCount++;
		}
	}
}

//Compute the MaxMin between two fibers
double FVNormCutGUI::ComputeMeanDistance(int NbSourcePoints,vtkIdType* SourceIds,int NbTargetPoints,vtkIdType* TargetIds)
{
	double x,y,z;
	double xs,ys,zs;
	double xt,yt,zt;

	double MeanDist, Distance, MinDist, TotalDist = 0;

	vtkSmartPointer<vtkPolyData> PolyData;
	PolyData=m_Display->GetOriginalPolyData();
	vtkPoints* Points=PolyData->GetPoints();
	for (int i=0;i<NbSourcePoints;i++)
	{
		double SourcePoint[3]={0,0,0};
		Points->GetPoint(SourceIds[i],SourcePoint);
		MinDist = 999999999;
		//For each point of the target fiber
		xs=SourcePoint[0];
		ys=SourcePoint[1];
		zs=SourcePoint[2];

		for (int j=0;j<NbTargetPoints;j++)
		{
			//calculate distance between the two points
			double TargetPoint[3]={0,0,0};
			Points->GetPoint(TargetIds[j],TargetPoint);
			xt = TargetPoint[0];
			yt = TargetPoint[1];
			zt = TargetPoint[2];

			x = (xs - xt);
			y = (ys - yt);
			z = (zs - zt);
			Distance = (x*x+y*y+z*z);
			//Keep the minimum distance of the distances between the whole points
			//of the target fiber and one point of the source fiber
			if (Distance<MinDist)
				MinDist = Distance;
		}
		//Finaly, sum all min
		TotalDist += MinDist;
	}
	MeanDist = TotalDist/NbSourcePoints;
	//return the Meanmin to have the Mean distance
	//it just remains to take the mean between the couple i,j end j,i
	return sqrt(MeanDist);
}

//Compute the MaxMin between two fibers
double FVNormCutGUI::ComputeMeanDistance(int SourceId,int NbTargetPoints,vtkIdType* TargetIds)
{
	double MeanDist, Distance, TotalDist = 0;

	vtkSmartPointer<vtkPolyData> PolyData;
	PolyData=m_Display->GetOriginalPolyData();
	vtkPoints* Points=PolyData->GetPoints();
	RealImageType::Pointer DistanceMap=m_Display->GetDTVector(SourceId);

	for (int j=0;j<NbTargetPoints;j++)
	{
		double TargetPoint[3]={0,0,0};
		Points->GetPoint(TargetIds[j],TargetPoint);
		itk::Point<double,3> ITKPoint;
		ITKPoint[0]=TargetPoint[0];
		ITKPoint[1]=TargetPoint[1];
		ITKPoint[2]=TargetPoint[2];

		ContinuousIndexType ContId;
		itk::Index<3> Index;

		DistanceMap->TransformPhysicalPointToContinuousIndex(ITKPoint, ContId);
		Index[0]=static_cast<long int>(vnl_math_rnd_halfinttoeven(ContId[0]));
		Index[1]=static_cast<long int>(vnl_math_rnd_halfinttoeven(ContId[1]));
		Index[2]=static_cast<long int>(vnl_math_rnd_halfinttoeven(ContId[2]));
		Distance=DistanceMap->GetPixel(Index);
		TotalDist += Distance;
	}
	MeanDist = TotalDist/NbTargetPoints;
	return MeanDist;
}

double FVNormCutGUI::Assoc(int BeginId, int EndId, bool All)
{
	double SumWeight=0;
	for(int i=BeginId; i<=EndId; i++)
	{
		if(!All)
		{
			for(int j=BeginId; j<=EndId; j++)
				SumWeight+=m_Weight[i][j];
		}
		else
		{
			for(unsigned int j=0; j<m_Weight.size() ; j++)
				SumWeight+=m_Weight[i][j];
		}
	}
	return SumWeight;
}

void FVNormCutGUI::GenerateClass()
{
	int ClusterDone=1;
	m_Mark=FillMark(m_Weight,ClusterDone,m_SB_Cluster->value());
}

std::vector<int> FVNormCutGUI::FillMark(std::vector<std::vector<double> > Weight, int& ClusterDone, int NumberOfCluster)
{
	std::vector<int> Mark;
	if(Weight.size()==1 || NumberOfCluster==1)
	{
		for(unsigned int i=0; i<Weight.size(); i++)
			Mark.push_back(ClusterDone);
		return Mark;
	}
	else
	{
		double MinCut=1000;
		int CutId=-1;
		for(unsigned int i=0; i<Weight.size()-1; i++)
		{
			double cut=Cut(i,i+1);
			double NCut=cut/Assoc(0,i,true)+cut/Assoc(i+1,Weight.size()-1,true);
			if(NCut<MinCut)
			{
				CutId=i;
				MinCut=NCut;
			}
		}
		std::vector<std::vector<double> > SubWeight;
		for(int i=0; i<=CutId; i++)
		{
			std::vector<double>Line;
			for(int j=0; j<=CutId; j++)
				Line.push_back(Weight[i][j]);
			SubWeight.push_back(Line);
		}
		Mark=FillMark(SubWeight,ClusterDone,NumberOfCluster/2);

		ClusterDone++;
		SubWeight.clear();
		for(unsigned int i=CutId+1; i<Weight.size(); i++)
		{
			std::vector<double>Line;
			for(unsigned int j=CutId+1; j<=Weight.size(); j++)
				Line.push_back(Weight[i][j]);
			SubWeight.push_back(Line);
		}
		std::vector<int> MarkTemp;

		if(NumberOfCluster%2==0)
			MarkTemp=FillMark(SubWeight,ClusterDone,NumberOfCluster/2);
		else
			MarkTemp=FillMark(SubWeight,ClusterDone,NumberOfCluster/2+1);
		for(unsigned int i=0; i<MarkTemp.size(); i++)
			Mark.push_back(MarkTemp[i]);
		return Mark;
	}
}

double FVNormCutGUI::Cut(int Previous, int Next)
{
	double Cut=0;
	for(int i=0; i<=Previous; i++)
	{
		for(unsigned int j=Next; j<m_Weight.size(); j++)
			Cut+=m_Weight[i][j];
	}
	return Cut;
}

int FVNormCutGUI::GetNumberOfClasse()
{
	//Get the max of the mark vector which is the number of classe
	int nbclasse = 0;
	for(unsigned int i = 0 ; i < m_Mark.size() ; i++)
		if(m_Mark[i] > nbclasse)
			nbclasse = m_Mark[i];
	return nbclasse;
}

void FVNormCutGUI::UndoAction()
{
	emit Exit(FVPanelGUI::Undo);
}

void FVNormCutGUI::NextAction()
{
	GenerateClass();
	emit Exit(FVPanelGUI::Ok);
}
<|endoftext|>


<commit_before>#ifndef ITER_CYCLE_H_
#define ITER_CYCLE_H_

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container>
    class Cycle;

    template <typename Container>
    Cycle<Container> cycle(Container&&);

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T>);

    template <typename Container>
    class Cycle {
        private:
            friend Cycle cycle<Container>(Container&&);
            template <typename T>
            friend Cycle<std::initializer_list<T>> cycle(
                    std::initializer_list<T>);

            Container container;

            Cycle(Container&& container)
                : container(std::forward<Container>(container))
            { }

        public:
            class Iterator
                : public std::iterator<std::input_iterator_tag,
                            iterator_traits_deref<Container>>
            {
                private:
                    using iter_type = iterator_type<Container>;
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> begin;
                    iterator_type<Container> end;
                public:
                    Iterator (iterator_type<Container> iter,
                            iterator_type<Container> end)
                        : sub_iter{iter},
                        begin{iter},
                        end{end}
                    { }

                    iterator_deref<Container> operator*() {
                        return *this->sub_iter;
                    }

                    Iterator& operator++() {
                        ++this->sub_iter;
                        // reset to beginning upon reaching the end
                        if (!(this->sub_iter != this->end)) {
                            this->sub_iter = this->begin;
                        }
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container)};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container)};
            }

    };

    template <typename Container>
    Cycle<Container> cycle(Container&& container) {
        return {std::forward<Container>(container)};
    }

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T> il)
    {
        return {std::move(il)};
    }
}

#endif
<commit_msg>moves end, copies begin<commit_after>#ifndef ITER_CYCLE_H_
#define ITER_CYCLE_H_

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container>
    class Cycle;

    template <typename Container>
    Cycle<Container> cycle(Container&&);

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T>);

    template <typename Container>
    class Cycle {
        private:
            friend Cycle cycle<Container>(Container&&);
            template <typename T>
            friend Cycle<std::initializer_list<T>> cycle(
                    std::initializer_list<T>);

            Container container;

            Cycle(Container&& container)
                : container(std::forward<Container>(container))
            { }

        public:
            class Iterator
                : public std::iterator<std::input_iterator_tag,
                            iterator_traits_deref<Container>>
            {
                private:
                    using iter_type = iterator_type<Container>;
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> begin;
                    iterator_type<Container> end;
                public:
                    Iterator (const iterator_type<Container>& iter,
                            iterator_type<Container>&& end)
                        : sub_iter{iter},
                        begin{iter},
                        end{std::move(end)}
                    { }

                    iterator_deref<Container> operator*() {
                        return *this->sub_iter;
                    }

                    Iterator& operator++() {
                        ++this->sub_iter;
                        // reset to beginning upon reaching the end
                        if (!(this->sub_iter != this->end)) {
                            this->sub_iter = this->begin;
                        }
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }
            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container)};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container)};
            }

    };

    template <typename Container>
    Cycle<Container> cycle(Container&& container) {
        return {std::forward<Container>(container)};
    }

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T> il)
    {
        return {std::move(il)};
    }
}

#endif
<|endoftext|>


<commit_before>#include <cassert>

#include "SDL.h"

#include "GameWorldPanel.h"

#include "AutomapPanel.h"
#include "Button.h"
#include "CharacterPanel.h"
#include "LogbookPanel.h"
#include "PauseMenuPanel.h"
#include "WorldMapPanel.h"
#include "../Entities/CoordinateFrame.h"
#include "../Entities/Player.h"
#include "../Game/GameData.h"
#include "../Game/GameState.h"
#include "../Game/Options.h"
#include "../Math/Constants.h"
#include "../Math/Int2.h"
#include "../Math/Random.h"
#include "../Math/Rect.h"
#include "../Media/AudioManager.h"
#include "../Media/Color.h"
#include "../Media/MusicName.h"
#include "../Media/PaletteName.h"
#include "../Media/SoundName.h"
#include "../Media/TextureFile.h"
#include "../Media/TextureManager.h"
#include "../Media/TextureName.h"
#include "../Rendering/CLProgram.h"
#include "../Rendering/Renderer.h"
#include "../Utilities/Debug.h"

GameWorldPanel::GameWorldPanel(GameState *gameState)
	: Panel(gameState)
{
	assert(gameState->gameDataIsActive());

	this->automapButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> automapPanel(new AutomapPanel(gameState));
			gameState->setPanel(std::move(automapPanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();

	this->characterSheetButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> sheetPanel(new CharacterPanel(gameState));
			gameState->setPanel(std::move(sheetPanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();

	this->logbookButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> logbookPanel(new LogbookPanel(gameState));
			gameState->setPanel(std::move(logbookPanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();

	this->pauseButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> pausePanel(new PauseMenuPanel(gameState));
			gameState->setPanel(std::move(pausePanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();

	this->worldMapButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> mapPanel(new WorldMapPanel(gameState));
			gameState->setPanel(std::move(mapPanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();
}

GameWorldPanel::~GameWorldPanel()
{

}

void GameWorldPanel::handleEvents(bool &running)
{
	SDL_Event e;
	while (SDL_PollEvent(&e) != 0)
	{
		bool applicationExit = (e.type == SDL_QUIT);
		bool resized = (e.type == SDL_WINDOWEVENT) &&
			(e.window.event == SDL_WINDOWEVENT_RESIZED);
		bool escapePressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_ESCAPE);

		if (applicationExit)
		{
			running = false;
		}
		if (resized)
		{
			int width = e.window.data1;
			int height = e.window.data2;
			this->getGameState()->resizeWindow(width, height);
		}
		if (escapePressed)
		{
			this->pauseButton->click(this->getGameState());
		}

		bool leftClick = (e.type == SDL_MOUSEBUTTONDOWN) &&
			(e.button.button == SDL_BUTTON_LEFT);
		bool activateHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_e);
		bool automapHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_n);
		bool logbookHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_l);
		bool sheetHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_TAB);
		bool worldMapHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_m);

		if (leftClick)
		{
			// Interface buttons? Entities in the world?
		}
		if (activateHotkeyPressed)
		{
			// Activate whatever is looked at.
		}
		else if (automapHotkeyPressed)
		{
			// Go to the automap.
			this->automapButton->click(this->getGameState());
		}
		else if (logbookHotkeyPressed)
		{
			// Go to the logbook.
			this->logbookButton->click(this->getGameState());
		}
		else if (sheetHotkeyPressed)
		{
			// Go to the character screen.
			this->characterSheetButton->click(this->getGameState());
		}
		else if (worldMapHotkeyPressed)
		{
			// Go to the world map.
			this->worldMapButton->click(this->getGameState());
		}
	}
}

void GameWorldPanel::handleMouse(double dt)
{
	static_cast<void>(dt);

	// Make the camera look around.
	int dx, dy;
	const auto mouse = SDL_GetRelativeMouseState(&dx, &dy);

	// The program will eventually not require holding a mouse button to turn.
	bool leftClick = (mouse & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0;
	bool rightClick = (mouse & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
	bool turning = ((dx != 0) || (dy != 0)) && (leftClick || rightClick);

	if (turning)
	{
		auto dimensions = this->getGameState()->getScreenDimensions();
		double dxx = static_cast<double>(dx) / static_cast<double>(dimensions.getX());
		double dyy = static_cast<double>(dy) / static_cast<double>(dimensions.getY());

		// Pitch and/or yaw the camera.
		const auto &options = this->getGameState()->getOptions();
		this->getGameState()->getGameData()->getPlayer().rotate(dxx, -dyy,
			options.getHorizontalSensitivity(), options.getVerticalSensitivity(),
			options.getVerticalFOV());
	}
}

void GameWorldPanel::handleKeyboard(double dt)
{
	// Listen for WASD, jump...
	const auto keys = SDL_GetKeyboardState(nullptr);

	bool forward = keys[SDL_SCANCODE_W] != 0;
	bool backward = keys[SDL_SCANCODE_S] != 0;
	bool left = keys[SDL_SCANCODE_A] != 0;
	bool right = keys[SDL_SCANCODE_D] != 0;
	bool jump = keys[SDL_SCANCODE_SPACE] != 0;

	bool any = forward || backward || left || right || jump;

	if (any)
	{
		bool isRunning = keys[SDL_SCANCODE_LSHIFT] != 0;
		auto &player = this->getGameState()->getGameData()->getPlayer();

		// Get some relevant player direction data.
		Float2d groundDirection = player.getGroundDirection();
		Float3d groundDirection3D = Float3d(groundDirection.getX(), 0.0,
			groundDirection.getY()).normalized();
		Float3d rightDirection = player.getFrame().getRight().normalized();

		// Calculate the acceleration direction based on input.
		Float3d accelDirection = Float3d(0.0, 0.0, 0.0);
		if (forward)
		{
			accelDirection = accelDirection + groundDirection3D;
		}
		if (backward)
		{
			accelDirection = accelDirection - groundDirection3D;
		}
		if (right)
		{
			accelDirection = accelDirection + rightDirection;
		}
		if (left)
		{
			accelDirection = accelDirection - rightDirection;
		}

		// To do: check jump eventually once gravity and ground collision are implemented.

		// Use a normalized direction.
		accelDirection = accelDirection.normalized();

		// Set the magnitude of the acceleration to some arbitrary numbers. These values
		// are independent of max speed. The original game didn't have sprinting, but it
		// seems like something relevant to do anyway (at least in testing).
		double accelMagnitude = isRunning ? 35.0 : 10.0;

		// Change the player's velocity if valid.
		if (std::isfinite(accelDirection.length()))
		{
			player.accelerate(accelDirection, accelMagnitude, isRunning, dt);
		}
	}
}

void GameWorldPanel::tick(double dt, bool &running)
{
	assert(this->getGameState()->gameDataIsActive());

	this->handleEvents(running);
	this->handleMouse(dt);
	this->handleKeyboard(dt);

	// Animate the game world.
	auto *gameData = this->getGameState()->getGameData();
	gameData->incrementGameTime(dt);

	// Tick the player.
	auto &player = gameData->getPlayer();
	player.tick(this->getGameState(), dt);

	// Update CLProgram members that are refreshed each frame.
	double verticalFOV = this->getGameState()->getOptions().getVerticalFOV();
	auto &clProgram = gameData->getCLProgram();
	clProgram.updateCamera(player.getPosition(), player.getDirection(), verticalFOV);
	clProgram.updateGameTime(gameData->getGameTime());
}

void GameWorldPanel::render(SDL_Renderer *renderer, const SDL_Rect *letterbox)
{
	assert(this->getGameState()->gameDataIsActive());

	// Draw game world using OpenCL rendering.
	this->getGameState()->getGameData()->getCLProgram().render(renderer);

	// Interface objects (stat bars, compass, ...) should snap to the edges of the native
	// screen, not just the letterbox, because right now, when the screen is tall, the
	// compass is near the middle of the screen (in the way), and the stat bars are much
	// higher than they should be. I haven't figured out yet what the equation is. I
	// think it requires using the original height and the draw scale somehow.

	// Set screen palette.
	auto &textureManager = this->getGameState()->getTextureManager();
	textureManager.setPalette(PaletteName::Default);

	// Draw game world interface.
	const auto *gameInterface = textureManager.getTexture(
		TextureFile::fromName(TextureName::GameWorldInterface));
	int gameInterfaceWidth, gameInterfaceHeight;
	SDL_QueryTexture(const_cast<SDL_Texture*>(gameInterface), nullptr, nullptr,
		&gameInterfaceWidth, &gameInterfaceHeight);

	this->drawScaledToNative(gameInterface,
		(ORIGINAL_WIDTH / 2) - (gameInterfaceWidth / 2),
		ORIGINAL_HEIGHT - gameInterfaceHeight,
		gameInterfaceWidth,
		gameInterfaceHeight,
		renderer);

	// Compass frame.
	const auto &compassFrame = textureManager.getSurface(
		TextureFile::fromName(TextureName::CompassFrame));
	SDL_SetColorKey(compassFrame.getSurface(), SDL_TRUE, Color::Black.toRGB());

	// Compass slider (the actual headings). +X is north, +Z is east.
	const auto &compassSlider = textureManager.getSurface(
		TextureFile::fromName(TextureName::CompassSlider));

	Surface compassSliderSegment(32, 7);
	compassSlider.blit(compassSliderSegment, Int2(), Rect(60, 0,
		compassSliderSegment.getWidth(), compassSliderSegment.getHeight()));

	// Should do some sin() and cos() functions to get the segment location.
	//int segmentX = ...;

	// Fill in transparent edges behind compass slider (due to SDL blit truncation).
	Surface compassFiller(36, 11);
	compassFiller.fill(Color(205, 186, 155));

	this->drawScaledToNative(compassFiller,
		(ORIGINAL_WIDTH / 2) - (compassFrame.getWidth() / 2) + 1,
		5,
		compassFiller.getWidth(),
		compassFiller.getHeight(),
		renderer);

	this->drawScaledToNative(compassSliderSegment,
		(ORIGINAL_WIDTH / 2) - 16,
		7,
		compassSliderSegment.getWidth(),
		compassSliderSegment.getHeight(),
		renderer);

	this->drawScaledToNative(compassFrame,
		(ORIGINAL_WIDTH / 2) - (compassFrame.getWidth() / 2),
		0,
		compassFrame.getWidth(),
		compassFrame.getHeight(),
		renderer);

	// Draw cursor.
	const auto &cursor = textureManager.getSurface(
		TextureFile::fromName(TextureName::SwordCursor));
	this->drawCursor(cursor, renderer);
}
<commit_msg>Fill in small edge on game world interface.<commit_after>#include <cassert>

#include "SDL.h"

#include "GameWorldPanel.h"

#include "AutomapPanel.h"
#include "Button.h"
#include "CharacterPanel.h"
#include "LogbookPanel.h"
#include "PauseMenuPanel.h"
#include "WorldMapPanel.h"
#include "../Entities/CoordinateFrame.h"
#include "../Entities/Player.h"
#include "../Game/GameData.h"
#include "../Game/GameState.h"
#include "../Game/Options.h"
#include "../Math/Constants.h"
#include "../Math/Int2.h"
#include "../Math/Random.h"
#include "../Math/Rect.h"
#include "../Media/AudioManager.h"
#include "../Media/Color.h"
#include "../Media/MusicName.h"
#include "../Media/PaletteName.h"
#include "../Media/SoundName.h"
#include "../Media/TextureFile.h"
#include "../Media/TextureManager.h"
#include "../Media/TextureName.h"
#include "../Rendering/CLProgram.h"
#include "../Rendering/Renderer.h"
#include "../Utilities/Debug.h"

GameWorldPanel::GameWorldPanel(GameState *gameState)
	: Panel(gameState)
{
	assert(gameState->gameDataIsActive());

	this->automapButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> automapPanel(new AutomapPanel(gameState));
			gameState->setPanel(std::move(automapPanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();

	this->characterSheetButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> sheetPanel(new CharacterPanel(gameState));
			gameState->setPanel(std::move(sheetPanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();

	this->logbookButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> logbookPanel(new LogbookPanel(gameState));
			gameState->setPanel(std::move(logbookPanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();

	this->pauseButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> pausePanel(new PauseMenuPanel(gameState));
			gameState->setPanel(std::move(pausePanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();

	this->worldMapButton = []()
	{
		auto function = [](GameState *gameState)
		{
			std::unique_ptr<Panel> mapPanel(new WorldMapPanel(gameState));
			gameState->setPanel(std::move(mapPanel));
		};
		return std::unique_ptr<Button>(new Button(function));
	}();
}

GameWorldPanel::~GameWorldPanel()
{

}

void GameWorldPanel::handleEvents(bool &running)
{
	SDL_Event e;
	while (SDL_PollEvent(&e) != 0)
	{
		bool applicationExit = (e.type == SDL_QUIT);
		bool resized = (e.type == SDL_WINDOWEVENT) &&
			(e.window.event == SDL_WINDOWEVENT_RESIZED);
		bool escapePressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_ESCAPE);

		if (applicationExit)
		{
			running = false;
		}
		if (resized)
		{
			int width = e.window.data1;
			int height = e.window.data2;
			this->getGameState()->resizeWindow(width, height);
		}
		if (escapePressed)
		{
			this->pauseButton->click(this->getGameState());
		}

		bool leftClick = (e.type == SDL_MOUSEBUTTONDOWN) &&
			(e.button.button == SDL_BUTTON_LEFT);
		bool activateHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_e);
		bool automapHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_n);
		bool logbookHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_l);
		bool sheetHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_TAB);
		bool worldMapHotkeyPressed = (e.type == SDL_KEYDOWN) &&
			(e.key.keysym.sym == SDLK_m);

		if (leftClick)
		{
			// Interface buttons? Entities in the world?
		}
		if (activateHotkeyPressed)
		{
			// Activate whatever is looked at.
		}
		else if (automapHotkeyPressed)
		{
			// Go to the automap.
			this->automapButton->click(this->getGameState());
		}
		else if (logbookHotkeyPressed)
		{
			// Go to the logbook.
			this->logbookButton->click(this->getGameState());
		}
		else if (sheetHotkeyPressed)
		{
			// Go to the character screen.
			this->characterSheetButton->click(this->getGameState());
		}
		else if (worldMapHotkeyPressed)
		{
			// Go to the world map.
			this->worldMapButton->click(this->getGameState());
		}
	}
}

void GameWorldPanel::handleMouse(double dt)
{
	static_cast<void>(dt);

	// Make the camera look around.
	int dx, dy;
	const auto mouse = SDL_GetRelativeMouseState(&dx, &dy);

	// The program will eventually not require holding a mouse button to turn.
	bool leftClick = (mouse & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0;
	bool rightClick = (mouse & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
	bool turning = ((dx != 0) || (dy != 0)) && (leftClick || rightClick);

	if (turning)
	{
		auto dimensions = this->getGameState()->getScreenDimensions();
		double dxx = static_cast<double>(dx) / static_cast<double>(dimensions.getX());
		double dyy = static_cast<double>(dy) / static_cast<double>(dimensions.getY());

		// Pitch and/or yaw the camera.
		const auto &options = this->getGameState()->getOptions();
		this->getGameState()->getGameData()->getPlayer().rotate(dxx, -dyy,
			options.getHorizontalSensitivity(), options.getVerticalSensitivity(),
			options.getVerticalFOV());
	}
}

void GameWorldPanel::handleKeyboard(double dt)
{
	// Listen for WASD, jump...
	const auto keys = SDL_GetKeyboardState(nullptr);

	bool forward = keys[SDL_SCANCODE_W] != 0;
	bool backward = keys[SDL_SCANCODE_S] != 0;
	bool left = keys[SDL_SCANCODE_A] != 0;
	bool right = keys[SDL_SCANCODE_D] != 0;
	bool jump = keys[SDL_SCANCODE_SPACE] != 0;

	bool any = forward || backward || left || right || jump;

	if (any)
	{
		bool isRunning = keys[SDL_SCANCODE_LSHIFT] != 0;
		auto &player = this->getGameState()->getGameData()->getPlayer();

		// Get some relevant player direction data.
		Float2d groundDirection = player.getGroundDirection();
		Float3d groundDirection3D = Float3d(groundDirection.getX(), 0.0,
			groundDirection.getY()).normalized();
		Float3d rightDirection = player.getFrame().getRight().normalized();

		// Calculate the acceleration direction based on input.
		Float3d accelDirection = Float3d(0.0, 0.0, 0.0);
		if (forward)
		{
			accelDirection = accelDirection + groundDirection3D;
		}
		if (backward)
		{
			accelDirection = accelDirection - groundDirection3D;
		}
		if (right)
		{
			accelDirection = accelDirection + rightDirection;
		}
		if (left)
		{
			accelDirection = accelDirection - rightDirection;
		}

		// To do: check jump eventually once gravity and ground collision are implemented.

		// Use a normalized direction.
		accelDirection = accelDirection.normalized();

		// Set the magnitude of the acceleration to some arbitrary numbers. These values
		// are independent of max speed. The original game didn't have sprinting, but it
		// seems like something relevant to do anyway (at least in testing).
		double accelMagnitude = isRunning ? 35.0 : 10.0;

		// Change the player's velocity if valid.
		if (std::isfinite(accelDirection.length()))
		{
			player.accelerate(accelDirection, accelMagnitude, isRunning, dt);
		}
	}
}

void GameWorldPanel::tick(double dt, bool &running)
{
	assert(this->getGameState()->gameDataIsActive());

	this->handleEvents(running);
	this->handleMouse(dt);
	this->handleKeyboard(dt);

	// Animate the game world.
	auto *gameData = this->getGameState()->getGameData();
	gameData->incrementGameTime(dt);

	// Tick the player.
	auto &player = gameData->getPlayer();
	player.tick(this->getGameState(), dt);

	// Update CLProgram members that are refreshed each frame.
	double verticalFOV = this->getGameState()->getOptions().getVerticalFOV();
	auto &clProgram = gameData->getCLProgram();
	clProgram.updateCamera(player.getPosition(), player.getDirection(), verticalFOV);
	clProgram.updateGameTime(gameData->getGameTime());
}

void GameWorldPanel::render(SDL_Renderer *renderer, const SDL_Rect *letterbox)
{
	assert(this->getGameState()->gameDataIsActive());

	// Draw game world using OpenCL rendering.
	this->getGameState()->getGameData()->getCLProgram().render(renderer);

	// Interface objects (stat bars, compass, ...) should snap to the edges of the native
	// screen, not just the letterbox, because right now, when the screen is tall, the
	// compass is near the middle of the screen (in the way), and the stat bars are much
	// higher than they should be. I haven't figured out yet what the equation is. I
	// think it requires using the original height and the draw scale somehow.

	// Set screen palette.
	auto &textureManager = this->getGameState()->getTextureManager();
	textureManager.setPalette(PaletteName::Default);

	// Draw game world interface.
	const auto *gameInterface = textureManager.getTexture(
		TextureFile::fromName(TextureName::GameWorldInterface));
	int gameInterfaceWidth, gameInterfaceHeight;
	SDL_QueryTexture(const_cast<SDL_Texture*>(gameInterface), nullptr, nullptr,
		&gameInterfaceWidth, &gameInterfaceHeight);

	this->drawScaledToNative(gameInterface,
		(ORIGINAL_WIDTH / 2) - (gameInterfaceWidth / 2),
		ORIGINAL_HEIGHT - gameInterfaceHeight,
		gameInterfaceWidth,
		gameInterfaceHeight,
		renderer);

	// Compass frame.
	const auto &compassFrame = textureManager.getSurface(
		TextureFile::fromName(TextureName::CompassFrame));
	SDL_SetColorKey(compassFrame.getSurface(), SDL_TRUE, Color::Black.toRGB());

	// Compass slider (the actual headings). +X is north, +Z is east.
	const auto &compassSlider = textureManager.getSurface(
		TextureFile::fromName(TextureName::CompassSlider));

	Surface compassSliderSegment(32, 7);
	compassSlider.blit(compassSliderSegment, Int2(), Rect(60, 0,
		compassSliderSegment.getWidth(), compassSliderSegment.getHeight()));

	// Should do some sin() and cos() functions to get the segment location.
	//int segmentX = ...;

	// Fill in edges behind interface objects due to SDL blit truncation.
	Surface mainFiller(gameInterfaceWidth, 2);
	mainFiller.fill(Color(15, 15, 27));

	this->drawScaledToNative(mainFiller,
		(ORIGINAL_WIDTH / 2) - (mainFiller.getWidth() / 2),
		ORIGINAL_HEIGHT - (mainFiller.getHeight() - 1),
		mainFiller.getWidth(),
		mainFiller.getHeight(),
		renderer);

	Surface compassFiller(36, 11);
	compassFiller.fill(Color(205, 186, 155));

	this->drawScaledToNative(compassFiller,
		(ORIGINAL_WIDTH / 2) - (compassFrame.getWidth() / 2) + 1,
		5,
		compassFiller.getWidth(),
		compassFiller.getHeight(),
		renderer);

	this->drawScaledToNative(compassSliderSegment,
		(ORIGINAL_WIDTH / 2) - 16,
		7,
		compassSliderSegment.getWidth(),
		compassSliderSegment.getHeight(),
		renderer);

	this->drawScaledToNative(compassFrame,
		(ORIGINAL_WIDTH / 2) - (compassFrame.getWidth() / 2),
		0,
		compassFrame.getWidth(),
		compassFrame.getHeight(),
		renderer);

	// Draw cursor.
	const auto &cursor = textureManager.getSurface(
		TextureFile::fromName(TextureName::SwordCursor));
	this->drawCursor(cursor, renderer);
}
<|endoftext|>


<commit_before>//=====================================================================//
/*! @file
    @brief  GR-KAEDE_net (RX64M) メイン @n
			Copyright 2017 Kunihito Hiramatsu
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/rspi_io.hpp"
#include "common/sdc_io.hpp"
#include "common/fifo.hpp"
#include "common/cmt_io.hpp"
#include "common/sci_io.hpp"
#include "common/format.hpp"
#include "common/input.hpp"
#include "common/fixed_string.hpp"

#include "chip/phy_base.hpp"
#include "net2/net_main.hpp"
//#include "net/http_server.hpp"

namespace {

	typedef device::ETHERC0 ETHERC;      // Ethernet Controller
	typedef device::EDMAC0 EDMAC;        // Ethernet DMA Controller
	typedef chip::phy_base<ETHERC> PHY;  // Ethernet PHY (LAN8720)
	typedef device::ether_io<ETHERC, EDMAC, PHY> ETHER_IO;
	ETHER_IO 	ether_;

	volatile bool tcpip_flag_ = false;
	volatile uint32_t net_int_cnt_ = 0;

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  CMT タスク
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class cmt_task {

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		cmt_task() { }

		//-----------------------------------------------------------------//
		/*!
			@brief  オペレーター ()
		*/
		//-----------------------------------------------------------------//
		void operator() () {
		}
	};

	typedef device::cmt_io<device::CMT0, cmt_task> CMT0;
	CMT0	cmt_;

	typedef utils::fifo<uint8_t, 4096> BUFFER;
	typedef device::sci_io<device::SCI7, BUFFER, BUFFER> SCI;
	SCI		sci_;

	// SDC 用　SPI 定義（RSPI）
	typedef device::rspi_io<device::RSPI> SPI;
	SPI		spi_;

	typedef device::PORT<device::PORTC, device::bitpos::B4> SDC_SELECT;	///< カード選択信号
	typedef device::NULL_PORT  SDC_POWER;	///< カード電源制御（常に電源ＯＮ）
	typedef device::PORT<device::PORTB, device::bitpos::B7> SDC_DETECT;	///< カード検出

	typedef utils::sdc_io<SPI, SDC_SELECT, SDC_POWER, SDC_DETECT> SDC;
	SDC		sdc_(spi_, 20000000);

	typedef utils::rtc_io RTC;
	RTC		rtc_;

	static const uint32_t UDPN = 4;  // UDP の経路数
 	static const uint32_t TCPN = 6;  // TCP の経路数
	typedef net::net_main<ETHER_IO, UDPN, TCPN> NET_MAIN;
	NET_MAIN	net_(ether_);

//	typedef net::http_server<ETHER_IO, SDC> HTTP;
//	HTTP		http_(ether_, sdc_);
}

extern "C" {

	//-----------------------------------------------------------------//
	/*!
		@brief  システム・文字出力
		@param[in]	ch	文字
	*/
	//-----------------------------------------------------------------//
	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  システム・文字列出力
		@param[in]	s	文字列
	*/
	//-----------------------------------------------------------------//
	void sci_puts(const char* s)
	{
		sci_.puts(s);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  システム・文字入力
		@return	文字
	*/
	//-----------------------------------------------------------------//
	char sci_getch(void)
	{
		return sci_.getch();
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  システム・文字列長の取得
		@return	文字列長
	*/
	//-----------------------------------------------------------------//
	uint16_t sci_length(void)
	{
		return sci_.recv_length();
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  GMT 時間の取得
		@return GMT 時間
	*/
	//-----------------------------------------------------------------//
	time_t get_time()
	{
		time_t t = 0;
		rtc_.get_time(t);
		return t;
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へ初期化関数を提供
		@param[in]	drv		Physical drive nmuber (0)
		@return ステータス
	 */
	//-----------------------------------------------------------------//
	DSTATUS disk_initialize(BYTE drv) {
		return sdc_.at_mmc().disk_initialize(drv);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へステータスを提供
		@param[in]	drv		Physical drive nmuber (0)
	 */
	//-----------------------------------------------------------------//
	DSTATUS disk_status(BYTE drv) {
		return sdc_.at_mmc().disk_status(drv);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へリード・セクターを提供
		@param[in]	drv		Physical drive nmuber (0)
		@param[out]	buff	Pointer to the data buffer to store read data
		@param[in]	sector	Start sector number (LBA)
		@param[in]	count	Sector count (1..128)
		@return リザルト
	 */
	//-----------------------------------------------------------------//
	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_read(drv, buff, sector, count);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へライト・セクターを提供
		@param[in]	drv		Physical drive nmuber (0)
		@param[in]	buff	Pointer to the data to be written
		@param[in]	sector	Start sector number (LBA)
		@param[in]	count	Sector count (1..128)
		@return リザルト
	 */
	//-----------------------------------------------------------------//
	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_write(drv, buff, sector, count);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へI/O コントロールを提供
		@param[in]	drv		Physical drive nmuber (0)
		@param[in]	ctrl	Control code
		@param[in]	buff	Buffer to send/receive control data
		@return リザルト
	 */
	//-----------------------------------------------------------------//
	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdc_.at_mmc().disk_ioctl(drv, ctrl, buff);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へ時間を提供
		@return FatFs 時間
	 */
	//-----------------------------------------------------------------//
	DWORD get_fattime(void) {
		auto t = get_time();
		return utils::str::get_fattime(t);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	UTF-8 から ShiftJIS への変換
		@param[in]	src	UTF-8 文字列ソース
		@param[out]	dst	ShiftJIS 文字列出力
	 */
	//-----------------------------------------------------------------//
	void utf8_to_sjis(const char* src, char* dst) {
		utils::str::utf8_to_sjis(src, dst);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	イーサーネット・割り込みタスク
	 */
	//-----------------------------------------------------------------//
	void ether_process_(void)
	{
		net_.process();
	}
}

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

int main(int argc, char** argv)
{
	device::init_port();

	device::PORTC::PDR.B0 = 1; // output
	device::PORTC::PDR.B1 = 1; // output
	device::PORT0::PDR.B2 = 1; // output
	device::PORT0::PDR.B3 = 1; // output

	{  // GR-KAEDE の SPI 端子のハードバグ回避
	   // ※PC3 から、PC7 へ １K オームで接続
		device::PORTC::PDR.B3 = 1; // output
		device::PORTC::PODR.B3 = 1;
	}

	device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

	device::SYSTEM::MOSCWTCR = 9;	// 1ms wait
	// メインクロック強制発振とドライブ能力設定
	device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV2.b(0b10)
						  | device::SYSTEM::MOFCR.MOFXIN.b(1);
	device::SYSTEM::MOSCCR.MOSTP = 0;		// メインクロック発振器動作
	while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) asm("nop");

	// Base Clock 12MHz
	device::SYSTEM::PLLCR.STC = 0b010011;		// PLL 10 倍(120MHz)
	device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
	while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) asm("nop");

	device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(1)		// 1/2 (120/2=60)
						  | device::SYSTEM::SCKCR.ICK.b(0)		// 1/1 (120/1=120)
						  | device::SYSTEM::SCKCR.BCK.b(1)		// 1/2 (120/2=60)
						  | device::SYSTEM::SCKCR.PCKA.b(0)		// 1/1 (120/1=120)
						  | device::SYSTEM::SCKCR.PCKB.b(1)		// 1/2 (120/2=60)
						  | device::SYSTEM::SCKCR.PCKC.b(1)		// 1/2 (120/2=60)
						  | device::SYSTEM::SCKCR.PCKD.b(1);	// 1/2 (120/2=60)
	device::SYSTEM::SCKCR2.UCK = 0b0100;  // USB Clock: 1/5 (120/5=24)
	device::SYSTEM::SCKCR3.CKSEL = 0b100;	///< PLL 選択

	{  // タイマー設定、１００Ｈｚ（１０ｍｓ）
		uint8_t int_level = 1;
		cmt_.start(100, int_level);
	}

	{  // SCI 設定
		uint8_t int_level = 2;
		sci_.start(115200, int_level);
	}

	utils::format("\nStart GR-KAEDE Net2 Stack Sample\n");

	// SD カード・クラスの初期化
	sdc_.start();

	{  // Ethernet の開始
		uint8_t intr_level = 4;
		ether_.start(intr_level);

		static uint8_t mac[6] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
		net_.start(mac);

		ether_.set_intr_task(ether_process_);
	}

#if 0
	{  // HTTP サーバーの設定
		http_.start("GR-KAEDE_net HTTP Server");

		// ルート・ページ設定
		http_.set_link("/", "", [=](void) {
			time_t t = get_time();
			struct tm *m = localtime(&t);
			HTTP::http_format("%s %s %d %02d:%02d:%02d  %4d
\n")
				% get_wday(m->tm_wday)
				% get_mon(m->tm_mon)
				% static_cast<uint32_t>(m->tm_mday)
				% static_cast<uint32_t>(m->tm_hour)
				% static_cast<uint32_t>(m->tm_min)
				% static_cast<uint32_t>(m->tm_sec)
				% static_cast<uint32_t>(m->tm_year + 1900);

			http_.tag_hr(500, 3);
		} );
	}
#endif

	uint32_t cnt = 0;
	while(1) {  // 100Hz (10ms interval)
		cmt_.sync();

		sdc_.service();

		net_.service();
#if 0
		bool l = net_.check_link();
		if(l) {
			http_.service();
		}
#endif
		device::PORTC::PODR.B0 = (((cnt + 0)  & 31) < 8) ? 1 : 0;
		device::PORTC::PODR.B1 = (((cnt + 8)  & 31) < 8) ? 1 : 0;
		device::PORT0::PODR.B2 = (((cnt + 16) & 31) < 8) ? 1 : 0;
		device::PORT0::PODR.B3 = (((cnt + 24) & 31) < 8) ? 1 : 0;
		++cnt;
	}
}
<commit_msg>update sci_put exclusive control<commit_after>//=====================================================================//
/*! @file
    @brief  GR-KAEDE_net (RX64M) メイン @n
			Copyright 2017 Kunihito Hiramatsu
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/rspi_io.hpp"
#include "common/sdc_io.hpp"
#include "common/fifo.hpp"
#include "common/cmt_io.hpp"
#include "common/sci_io.hpp"
#include "common/format.hpp"
#include "common/input.hpp"
#include "common/fixed_string.hpp"

#include "chip/phy_base.hpp"
#include "net2/net_main.hpp"
//#include "net/http_server.hpp"

namespace {

	typedef device::ETHERC0 ETHERC;      // Ethernet Controller
	typedef device::EDMAC0 EDMAC;        // Ethernet DMA Controller
	typedef chip::phy_base<ETHERC> PHY;  // Ethernet PHY (LAN8720)
	typedef device::ether_io<ETHERC, EDMAC, PHY> ETHER_IO;
	ETHER_IO 	ether_;

	volatile bool tcpip_flag_ = false;
	volatile uint32_t net_int_cnt_ = 0;

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  CMT タスク
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class cmt_task {

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		cmt_task() { }

		//-----------------------------------------------------------------//
		/*!
			@brief  オペレーター ()
		*/
		//-----------------------------------------------------------------//
		void operator() () {
		}
	};

	typedef device::cmt_io<device::CMT0, cmt_task> CMT0;
	CMT0	cmt_;

	typedef utils::fifo<uint8_t, 4096> BUFFER;
	typedef device::sci_io<device::SCI7, BUFFER, BUFFER> SCI;
	SCI		sci_;

	// SDC 用　SPI 定義（RSPI）
	typedef device::rspi_io<device::RSPI> SPI;
	SPI		spi_;

	typedef device::PORT<device::PORTC, device::bitpos::B4> SDC_SELECT;	///< カード選択信号
	typedef device::NULL_PORT  SDC_POWER;	///< カード電源制御（常に電源ＯＮ）
	typedef device::PORT<device::PORTB, device::bitpos::B7> SDC_DETECT;	///< カード検出

	typedef utils::sdc_io<SPI, SDC_SELECT, SDC_POWER, SDC_DETECT> SDC;
	SDC		sdc_(spi_, 20000000);

	typedef utils::rtc_io RTC;
	RTC		rtc_;

	static const uint32_t UDPN = 4;  // UDP の経路数
 	static const uint32_t TCPN = 6;  // TCP の経路数
	typedef net::net_main<ETHER_IO, UDPN, TCPN> NET_MAIN;
	NET_MAIN	net_(ether_);

//	typedef net::http_server<ETHER_IO, SDC> HTTP;
//	HTTP		http_(ether_, sdc_);
}

extern "C" {

	//-----------------------------------------------------------------//
	/*!
		@brief  システム・文字出力 @n
				※割り込み対応
		@param[in]	ch	文字
	*/
	//-----------------------------------------------------------------//
	void sci_putch(char ch)
	{
		static volatile bool lock = false;
		static utils::fifo<uint8_t, 1024> tmp;
		if(lock) {
			if((tmp.size() - tmp.length() - 1) > 0) {
				tmp.put(ch);
			}
		}
		lock = true;
		while(tmp.length() > 0) {
			sci_.putch(tmp.get());
		}
		sci_.putch(ch);
		lock = false;
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  システム・文字列出力
		@param[in]	s	文字列
	*/
	//-----------------------------------------------------------------//
	void sci_puts(const char* s)
	{
		sci_.puts(s);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  システム・文字入力
		@return	文字
	*/
	//-----------------------------------------------------------------//
	char sci_getch(void)
	{
		return sci_.getch();
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  システム・文字列長の取得
		@return	文字列長
	*/
	//-----------------------------------------------------------------//
	uint16_t sci_length(void)
	{
		return sci_.recv_length();
	}

	//-----------------------------------------------------------------//
	/*!
		@brief  GMT 時間の取得
		@return GMT 時間
	*/
	//-----------------------------------------------------------------//
	time_t get_time()
	{
		time_t t = 0;
		rtc_.get_time(t);
		return t;
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へ初期化関数を提供
		@param[in]	drv		Physical drive nmuber (0)
		@return ステータス
	 */
	//-----------------------------------------------------------------//
	DSTATUS disk_initialize(BYTE drv) {
		return sdc_.at_mmc().disk_initialize(drv);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へステータスを提供
		@param[in]	drv		Physical drive nmuber (0)
	 */
	//-----------------------------------------------------------------//
	DSTATUS disk_status(BYTE drv) {
		return sdc_.at_mmc().disk_status(drv);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へリード・セクターを提供
		@param[in]	drv		Physical drive nmuber (0)
		@param[out]	buff	Pointer to the data buffer to store read data
		@param[in]	sector	Start sector number (LBA)
		@param[in]	count	Sector count (1..128)
		@return リザルト
	 */
	//-----------------------------------------------------------------//
	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_read(drv, buff, sector, count);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へライト・セクターを提供
		@param[in]	drv		Physical drive nmuber (0)
		@param[in]	buff	Pointer to the data to be written
		@param[in]	sector	Start sector number (LBA)
		@param[in]	count	Sector count (1..128)
		@return リザルト
	 */
	//-----------------------------------------------------------------//
	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_write(drv, buff, sector, count);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へI/O コントロールを提供
		@param[in]	drv		Physical drive nmuber (0)
		@param[in]	ctrl	Control code
		@param[in]	buff	Buffer to send/receive control data
		@return リザルト
	 */
	//-----------------------------------------------------------------//
	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdc_.at_mmc().disk_ioctl(drv, ctrl, buff);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	FatFs へ時間を提供
		@return FatFs 時間
	 */
	//-----------------------------------------------------------------//
	DWORD get_fattime(void) {
		auto t = get_time();
		return utils::str::get_fattime(t);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	UTF-8 から ShiftJIS への変換
		@param[in]	src	UTF-8 文字列ソース
		@param[out]	dst	ShiftJIS 文字列出力
	 */
	//-----------------------------------------------------------------//
	void utf8_to_sjis(const char* src, char* dst) {
		utils::str::utf8_to_sjis(src, dst);
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	イーサーネット・割り込みタスク
	 */
	//-----------------------------------------------------------------//
	void ether_process_(void)
	{
		net_.process();
	}
}

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

int main(int argc, char** argv)
{
	device::init_port();

	device::PORTC::PDR.B0 = 1; // output
	device::PORTC::PDR.B1 = 1; // output
	device::PORT0::PDR.B2 = 1; // output
	device::PORT0::PDR.B3 = 1; // output

	{  // GR-KAEDE の SPI 端子のハードバグ回避
	   // ※PC3 から、PC7 へ １K オームで接続
		device::PORTC::PDR.B3 = 1; // output
		device::PORTC::PODR.B3 = 1;
	}

	device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

	device::SYSTEM::MOSCWTCR = 9;	// 1ms wait
	// メインクロック強制発振とドライブ能力設定
	device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV2.b(0b10)
						  | device::SYSTEM::MOFCR.MOFXIN.b(1);
	device::SYSTEM::MOSCCR.MOSTP = 0;		// メインクロック発振器動作
	while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) asm("nop");

	// Base Clock 12MHz
	device::SYSTEM::PLLCR.STC = 0b010011;		// PLL 10 倍(120MHz)
	device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
	while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) asm("nop");

	device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(1)		// 1/2 (120/2=60)
						  | device::SYSTEM::SCKCR.ICK.b(0)		// 1/1 (120/1=120)
						  | device::SYSTEM::SCKCR.BCK.b(1)		// 1/2 (120/2=60)
						  | device::SYSTEM::SCKCR.PCKA.b(0)		// 1/1 (120/1=120)
						  | device::SYSTEM::SCKCR.PCKB.b(1)		// 1/2 (120/2=60)
						  | device::SYSTEM::SCKCR.PCKC.b(1)		// 1/2 (120/2=60)
						  | device::SYSTEM::SCKCR.PCKD.b(1);	// 1/2 (120/2=60)
	device::SYSTEM::SCKCR2.UCK = 0b0100;  // USB Clock: 1/5 (120/5=24)
	device::SYSTEM::SCKCR3.CKSEL = 0b100;	///< PLL 選択

	{  // タイマー設定、１００Ｈｚ（１０ｍｓ）
		uint8_t int_level = 1;
		cmt_.start(100, int_level);
	}

	{  // SCI 設定
		uint8_t int_level = 2;
		sci_.start(115200, int_level);
	}

	utils::format("\nStart GR-KAEDE Net2 Stack Sample\n");

	// SD カード・クラスの初期化
	sdc_.start();

	{  // Ethernet の開始
		uint8_t intr_level = 4;
		ether_.start(intr_level);

		static uint8_t mac[6] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
		net_.start(mac);

		ether_.set_intr_task(ether_process_);
	}

#if 0
	{  // HTTP サーバーの設定
		http_.start("GR-KAEDE_net HTTP Server");

		// ルート・ページ設定
		http_.set_link("/", "", [=](void) {
			time_t t = get_time();
			struct tm *m = localtime(&t);
			HTTP::http_format("%s %s %d %02d:%02d:%02d  %4d
\n")
				% get_wday(m->tm_wday)
				% get_mon(m->tm_mon)
				% static_cast<uint32_t>(m->tm_mday)
				% static_cast<uint32_t>(m->tm_hour)
				% static_cast<uint32_t>(m->tm_min)
				% static_cast<uint32_t>(m->tm_sec)
				% static_cast<uint32_t>(m->tm_year + 1900);

			http_.tag_hr(500, 3);
		} );
	}
#endif

	uint32_t cnt = 0;
	while(1) {  // 100Hz (10ms interval)
		cmt_.sync();

		sdc_.service();

		net_.service();
#if 0
		bool l = net_.check_link();
		if(l) {
			http_.service();
		}
#endif
		device::PORTC::PODR.B0 = (((cnt + 0)  & 31) < 8) ? 1 : 0;
		device::PORTC::PODR.B1 = (((cnt + 8)  & 31) < 8) ? 1 : 0;
		device::PORT0::PODR.B2 = (((cnt + 16) & 31) < 8) ? 1 : 0;
		device::PORT0::PODR.B3 = (((cnt + 24) & 31) < 8) ? 1 : 0;
		++cnt;
	}
}
<|endoftext|>


<commit_before>#pragma once

#include "..\Quantities\Dimensionless.hpp"
#include "..\Quantities\Quantities.hpp"
#include <string>

namespace Principia {
namespace Geometry {
  template<typename Scalar>
  struct R3Element {
   public:
    R3Element(Scalar const& x, Scalar const& y, Scalar const& z) :
      x(x), y(y), z(z) {};

    Scalar&       operator[] (int const index);
    Scalar& const operator[] (int const index) const;

    Scalar x;
    Scalar y;
    Scalar z;
  };

template<typename T>
R3Element<T> operator+ (R3Element<T> const& right);
template<typename T>
R3Element<T> operator- (R3Element<T> const& right);
template<typename T>

R3Element<T> operator+ (R3Element<T> const& left, R3Element<T> const& right);
template<typename T>
R3Element<T> operator- (R3Element<T> const& left, R3Element<T> const& right);
template<typename T>

R3Element<T> operator* (Quantities::Dimensionless const& left,
                        R3Element<T> const& right);
template<typename T>
R3Element<T> operator* (R3Element<T> const& left,
                        Quantities::Dimensionless const& right);
template<typename T>
R3Element<T> operator/ (R3Element<T> const& left,
                        Quantities::Dimensionless const& right);

template<typename T, typename U>
R3Element<Quantities::Product<U, T>> operator* (U const& left,
                                                R3Element<T> const& right);
template<typename T, typename U>
R3Element<Quantities::Product<T, U>> operator* (R3Element<T> const& left,
                                                U const& right);
template<typename T, typename U>
R3Element<Quantities::Quotient<T, U>> operator/ (R3Element<T> const& left,
                                                 U const& right);

template<typename T>
R3Element<T> operator+= (R3Element<T>& left, R3Element<T> const& right);
template<typename T>
R3Element<T> operator-= (R3Element<T>& left, R3Element<T> const& right);

template<typename T>
R3Element<T> operator*= (R3Element<T>& left,
                         Quantities::Dimensionless const& right);
template<typename T>
R3Element<T> operator/= (R3Element<T>& left,
                         Quantities::Dimensionless const& right);

template<typename T, typename U>
R3Element<Quantities::Product<T, U>> Cross(R3Element<T> const& left,
                                           R3Element<U> const& right);
template<typename T, typename U>
Quantities::Product<T, U> Dot(R3Element<T> const& left,
                              R3Element<U> const& right);
}
}
<commit_msg>Edited some comments.<commit_after>#pragma once

#include "..\Quantities\Dimensionless.hpp"
#include "..\Quantities\Quantities.hpp"
#include <string>

namespace Principia {
namespace Geometry {
  // R3Element is an element of a 3-dimensional dimensionful vector space on the
  // field R, represented by Dimensionless. It is the underlying data type for
  // the more advanced strongly typed structures of the Grassmann algebras and
  // affine spaces.
  template<typename Scalar>
  struct R3Element {
   public:
    R3Element(Scalar const& x, Scalar const& y, Scalar const& z) :
      x(x), y(y), z(z) {};

    Scalar&       operator[] (int const index);
    Scalar& const operator[] (int const index) const;

    Scalar x;
    Scalar y;
    Scalar z;
  };

template<typename T>
R3Element<T> operator+ (R3Element<T> const& right);
template<typename T>
R3Element<T> operator- (R3Element<T> const& right);
template<typename T>

R3Element<T> operator+ (R3Element<T> const& left, R3Element<T> const& right);
template<typename T>
R3Element<T> operator- (R3Element<T> const& left, R3Element<T> const& right);
template<typename T>

R3Element<T> operator* (Quantities::Dimensionless const& left,
                        R3Element<T> const& right);
template<typename T>
R3Element<T> operator* (R3Element<T> const& left,
                        Quantities::Dimensionless const& right);
template<typename T>
R3Element<T> operator/ (R3Element<T> const& left,
                        Quantities::Dimensionless const& right);

// These operations are actually tensor products with dimensionful 1-dimensional
// vectors, see [Tao 2012].
template<typename T, typename U>
R3Element<Quantities::Product<U, T>> operator* (U const& left,
                                                R3Element<T> const& right);
template<typename T, typename U>
R3Element<Quantities::Product<T, U>> operator* (R3Element<T> const& left,
                                                U const& right);
template<typename T, typename U>
R3Element<Quantities::Quotient<T, U>> operator/ (R3Element<T> const& left,
                                                 U const& right);

template<typename T>
R3Element<T> operator+= (R3Element<T>& left, R3Element<T> const& right);
template<typename T>
R3Element<T> operator-= (R3Element<T>& left, R3Element<T> const& right);

template<typename T>
R3Element<T> operator*= (R3Element<T>& left,
                         Quantities::Dimensionless const& right);
template<typename T>
R3Element<T> operator/= (R3Element<T>& left,
                         Quantities::Dimensionless const& right);

template<typename T, typename U>
R3Element<Quantities::Product<T, U>> Cross(R3Element<T> const& left,
                                           R3Element<U> const& right);
template<typename T, typename U>
Quantities::Product<T, U> Dot(R3Element<T> const& left,
                              R3Element<U> const& right);
}
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include <limits>

#include "Eigen/Dense"

#include "cyber/common/log.h"
#include "modules/common/math/linear_quadratic_regulator.h"

namespace apollo {
namespace common {
namespace math {

using Matrix = Eigen::MatrixXd;

void SolveLQRProblem(const Matrix &A, const Matrix &B, const Matrix &Q,
                     const Matrix &R, const double tolerance,
                     const uint max_num_iteration, Matrix *ptr_K) {
  if (A.rows() != A.cols() || B.rows() != A.rows() || Q.rows() != Q.cols() ||
      Q.rows() != A.rows() || R.rows() != R.cols() || R.rows() != B.cols()) {
    AERROR << "LQR solver: one or more matrices have incompatible dimensions.";
    return;
  }

  Matrix AT = A.transpose();
  Matrix BT = B.transpose();

  // Solves a discrete-time Algebraic Riccati equation (DARE)
  // Calculate Matrix Difference Riccati Equation, initialize P and Q
  Matrix P = Q;
  uint num_iteration = 0;
  double diff = std::numeric_limits<double>::max();
  while (num_iteration++ < max_num_iteration && diff > tolerance) {
    Matrix P_next =
        AT * P * A - AT * P * B * (R + BT * P * B).inverse() * BT * P * A + Q;
    // check the difference between P and P_next
    diff = fabs((P_next - P).maxCoeff());
    P = P_next;
  }

  if (num_iteration >= max_num_iteration) {
    ADEBUG << "LQR solver cannot converge to a solution, "
              "last consecutive result diff. is:"
           << diff;
  } else {
    ADEBUG << "LQR solver converged at iteration: " << num_iteration
           << ", max consecutive result diff.: " << diff;
  }
  *ptr_K = (R + BT * P * B).inverse() * BT * P * A;
}

}  // namespace math
}  // namespace common
}  // namespace apollo
<commit_msg>Update linear_quadratic_regulator.cc<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include <limits>

#include "Eigen/Dense"

#include "cyber/common/log.h"
#include "modules/common/math/linear_quadratic_regulator.h"

namespace apollo {
namespace common {
namespace math {

using Matrix = Eigen::MatrixXd;

void SolveLQRProblem(const Matrix &A, const Matrix &B, const Matrix &Q,
                     const Matrix &R, const double tolerance,
                     const uint max_num_iteration, Matrix *ptr_K) {
  if (A.rows() != A.cols() || B.rows() != A.rows() || Q.rows() != Q.cols() ||
      Q.rows() != A.rows() || R.rows() != R.cols() || R.rows() != B.cols()) {
    AERROR << "LQR solver: one or more matrices have incompatible dimensions.";
    return;
  }

  Matrix AT = A.transpose();
  Matrix BT = B.transpose();

  // Solves a discrete-time Algebraic Riccati equation (DARE)
  // Calculate Matrix Difference Riccati Equation, initialize P and Q
  Matrix P = Q;
  uint num_iteration = 0;
  double diff = std::numeric_limits<double>::max();
  while (num_iteration++ < max_num_iteration && diff > tolerance) {
    Matrix P_next =
        AT * P * A - AT * P * B * (R + BT * P * B).inverse() * BT * P * A + Q;
    // check the difference between P and P_next
    diff = fabs((P_next - P).maxCoeff());
    P = P_next;
  }

  if (num_iteration >= max_num_iteration) {
    ADEBUG << "LQR solver cannot converge to a solution, "
              "last consecutive result diff is: "
           << diff;
  } else {
    ADEBUG << "LQR solver converged at iteration: " << num_iteration
           << ", max consecutive result diff.: " << diff;
  }
  *ptr_K = (R + BT * P * B).inverse() * BT * P * A;
}

}  // namespace math
}  // namespace common
}  // namespace apollo
<|endoftext|>


<commit_before>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.

#include "../precomp.hpp"
#include "layers_common.hpp"

namespace cv
{
namespace dnn
{

// Quantize FP32/FP16 Inputs to INT8
class QuantizeLayerImpl CV_FINAL : public QuantizeLayer
{
public:
    QuantizeLayerImpl(const LayerParams& params)
    {
        scale = params.get<float>("scales", 1.0f);
        zeropoint = params.get<int>("zeropoints", 0);
        setParamsFrom(params);
    }

    virtual bool supportBackend(int backendId) CV_OVERRIDE
    {
        return backendId == DNN_BACKEND_OPENCV;
    }

    bool getMemoryShapes(const std::vector<MatShape> &inputs,
                         const int requiredOutputs,
                         std::vector<MatShape> &outputs,
                         std::vector<MatShape> &internals) const CV_OVERRIDE
    {
        CV_Assert(inputs.size() == 1);
        Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
        return false;
    }

    virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
    {
        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);
    }

#ifdef HAVE_OPENCL
    bool forward_ocl(InputArrayOfArrays inputs_, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_)
    {
        std::vector<UMat> inputs, outputs;
        inputs_.getUMatVector(inputs);
        outputs_.getUMatVector(outputs);

        if (inputs_.depth() == CV_16S)
        {
            UMat inputFp32(shape(inputs[0]), CV_32F);
            convertFp16(inputs[0], inputFp32);
            inputFp32.copyTo(inputs[0]);
        }

        inputs[0].convertTo(outputs[0], CV_8S, 1.f/scale, zeropoint);
        return true;
    }
#endif

    void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
    {
        CV_TRACE_FUNCTION();
        CV_TRACE_ARG_VALUE(name, "name", name.c_str());

        CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
                   forward_ocl(inputs_arr, outputs_arr, internals_arr))

        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);

        inputs[0].convertTo(outputs[0], CV_8S, 1.f/scale, zeropoint);
    }
};

// Dequantize INT8 Inputs to FP32/FP16
class DequantizeLayerImpl CV_FINAL : public DequantizeLayer
{
public:
    DequantizeLayerImpl(const LayerParams& params)
    {
        scale = params.get<float>("scales", 1.0f);
        zeropoint = params.get<int>("zeropoints", 0);
        setParamsFrom(params);
    }

    virtual bool supportBackend(int backendId) CV_OVERRIDE
    {
        return backendId == DNN_BACKEND_OPENCV;
    }

    bool getMemoryShapes(const std::vector<MatShape> &inputs,
                         const int requiredOutputs,
                         std::vector<MatShape> &outputs,
                         std::vector<MatShape> &internals) const CV_OVERRIDE
    {
        CV_Assert(inputs.size() == 1);
        Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
        return false;
    }

    virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
    {
        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);
    }

#ifdef HAVE_OPENCL
    bool forward_ocl(InputArrayOfArrays inputs_, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_)
    {
        std::vector<UMat> inputs, outputs;
        inputs_.getUMatVector(inputs);
        outputs_.getUMatVector(outputs);

        UMat outputFp32(shape(outputs[0]), CV_32F);
        inputs[0].convertTo(outputFp32, CV_32F, scale, -(scale*zeropoint));

        if (outputs_.depth() == CV_16S)
            convertFp16(outputFp32, outputs[0]);
        else
            outputFp32.copyTo(outputs[0]);
        return true;
    }
#endif

    void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
    {
        CV_TRACE_FUNCTION();
        CV_TRACE_ARG_VALUE(name, "name", name.c_str());

        CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
                   forward_ocl(inputs_arr, outputs_arr, internals_arr))

        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);

        inputs[0].convertTo(outputs[0], CV_32F, scale, -(scale*zeropoint));
    }
};

// Rescale/Requantize INT8 Inputs from (scale1, zeropoint1) to (scale2, zeropoint2)
class RequantizeLayerImpl CV_FINAL : public RequantizeLayer
{
public:
    RequantizeLayerImpl(const LayerParams& params)
    {
        scale = params.get<float>("scale", 1.f);
        shift = params.get<float>("shift", 0.f);
        setParamsFrom(params);
    }

    virtual bool supportBackend(int backendId) CV_OVERRIDE
    {
        return backendId == DNN_BACKEND_OPENCV;
    }

    bool getMemoryShapes(const std::vector<MatShape> &inputs,
                         const int requiredOutputs,
                         std::vector<MatShape> &outputs,
                         std::vector<MatShape> &internals) const CV_OVERRIDE
    {
        CV_Assert(inputs.size() == 1);
        Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
        return false;
    }

    virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
    {
        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);
    }

    void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
    {
        CV_TRACE_FUNCTION();
        CV_TRACE_ARG_VALUE(name, "name", name.c_str());

        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);

        inputs[0].convertTo(outputs[0], CV_8S, scale, shift);
    }
};

Ptr<QuantizeLayer> QuantizeLayer::create(const LayerParams& params)
{
    return Ptr<QuantizeLayer>(new QuantizeLayerImpl(params));
}

Ptr<DequantizeLayer> DequantizeLayer::create(const LayerParams& params)
{
    return Ptr<DequantizeLayer>(new DequantizeLayerImpl(params));
}

Ptr<RequantizeLayer> RequantizeLayer::create(const LayerParams& params)
{
    return Ptr<RequantizeLayer>(new RequantizeLayerImpl(params));
}

}
}
<commit_msg>dnn(int8): fix using of incorrect UMat constructor<commit_after>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.

#include "../precomp.hpp"
#include "layers_common.hpp"

namespace cv
{
namespace dnn
{

// Quantize FP32/FP16 Inputs to INT8
class QuantizeLayerImpl CV_FINAL : public QuantizeLayer
{
public:
    QuantizeLayerImpl(const LayerParams& params)
    {
        scale = params.get<float>("scales", 1.0f);
        zeropoint = params.get<int>("zeropoints", 0);
        setParamsFrom(params);
    }

    virtual bool supportBackend(int backendId) CV_OVERRIDE
    {
        return backendId == DNN_BACKEND_OPENCV;
    }

    bool getMemoryShapes(const std::vector<MatShape> &inputs,
                         const int requiredOutputs,
                         std::vector<MatShape> &outputs,
                         std::vector<MatShape> &internals) const CV_OVERRIDE
    {
        CV_Assert(inputs.size() == 1);
        Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
        return false;
    }

    virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
    {
        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);
    }

#ifdef HAVE_OPENCL
    bool forward_ocl(InputArrayOfArrays inputs_, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_)
    {
        std::vector<UMat> inputs, outputs;
        inputs_.getUMatVector(inputs);
        outputs_.getUMatVector(outputs);

        if (inputs_.depth() == CV_16S)
        {
            UMat inputFp32;
            convertFp16(inputs[0], inputFp32);
            inputs[0] = inputFp32;  // replace
        }

        inputs[0].convertTo(outputs[0], CV_8S, 1.f/scale, zeropoint);
        return true;
    }
#endif

    void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
    {
        CV_TRACE_FUNCTION();
        CV_TRACE_ARG_VALUE(name, "name", name.c_str());

        CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
                   forward_ocl(inputs_arr, outputs_arr, internals_arr))

        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);

        inputs[0].convertTo(outputs[0], CV_8S, 1.f/scale, zeropoint);
    }
};

// Dequantize INT8 Inputs to FP32/FP16
class DequantizeLayerImpl CV_FINAL : public DequantizeLayer
{
public:
    DequantizeLayerImpl(const LayerParams& params)
    {
        scale = params.get<float>("scales", 1.0f);
        zeropoint = params.get<int>("zeropoints", 0);
        setParamsFrom(params);
    }

    virtual bool supportBackend(int backendId) CV_OVERRIDE
    {
        return backendId == DNN_BACKEND_OPENCV;
    }

    bool getMemoryShapes(const std::vector<MatShape> &inputs,
                         const int requiredOutputs,
                         std::vector<MatShape> &outputs,
                         std::vector<MatShape> &internals) const CV_OVERRIDE
    {
        CV_Assert(inputs.size() == 1);
        Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
        return false;
    }

    virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
    {
        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);
    }

#ifdef HAVE_OPENCL
    bool forward_ocl(InputArrayOfArrays inputs_, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_)
    {
        std::vector<UMat> inputs, outputs;
        inputs_.getUMatVector(inputs);
        outputs_.getUMatVector(outputs);

        UMat outputFp32;
        inputs[0].convertTo(outputFp32, CV_32F, scale, -(scale*zeropoint));

        if (outputs_.depth() == CV_16S)
            convertFp16(outputFp32, outputs[0]);
        else
            outputFp32.copyTo(outputs[0]);
        return true;
    }
#endif

    void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
    {
        CV_TRACE_FUNCTION();
        CV_TRACE_ARG_VALUE(name, "name", name.c_str());

        CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
                   forward_ocl(inputs_arr, outputs_arr, internals_arr))

        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);

        inputs[0].convertTo(outputs[0], CV_32F, scale, -(scale*zeropoint));
    }
};

// Rescale/Requantize INT8 Inputs from (scale1, zeropoint1) to (scale2, zeropoint2)
class RequantizeLayerImpl CV_FINAL : public RequantizeLayer
{
public:
    RequantizeLayerImpl(const LayerParams& params)
    {
        scale = params.get<float>("scale", 1.f);
        shift = params.get<float>("shift", 0.f);
        setParamsFrom(params);
    }

    virtual bool supportBackend(int backendId) CV_OVERRIDE
    {
        return backendId == DNN_BACKEND_OPENCV;
    }

    bool getMemoryShapes(const std::vector<MatShape> &inputs,
                         const int requiredOutputs,
                         std::vector<MatShape> &outputs,
                         std::vector<MatShape> &internals) const CV_OVERRIDE
    {
        CV_Assert(inputs.size() == 1);
        Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
        return false;
    }

    virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
    {
        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);
    }

    void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
    {
        CV_TRACE_FUNCTION();
        CV_TRACE_ARG_VALUE(name, "name", name.c_str());

        std::vector<Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);

        inputs[0].convertTo(outputs[0], CV_8S, scale, shift);
    }
};

Ptr<QuantizeLayer> QuantizeLayer::create(const LayerParams& params)
{
    return Ptr<QuantizeLayer>(new QuantizeLayerImpl(params));
}

Ptr<DequantizeLayer> DequantizeLayer::create(const LayerParams& params)
{
    return Ptr<DequantizeLayer>(new DequantizeLayerImpl(params));
}

Ptr<RequantizeLayer> RequantizeLayer::create(const LayerParams& params)
{
    return Ptr<RequantizeLayer>(new RequantizeLayerImpl(params));
}

}
}
<|endoftext|>