<commit_before>/*
The MIT License

Copyright (c) 2011 by Jorrit Tyberghein

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
 */

#include <crystalspace.h>

#include "listctrltools.h"

csStringArray ListCtrlTools::ReadRow (wxListCtrl* list, int row)
{
  wxListItem rowInfo;
  csStringArray rc;

  rowInfo.m_itemId = row;
  rowInfo.m_mask = wxLIST_MASK_TEXT;
  for (int i = 0 ; i < list->GetColumnCount () ; i++)
  {
    rowInfo.m_col = i;
    list->GetItem (rowInfo);
    csString col = (const char*)(rowInfo.m_text.mb_str (wxConvUTF8));
    rc.Push (col);
  }
  return rc;
}

long ListCtrlTools::AddRow (wxListCtrl* list, const char* value, ...)
{
  long idx = list->InsertItem (list->GetItemCount (), wxString (value, wxConvUTF8));
  int col = 1;
  va_list args;
  va_start (args, value);
  const char* value2 = va_arg (args, char*);
  while (value2 != 0)
  {
    list->SetItem (idx, col++, wxString (value2, wxConvUTF8));
    value2 = va_arg (args, char*);
  }
  for (int i = 0 ; i < col ; i++)
    list->SetColumnWidth (i, wxLIST_AUTOSIZE | wxLIST_AUTOSIZE_USEHEADER);
  return idx;
}

void ListCtrlTools::ColorRow (wxListCtrl* list, int idx,
    unsigned char red, unsigned char green, unsigned char blue)
{
  wxListItem rowInfo;

  rowInfo.m_itemId = idx;
  rowInfo.m_mask = wxLIST_MASK_TEXT;
  for (int i = 0 ; i < list->GetColumnCount () ; i++)
  {
    rowInfo.m_col = i;
    list->GetItem (rowInfo);
    rowInfo.SetTextColour (wxColour (red, green, blue));
    list->SetItem (rowInfo);
  }
}

void ListCtrlTools::BackgroundColorRow (wxListCtrl* list, int idx,
    unsigned char red, unsigned char green, unsigned char blue)
{
  wxListItem rowInfo;

  rowInfo.m_itemId = idx;
  rowInfo.m_mask = wxLIST_MASK_TEXT;
  for (int i = 0 ; i < list->GetColumnCount () ; i++)
  {
    rowInfo.m_col = i;
    list->GetItem (rowInfo);
    rowInfo.SetBackgroundColour (wxColour (red, green, blue));
    list->SetItem (rowInfo);
  }
}

void ListCtrlTools::SetColumn (wxListCtrl* list, int idx, const char* name, int width)
{
  wxListItem colPath;
  colPath.SetId (idx);
  colPath.SetText (wxString (name, wxConvUTF8));
  colPath.SetWidth (width);
  list->InsertColumn (idx, colPath);
}

<commit_msg>Fixed autoresize so it works for columns and contents.<commit_after>/*
The MIT License

Copyright (c) 2011 by Jorrit Tyberghein

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
 */

#include <crystalspace.h>

#include "listctrltools.h"

csStringArray ListCtrlTools::ReadRow (wxListCtrl* list, int row)
{
  wxListItem rowInfo;
  csStringArray rc;

  rowInfo.m_itemId = row;
  rowInfo.m_mask = wxLIST_MASK_TEXT;
  for (int i = 0 ; i < list->GetColumnCount () ; i++)
  {
    rowInfo.m_col = i;
    list->GetItem (rowInfo);
    csString col = (const char*)(rowInfo.m_text.mb_str (wxConvUTF8));
    rc.Push (col);
  }
  return rc;
}

long ListCtrlTools::AddRow (wxListCtrl* list, const char* value, ...)
{
  long idx = list->InsertItem (list->GetItemCount (), wxString (value, wxConvUTF8));
  int col = 1;
  va_list args;
  va_start (args, value);
  const char* value2 = va_arg (args, char*);
  while (value2 != 0)
  {
    list->SetItem (idx, col++, wxString (value2, wxConvUTF8));
    value2 = va_arg (args, char*);
  }
  for (int i = 0 ; i < col ; i++)
    list->SetColumnWidth (i, wxLIST_AUTOSIZE_USEHEADER);
  return idx;
}

void ListCtrlTools::ColorRow (wxListCtrl* list, int idx,
    unsigned char red, unsigned char green, unsigned char blue)
{
  wxListItem rowInfo;

  rowInfo.m_itemId = idx;
  rowInfo.m_mask = wxLIST_MASK_TEXT;
  for (int i = 0 ; i < list->GetColumnCount () ; i++)
  {
    rowInfo.m_col = i;
    list->GetItem (rowInfo);
    rowInfo.SetTextColour (wxColour (red, green, blue));
    list->SetItem (rowInfo);
  }
}

void ListCtrlTools::BackgroundColorRow (wxListCtrl* list, int idx,
    unsigned char red, unsigned char green, unsigned char blue)
{
  wxListItem rowInfo;

  rowInfo.m_itemId = idx;
  rowInfo.m_mask = wxLIST_MASK_TEXT;
  for (int i = 0 ; i < list->GetColumnCount () ; i++)
  {
    rowInfo.m_col = i;
    list->GetItem (rowInfo);
    rowInfo.SetBackgroundColour (wxColour (red, green, blue));
    list->SetItem (rowInfo);
  }
}

void ListCtrlTools::SetColumn (wxListCtrl* list, int idx, const char* name, int width)
{
  wxListItem colPath;
  colPath.SetId (idx);
  colPath.SetText (wxString (name, wxConvUTF8));
  colPath.SetWidth (width);
  list->InsertColumn (idx, colPath);
}

<|endoftext|>


<commit_before><commit_msg>+ log<commit_after><|endoftext|>


<commit_before>#include "forward_intersection.h"

#include <cmath>
#include "..//Basics//Matrix//matrix.h"
#include "..//Basics//rot_matrix.h"
#include "..//Basics//straight_line.h"

//###################################################################################
double Vorwaertsschnitt::Zaehler_x(Cam K, Point OP_0, Matrix& R)
{
	double Z;
  	Z =   R(0,0) * (OP_0.get_X() - K.get_OX())
		+ R(1,0) * (OP_0.get_Y() - K.get_OY())
		+ R(2,0) * (OP_0.get_Z() - K.get_OZ());
	return Z;
}

double Vorwaertsschnitt::Zaehler_y(Cam K, Point OP_0, Matrix& R)
{
	double Z;
	Z =   R(0,1) * (OP_0.get_X() - K.get_OX())
		+ R(1,1) * (OP_0.get_Y() - K.get_OY())
		+ R(2,1) * (OP_0.get_Z() - K.get_OZ());
	return Z;
}

double Vorwaertsschnitt::Nenner(Cam K, Point OP_0, Matrix& R)
{
	double N;
	N =   R(0,2) * (OP_0.get_X() - K.get_OX())
		+ R(1,2) * (OP_0.get_Y() - K.get_OY())
		+ R(2,2) * (OP_0.get_Z() - K.get_OZ());
	return N;
}

double Vorwaertsschnitt::dxdX(Cam K, double Zx, double N, Matrix& R)
{
	double A;
    A = (K.get_c() * (R(0,2) * Zx - R(0,0) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dxdY(Cam K, double Zx, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(1,2) * Zx - R(1,0) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dxdZ(Cam K, double Zx, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(2,2) * Zx - R(2,0) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dydX(Cam K, double Zy, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(0,2) * Zy - R(0,1) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dydY(Cam K, double Zy, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(1,2) * Zy - R(1,1) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dydZ(Cam K, double Zy, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(2,2) * Zy - R(2,1) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::lx(Cam K, Point OP_0, double BP_x, Matrix& R)
{
	double l;
	double BP_x0;
	BP_x0 =  K.get_c() * (Zaehler_x(K,OP_0,R) / Nenner(K, OP_0,R)); // ohne xh + dx
	l = (-1.0)*(BP_x - BP_x0);
	return l;
}

double Vorwaertsschnitt::ly(Cam K, Point OP_0, double BP_y, Matrix& R)
{
	double l;
	double BP_y0;
	BP_y0 =  K.get_c() * (Zaehler_y(K,OP_0,R) / Nenner(K, OP_0,R)); // ohne yh + dy
	l = (-1.0)*(BP_y - BP_y0);
	return l;
}

double Vorwaertsschnitt::x(Cam K, Point OP_0, Matrix& R)
{
	double BP_x0;
	BP_x0 =  K.get_c() * (Zaehler_x(K,OP_0,R) / Nenner(K, OP_0,R)); // ohne xh + dx
	return BP_x0;
}

double Vorwaertsschnitt::y(Cam K, Point OP_0, Matrix& R)
{
	double BP_y0;
	BP_y0 =  K.get_c() * (Zaehler_y(K,OP_0,R) / Nenner(K, OP_0,R)); // ohne yh + dy
	return BP_y0;
}

//###################################################################################

Vorwaertsschnitt::Vorwaertsschnitt(vector<BPoint> &BP)//,Point Org
{
 if(BP.size()>1)
 {
 m_is_error=false;

 //###############################################
 //Nherungsberechnung des Schnittpunktes
 //2 Geraden die sich schneiden (sollten)

 BPoint BP1 = BP[0];
 BPoint BP2 = BP[1];

 //cout <<endl<<"m: "<< BP1.get_m()<<" n: "<<BP1.get_n()<< flush;
 //cout <<endl<<"m: "<< BP2.get_m()<<" n: "<<BP2.get_n()<< flush;

 Gerade G_l(BP1.get_Point(),BP1.get_Cam().get_O());
 Gerade G_r(BP2.get_Point(),BP2.get_Cam().get_O());

 m_schnittpunkt=G_l.Schnitt(G_r);

 //cout <<endl<<"schnittp: "<< m_schnittpunkt;
 //###############################################
 //Vorwrtsschnitt

 Point OP_0;
 OP_0=m_schnittpunkt; // Zuweisen des Nherungswertes

 //Anzahl der verfgbaren Bildpunkte:
 int anzahl = BP.size();

 /*
 //###############################################
 //	Kontrollrechnung
   double x_st_l,y_st_l,x_st_r,y_st_r,x_korr_l,x_unkorr_l,y_korr_l,y_unkorr_l,x_korr_r,x_unkorr_r,y_korr_r,y_unkorr_r;
   double dx_l,dy_l,dx_r,dy_r;

    x_st_l = x(K1,OP_0,R1);
	x_korr_l=BP1.get_xyBKooKorr().get_X();
	x_unkorr_l=BP1.get_xyBKoo().get_X();
    dx_l=x_st_l-x_korr_l;

	y_st_l = y(K1,OP_0,R1);
    y_korr_l=BP1.get_xyBKooKorr().get_Y();
	y_unkorr_l=BP1.get_xyBKoo().get_Y();
	dy_l=y_st_l-y_korr_l;

	x_st_r = x(K2,OP_0,R2);
	x_korr_r=BP2.get_xyBKooKorr().get_X();
	x_unkorr_r=BP2.get_xyBKoo().get_X();
    dx_r=x_st_r-x_korr_r;

	y_st_r = y(K2,OP_0,R2);
    y_korr_r=BP2.get_xyBKooKorr().get_Y();
	y_unkorr_r=BP2.get_xyBKoo().get_Y();
	dy_r=y_st_r-y_korr_r;
 //#################################################
*/

 //Punkt OP -> Neu berechneter(ausgeglichener) ObjektPunkt;
 Point OP;

 int i=0,k,j; //Laufvariable fr Abbruch
 Point dOP(100,100,100); //Differenz zwischen dem NherungsObjektpunkt und neu berechnetem Objektpunkt

while(!( fabs(dOP.get_X())<0.00000001 && fabs(dOP.get_Y())<0.00000001 && fabs(dOP.get_Z())<0.00000001 ) )
{
	Matrix A(anzahl*2,3,Null);
	Matrix l(anzahl*2,1,Null);
	for(k=0,j=0;k<anzahl*2;k=k+2,j++)
	{
		BPoint BB  = BP[j];
		Cam KK     = BB.get_Cam();
	    Rot R_hilf(KK.get_rotX(),KK.get_rotY(),KK.get_rotZ());
		Matrix RR;
		RR = R_hilf;//.get_Matrix();
		A(k  ,0) = dxdX(KK, Zaehler_x(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);
		A(k  ,1) = dxdY(KK, Zaehler_x(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);
		A(k  ,2) = dxdZ(KK, Zaehler_x(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);

		A(k+1,0) = dydX(KK, Zaehler_y(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);
		A(k+1,1) = dydY(KK, Zaehler_y(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);
		A(k+1,2) = dydZ(KK, Zaehler_y(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);

		l(k  ,0) = lx(KK,OP_0,BB.get_xyBKooKorr().get_X(),RR);
		l(k+1,0) = ly(KK,OP_0,BB.get_xyBKooKorr().get_Y(),RR);
	}

	//A.MatShow();
	//l.MatShow();

	Matrix N(3,3,Null);
	N = A.MatTrans().MatMult(A);
	//N.MatShow();

	Matrix Q(3,3,Null);
	Q = N.MatInvert();
	//Q.MatShow();

    Matrix tx;
    tx=A.MatTrans().MatMult(l);

	Matrix x;//(3,1,Null);
	x = Q.MatMult( tx );
	//x.MatShow();

	// Anbringen der "dX Verbesserung" x an den Nherungsobjektpunkt
	OP.set_X( OP_0.get_X() + x(0,0));
	OP.set_Y( OP_0.get_Y() + x(1,0));
	OP.set_Z( OP_0.get_Z() + x(2,0));

	//setzen der neuen Nherung und der Differenz zwischen altem und neuen Objektpunkt
    dOP=OP_0.Subt(OP);
    //Point dS3=Org.Subt(OP);//Kontrolle
	OP_0=OP;

	// Berechnung der Verbesserungen
	Matrix v(anzahl*2,1,Null);
	v = A.MatMult(x).MatSub( l );
	//v.MatShow();

	//Berechnung der Standardabweichung a posteriori
	Matrix vv;
	vv=v.MatTrans().MatMult(v);
	double s0 = sqrt(vv(0,0)/(anzahl*2-3));

	//Berechnung der Standardabweichung der ausgeglichenen Objektkoordinaten
	double sx, sy, sz;
	sx = s0 * sqrt( Q(0,0) ) *3;
	sy = s0 * sqrt( Q(1,1) ) *3;
	sz = s0 * sqrt( Q(2,2) ) *3;

	//setzen der Standardabweichnug
    OP.set_dX( sx );
	OP.set_dY( sy );
	OP.set_dZ( sz );

 ++i;
 if(i>1000)
 {
     m_is_error=true;
	 break;
	 //cout<< "i ist grer als 1000!!!\n";
 }

}//Ende der while-Schleife

 m_schnittpunkt=OP;

 }
 else m_is_error=true;
}
<commit_msg><commit_after>#include "forward_intersection.h"

#include <cmath>
#include "..//Basics//Matrix//matrix.h"
#include "..//Basics//rot_matrix.h"
#include "..//Basics//straight_line.h"

//###################################################################################
double Vorwaertsschnitt::Zaehler_x(Cam K, Point OP_0, Matrix& R)
{
	double Z;
  	Z =   R(0,0) * (OP_0.get_X() - K.get_OX())
		+ R(1,0) * (OP_0.get_Y() - K.get_OY())
		+ R(2,0) * (OP_0.get_Z() - K.get_OZ());
	return Z;
}

double Vorwaertsschnitt::Zaehler_y(Cam K, Point OP_0, Matrix& R)
{
	double Z;
	Z =   R(0,1) * (OP_0.get_X() - K.get_OX())
		+ R(1,1) * (OP_0.get_Y() - K.get_OY())
		+ R(2,1) * (OP_0.get_Z() - K.get_OZ());
	return Z;
}

double Vorwaertsschnitt::Nenner(Cam K, Point OP_0, Matrix& R)
{
	double N;
	N =   R(0,2) * (OP_0.get_X() - K.get_OX())
		+ R(1,2) * (OP_0.get_Y() - K.get_OY())
		+ R(2,2) * (OP_0.get_Z() - K.get_OZ());
	return N;
}

double Vorwaertsschnitt::dxdX(Cam K, double Zx, double N, Matrix& R)
{
	double A;
    A = (K.get_c() * (R(0,2) * Zx - R(0,0) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dxdY(Cam K, double Zx, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(1,2) * Zx - R(1,0) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dxdZ(Cam K, double Zx, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(2,2) * Zx - R(2,0) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dydX(Cam K, double Zy, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(0,2) * Zy - R(0,1) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dydY(Cam K, double Zy, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(1,2) * Zy - R(1,1) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::dydZ(Cam K, double Zy, double N, Matrix& R)
{
	double A;
	A = (K.get_c() * (R(2,2) * Zy - R(2,1) * N)) / (N * N);
	return A;
}

double Vorwaertsschnitt::lx(Cam K, Point OP_0, double BP_x, Matrix& R)
{
	double l;
	double BP_x0;
	BP_x0 =  K.get_c() * (Zaehler_x(K,OP_0,R) / Nenner(K, OP_0,R)); // ohne xh + dx
	l = (-1.0)*(BP_x - BP_x0);
	return l;
}

double Vorwaertsschnitt::ly(Cam K, Point OP_0, double BP_y, Matrix& R)
{
	double l;
	double BP_y0;
	BP_y0 =  K.get_c() * (Zaehler_y(K,OP_0,R) / Nenner(K, OP_0,R)); // ohne yh + dy
	l = (-1.0)*(BP_y - BP_y0);
	return l;
}

double Vorwaertsschnitt::x(Cam K, Point OP_0, Matrix& R)
{
	double BP_x0;
	BP_x0 =  K.get_c() * (Zaehler_x(K,OP_0,R) / Nenner(K, OP_0,R)); // ohne xh + dx
	return BP_x0;
}

double Vorwaertsschnitt::y(Cam K, Point OP_0, Matrix& R)
{
	double BP_y0;
	BP_y0 =  K.get_c() * (Zaehler_y(K,OP_0,R) / Nenner(K, OP_0,R)); // ohne yh + dy
	return BP_y0;
}

//###################################################################################

Vorwaertsschnitt::Vorwaertsschnitt(vector<BPoint> &BP)//,Point Org
{
 if(BP.size()>1)
 {
 m_is_error=false;

 //###############################################
 //Nherungsberechnung des Schnittpunktes
 //2 Geraden die sich schneiden (sollten)

 BPoint BP1 = BP[0];
 BPoint BP2 = BP[1];

 //cout <<endl<<"m: "<< BP1.get_m()<<" n: "<<BP1.get_n()<< flush;
 //cout <<endl<<"m: "<< BP2.get_m()<<" n: "<<BP2.get_n()<< flush;

 Gerade G_l(BP1.get_Point(),BP1.get_Cam().get_O());
 Gerade G_r(BP2.get_Point(),BP2.get_Cam().get_O());

 m_schnittpunkt=G_l.Schnitt(G_r);

 //cout <<endl<<"schnittp: "<< m_schnittpunkt;
 //###############################################
 //Vorwrtsschnitt

 Point OP_0;
 OP_0=m_schnittpunkt; // Zuweisen des Nherungswertes

 //Anzahl der verfgbaren Bildpunkte:
 int anzahl = BP.size();

 /*
 //###############################################
 //	Kontrollrechnung
   double x_st_l,y_st_l,x_st_r,y_st_r,x_korr_l,x_unkorr_l,y_korr_l,y_unkorr_l,x_korr_r,x_unkorr_r,y_korr_r,y_unkorr_r;
   double dx_l,dy_l,dx_r,dy_r;

    x_st_l = x(K1,OP_0,R1);
	x_korr_l=BP1.get_xyBKooKorr().get_X();
	x_unkorr_l=BP1.get_xyBKoo().get_X();
    dx_l=x_st_l-x_korr_l;

	y_st_l = y(K1,OP_0,R1);
    y_korr_l=BP1.get_xyBKooKorr().get_Y();
	y_unkorr_l=BP1.get_xyBKoo().get_Y();
	dy_l=y_st_l-y_korr_l;

	x_st_r = x(K2,OP_0,R2);
	x_korr_r=BP2.get_xyBKooKorr().get_X();
	x_unkorr_r=BP2.get_xyBKoo().get_X();
    dx_r=x_st_r-x_korr_r;

	y_st_r = y(K2,OP_0,R2);
    y_korr_r=BP2.get_xyBKooKorr().get_Y();
	y_unkorr_r=BP2.get_xyBKoo().get_Y();
	dy_r=y_st_r-y_korr_r;
 //#################################################
*/

 //Punkt OP -> Neu berechneter(ausgeglichener) ObjektPunkt;
 Point OP;

 int i=0,k,j; //Laufvariable fr Abbruch
 Point dOP(100,100,100); //Differenz zwischen dem NherungsObjektpunkt und neu berechnetem Objektpunkt

while(!( fabs(dOP.get_X())<0.00000001 && fabs(dOP.get_Y())<0.00000001 && fabs(dOP.get_Z())<0.00000001 ) )
{
	Matrix A(anzahl*2,3,Null);
	Matrix l(anzahl*2,1,Null);
	for(k=0,j=0;k<anzahl*2;k=k+2,j++)
	{
		BPoint BB  = BP[j];
		Cam KK     = BB.get_Cam();
	    Rot R_hilf(KK.get_rotX(),KK.get_rotY(),KK.get_rotZ());
		Matrix RR;
		RR = R_hilf;//.get_Matrix();
		A(k  ,0) = dxdX(KK, Zaehler_x(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);
		A(k  ,1) = dxdY(KK, Zaehler_x(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);
		A(k  ,2) = dxdZ(KK, Zaehler_x(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);

		A(k+1,0) = dydX(KK, Zaehler_y(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);
		A(k+1,1) = dydY(KK, Zaehler_y(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);
		A(k+1,2) = dydZ(KK, Zaehler_y(KK,OP_0,RR), Nenner(KK,OP_0,RR), RR);

		l(k  ,0) = lx(KK,OP_0,BB.get_xyBKooKorr().get_X(),RR);
		l(k+1,0) = ly(KK,OP_0,BB.get_xyBKooKorr().get_Y(),RR);
	}

	//A.MatShow();
	//l.MatShow();

	Matrix N(3,3,Null);
	N = A.MatTrans().MatMult(A);
	//N.MatShow();

	Matrix Q(3,3,Null);
	Q = N.MatInvert();
	//Q.MatShow();

    Matrix tx;
    tx=A.MatTrans().MatMult(l);

	Matrix x;//(3,1,Null);
	x = Q.MatMult( tx );
	//x.MatShow();

	// Anbringen der "dX Verbesserung" x an den Nherungsobjektpunkt
	OP.set_X( OP_0.get_X() + x(0,0));
	OP.set_Y( OP_0.get_Y() + x(1,0));
	OP.set_Z( OP_0.get_Z() + x(2,0));

	//setzen der neuen Nherung und der Differenz zwischen altem und neuen Objektpunkt
    dOP=OP_0.Subt(OP);
    //Point dS3=Org.Subt(OP);//Kontrolle
	OP_0=OP;

	// Berechnung der Verbesserungen
	Matrix v(anzahl*2,1,Null);
	v = A.MatMult(x).MatSub( l );
	//v.MatShow();

	//Berechnung der Standardabweichung a posteriori
	Matrix vv;
	vv=v.MatTrans().MatMult(v);
	double s0 = sqrt(vv(0,0)/(anzahl*2-3));

	//Berechnung der Standardabweichung der ausgeglichenen Objektkoordinaten
	double sx, sy, sz;
	sx = s0 * sqrt( Q(0,0) ) *3;
	sy = s0 * sqrt( Q(1,1) ) *3;
	sz = s0 * sqrt( Q(2,2) ) *3;

	//setzen der Standardabweichnug
    OP.set_dX( sx );
	OP.set_dY( sy );
	OP.set_dZ( sz );

 ++i;
 if(i>1000)
 {
     m_is_error=true;
	 break;
	 //cout<< "i ist grer als 1000!!!\n";
 }

}//Ende der while-Schleife

 m_schnittpunkt=OP;

 }
 else m_is_error=true;
}
<|endoftext|>


<commit_before><commit_msg>メニュー展開時に発生していたセグメンテーション違反を修正した<commit_after><|endoftext|>


<commit_before>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

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.
*/

#ifndef __BASIC_RESEMBLA_HPP__
#define __BASIC_RESEMBLA_HPP__

#include <string>
#include <fstream>
#include <vector>
#include <unordered_map>
#include <memory>
#include <stdexcept>
#include <mutex>

#include "simstring/simstring.h"

#include "resembla_interface.hpp"
#include "reranker.hpp"

namespace resembla {

// Resembla with a fixed pair of preprocessor and score function
template<
    typename Preprocessor,
    typename ScoreFunction
>
class BasicResembla: public ResemblaInterface
{
public:
    BasicResembla(const std::string& db_path, const std::string& inverse_path,
            const int simstring_measure, const double simstring_threshold, const size_t max_reranking_num,
            std::shared_ptr<Preprocessor> preprocess, std::shared_ptr<ScoreFunction> score_func,
            bool preprocess_corpus = true, size_t preprocessed_data_col = 0):
        simstring_measure(simstring_measure), simstring_threshold(simstring_threshold), max_reranking_num(max_reranking_num),
        reranker(), preprocess(preprocess), score_func(score_func), preprocess_corpus(preprocess_corpus)
    {
        db.open(db_path);
        std::basic_ifstream<string_type::value_type> ifs(inverse_path);
        if(ifs.fail()){
            throw std::runtime_error("input file is not available: " + inverse_path);
        }
        auto delimiter = cast_string<string_type>(std::string("\t"));
        while(ifs.good()){
            string_type line;
            std::getline(ifs, line);
            if(ifs.eof() || line.length() == 0){
                break;
            }

            auto columns = split(line, L'\t');
            if(columns.size() < 2){
                throw std::runtime_error("invalid line in " + inverse_path + ": " + cast_string<std::string>(line));
            }
            const auto& indexed = columns[0];
            auto original = columns[1];

            // due to the limited interface of preprocessors, concatenate extra data to the original text
            if(preprocessed_data_col > 0 && preprocessed_data_col - 1 < columns.size() && !columns[preprocessed_data_col - 1].empty()){
                original += delimiter + columns[preprocessed_data_col - 1];
            }

            const auto& i = inverse.find(indexed);
            if(i == std::end(inverse)){
                inverse[indexed] = {original};
            }
            else{
                inverse.at(indexed).push_back(original);
            }

            if(preprocess_corpus){
                preprocessed_corpus[columns[1]] = std::make_pair(columns[1], (*preprocess)(original, true));
            }
        }
    }

    std::vector<output_type> find(const string_type& query, double threshold = 0.0, size_t max_response = 0) const
    {
        // search from N-gram index
        std::vector<string_type> simstring_result;
        {
            std::lock_guard<std::mutex> lock(mutex_simstring);
            string_type search_query = preprocess->index(query);
            db.retrieve(search_query, simstring_measure, simstring_threshold, std::back_inserter(simstring_result));
            if(simstring_result.empty()){
                return {};
            }
        }

        std::vector<string_type> candidate_texts;
        for(const auto& i: simstring_result){
            if(i.empty()){
                continue;
            }
            const auto& j = inverse.at(i);
            std::copy(std::begin(j), std::end(j), std::back_inserter(candidate_texts));
            if(candidate_texts.size() == max_reranking_num){
                break;
            }
        }
        return eval(query, candidate_texts, threshold, max_response);
    }

    std::vector<output_type> eval(const string_type& query, const std::vector<string_type>& targets,
            double threshold = 0.0, size_t max_response = 0) const
    {
        // load preprocessed data if preprocessing is enabled. otherwise, process corpus texts on demand
        std::vector<WorkData> candidates;
        for(const auto& t: targets){
            if(preprocess_corpus){
                const auto i = preprocessed_corpus.find(t);
                if(i != std::end(preprocessed_corpus)){
                    candidates.push_back(i->second);
                    continue;
                }
            }
            auto tabpos = t.find(L'\t');
            candidates.push_back(std::make_pair(
                tabpos != string_type::npos ? t.substr(0, tabpos) : t,
                (*preprocess)(t, true)));
        }

        // execute reranking
        WorkData input_data = std::make_pair(query, (*preprocess)(query, false));
        std::vector<output_type> response;
        for(const auto& r: reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func, threshold, max_response)){
            response.push_back({r.first, score_func->name, r.second});
        }
        return response;
    }

protected:
    using WorkData = std::pair<string_type, typename Preprocessor::output_type>;

    mutable simstring::reader db;
    std::unordered_map<string_type, std::vector<string_type>> inverse;

    const int simstring_measure;
    const double simstring_threshold;
    const size_t max_reranking_num;
    const Reranker<string_type> reranker;

    const std::shared_ptr<Preprocessor> preprocess;
    const std::shared_ptr<ScoreFunction> score_func;

    const bool preprocess_corpus;
    std::unordered_map<string_type, WorkData> preprocessed_corpus;

    mutable std::mutex mutex_simstring;
};

}
#endif
<commit_msg>load preprocessed data<commit_after>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

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.
*/

#ifndef __BASIC_RESEMBLA_HPP__
#define __BASIC_RESEMBLA_HPP__

#include <string>
#include <fstream>
#include <vector>
#include <unordered_map>
#include <memory>
#include <stdexcept>
#include <mutex>

#include <simstring/simstring.h>
#include <json.hpp>

#include "resembla_interface.hpp"
#include "reranker.hpp"

#include "measure/weighted_sequence_serializer.hpp"

namespace resembla {

// Resembla with a fixed pair of preprocessor and score function
template<
    typename Preprocessor,
    typename ScoreFunction
>
class BasicResembla: public ResemblaInterface
{
public:
    BasicResembla(const std::string& db_path, const std::string& inverse_path,
            const int simstring_measure, const double simstring_threshold, const size_t max_reranking_num,
            std::shared_ptr<Preprocessor> preprocess, std::shared_ptr<ScoreFunction> score_func,
            bool preprocess_corpus = true, size_t preprocessed_data_col = 0):
        simstring_measure(simstring_measure), simstring_threshold(simstring_threshold), max_reranking_num(max_reranking_num),
        reranker(), preprocess(preprocess), score_func(score_func), preprocess_corpus(preprocess_corpus)
    {
        db.open(db_path);
        std::basic_ifstream<string_type::value_type> ifs(inverse_path);
        if(ifs.fail()){
            throw std::runtime_error("input file is not available: " + inverse_path);
        }
        auto delimiter = cast_string<string_type>(std::string("\t"));
        while(ifs.good()){
            string_type line;
            std::getline(ifs, line);
            if(ifs.eof() || line.length() == 0){
                break;
            }

            auto columns = split(line, L'\t');
            if(columns.size() < 2){
                throw std::runtime_error("invalid line in " + inverse_path + ": " + cast_string<std::string>(line));
            }
            const auto& indexed = columns[0];
            auto original = columns[1];

            const auto& i = inverse.find(indexed);
            if(i == std::end(inverse)){
                inverse[indexed] = {original};
            }
            else{
                inverse.at(indexed).push_back(original);
            }

            if(preprocess_corpus){
                if(preprocessed_data_col > 0 && preprocessed_data_col - 1 < columns.size() && !columns[preprocessed_data_col - 1].empty()){
                    nlohmann::json j = nlohmann::json::parse(cast_string<std::string>(columns[preprocessed_data_col - 1]));
                    typename Preprocessor::output_type preprocessed = j;
                    preprocessed_corpus[columns[1]] = std::make_pair(columns[1], preprocessed);
                }
                else{
                    preprocessed_corpus[columns[1]] = std::make_pair(columns[1], (*preprocess)(original, true));
                }
            }
        }
    }

    std::vector<output_type> find(const string_type& query, double threshold = 0.0, size_t max_response = 0) const
    {
        // search from N-gram index
        std::vector<string_type> simstring_result;
        {
            std::lock_guard<std::mutex> lock(mutex_simstring);
            string_type search_query = preprocess->index(query);
            db.retrieve(search_query, simstring_measure, simstring_threshold, std::back_inserter(simstring_result));
            if(simstring_result.empty()){
                return {};
            }
        }

        std::vector<string_type> candidate_texts;
        for(const auto& i: simstring_result){
            if(i.empty()){
                continue;
            }
            const auto& j = inverse.at(i);
            std::copy(std::begin(j), std::end(j), std::back_inserter(candidate_texts));
            if(candidate_texts.size() == max_reranking_num){
                break;
            }
        }
        return eval(query, candidate_texts, threshold, max_response);
    }

    std::vector<output_type> eval(const string_type& query, const std::vector<string_type>& targets,
            double threshold = 0.0, size_t max_response = 0) const
    {
        // load preprocessed data if preprocessing is enabled. otherwise, process corpus texts on demand
        std::vector<WorkData> candidates;
        for(const auto& t: targets){
            if(preprocess_corpus){
                const auto i = preprocessed_corpus.find(t);
                if(i != std::end(preprocessed_corpus)){
                    candidates.push_back(i->second);
                    continue;
                }
            }
            auto tabpos = t.find(L'\t');
            candidates.push_back(std::make_pair(
                tabpos != string_type::npos ? t.substr(0, tabpos) : t,
                (*preprocess)(t, true)));
        }

        // execute reranking
        WorkData input_data = std::make_pair(query, (*preprocess)(query, false));
        std::vector<output_type> response;
        for(const auto& r: reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func, threshold, max_response)){
            response.push_back({r.first, score_func->name, r.second});
        }
        return response;
    }

protected:
    using WorkData = std::pair<string_type, typename Preprocessor::output_type>;

    mutable simstring::reader db;
    std::unordered_map<string_type, std::vector<string_type>> inverse;

    const int simstring_measure;
    const double simstring_threshold;
    const size_t max_reranking_num;
    const Reranker<string_type> reranker;

    const std::shared_ptr<Preprocessor> preprocess;
    const std::shared_ptr<ScoreFunction> score_func;

    const bool preprocess_corpus;
    std::unordered_map<string_type, WorkData> preprocessed_corpus;

    mutable std::mutex mutex_simstring;
};

}
#endif
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef itkNeighborhoodAlgorithm_hxx
#define itkNeighborhoodAlgorithm_hxx
#include "itkNeighborhoodAlgorithm.h"
#include "itkImageRegionIterator.h"
#include "itkImageRegion.h"
#include "itkConstSliceIterator.h"

namespace itk
{
namespace NeighborhoodAlgorithm
{
template <typename TImage>
auto
ImageBoundaryFacesCalculator<TImage>::Compute(const TImage & img, RegionType regionToProcess, RadiusType radius)
  -> Result
{
  unsigned int j, i;
  // Analyze the regionToProcess to determine if any of its faces are
  // along a buffer boundary (we have no data in the buffer for pixels
  // that are outside the boundary, but within the neighborhood radius and will
  // have to treat them differently).  We also determine the size of the non-
  // boundary region that will be processed. For instance, given a 2D image
  // and regionTOProcess (size = 5x5),

  Result result;
  // The portion of the regionToProcess that is outside of the image bufferedRegion
  // doesn't make sense. If the regionToProcess is completely outside of
  // the image bufferedRegion, return an empty (default-constructed) result.
  if (!regionToProcess.Crop(img.GetBufferedRegion()))
  {
    return result;
  }

  const IndexType bStart = img.GetBufferedRegion().GetIndex();
  const SizeType  bSize = img.GetBufferedRegion().GetSize();
  const IndexType rStart = regionToProcess.GetIndex();
  const SizeType  rSize = regionToProcess.GetSize();

  IndexValueType overlapLow, overlapHigh;
  IndexType      fStart; // Boundary, "face"
  SizeType       fSize;  // region data.
  RegionType     fRegion;
  SizeType       nbSize = regionToProcess.GetSize();   // Non-boundary region
  IndexType      nbStart = regionToProcess.GetIndex(); // data.

  IndexType vrStart =
    rStart; // start index of variable processed region which has considered the boundary region in last direction
  SizeType vrSize =
    rSize; // size of variable processed region which has considered the boundary region in last direction

  for (i = 0; i < ImageDimension; ++i)
  {
    overlapLow = static_cast<IndexValueType>((rStart[i] - radius[i]) - bStart[i]);
    // image buffered region should be more than twice of the radius,
    // otherwise there would be overlap between two boundary regions.
    // in the case, we reduce upper boundary size to remove overlap.
    if (bSize[i] > 2 * radius[i])
    {
      overlapHigh = static_cast<IndexValueType>((bStart[i] + bSize[i]) - (rStart[i] + rSize[i] + radius[i]));
    }
    else
    {
      overlapHigh = static_cast<IndexValueType>((bStart[i] + radius[i]) - (rStart[i] + rSize[i]));
    }

    if (overlapLow < 0)                    // out of bounds condition, define
                                           // a region of
    {                                      // iteration along this face
      for (j = 0; j < ImageDimension; ++j) // define the starting index
      {                                    // and size of the face region
        fStart[j] = vrStart[j];
        if (j == i)
        {
          // Boundary region cannot be outside the region to process
          if (-overlapLow > static_cast<IndexValueType>(rSize[i]))
          {
            overlapLow = -static_cast<IndexValueType>(rSize[i]);
          }
          fSize[j] = -overlapLow;
          vrSize[j] += overlapLow;  // change start and size in this direction
          vrStart[j] -= overlapLow; // to ensure no duplicate pixels at corners
        }
        else
        {
          fSize[j] = vrSize[j];
        }

        // Boundary region cannot be outside the region to process
        if (fSize[j] > rSize[j])
        {
          fSize[j] = rSize[j];
        }
      }
      // avoid unsigned overflow if the non-boundary region is too small to
      // process
      if (fSize[i] > nbSize[i])
      {
        nbSize[i] = 0;
      }
      else
      {
        nbSize[i] -= fSize[i];
      }
      nbStart[i] += -overlapLow;
      fRegion.SetIndex(fStart);
      fRegion.SetSize(fSize);
      result.m_BoundaryFaces.push_back(fRegion);
    }
    if (overlapHigh < 0)
    {
      for (j = 0; j < ImageDimension; ++j)
      {
        if (j == i)
        {
          // Boundary region cannot be outside the region to process
          if (-overlapHigh > static_cast<IndexValueType>(rSize[i]))
          {
            overlapHigh = -static_cast<IndexValueType>(rSize[i]);
          }
          fStart[j] = rStart[j] + static_cast<IndexValueType>(rSize[j]) + overlapHigh;
          fSize[j] = -overlapHigh;
          vrSize[j] += overlapHigh; // change size in this direction
        }
        else
        {
          fStart[j] = vrStart[j];
          fSize[j] = vrSize[j];
        }
      }
      // avoid unsigned overflow if the non-boundary region is too small to
      // process
      if (fSize[i] > nbSize[i])
      {
        nbSize[i] = 0;
      }
      else
      {
        nbSize[i] -= fSize[i];
      }

      fRegion.SetIndex(fStart);
      fRegion.SetSize(fSize);
      result.m_BoundaryFaces.push_back(fRegion);
    }
  }
  result.m_NonBoundaryRegion.SetSize(nbSize);
  result.m_NonBoundaryRegion.SetIndex(nbStart);
  return result;
}

template <typename TImage>
typename ImageBoundaryFacesCalculator<TImage>::FaceListType
ImageBoundaryFacesCalculator<TImage>::operator()(const TImage * img, RegionType regionToProcess, RadiusType radius)
{
  const auto result = Compute(*img, regionToProcess, radius);

  if (result == Result{})
  {
    return FaceListType{};
  }
  else
  {
    FaceListType faceList = std::move(result.m_BoundaryFaces);
    faceList.push_front(result.m_NonBoundaryRegion);
    return faceList;
  }
}

template <typename TImage>
typename CalculateOutputWrapOffsetModifiers<TImage>::OffsetType
CalculateOutputWrapOffsetModifiers<TImage>::operator()(TImage * input, TImage * output) const
{
  OffsetType ans;

  const Size<TImage::ImageDimension> isz = input->GetBufferedRegion().GetSize();
  const Size<TImage::ImageDimension> osz = output->GetBufferedRegion().GetSize();

  for (int i = 0; i < TImage::ImageDimension; ++i)
  {
    ans[i] = osz[i] - isz[i];
  }
  return ans;
}
} // end namespace NeighborhoodAlgorithm
} // end namespace itk

#endif
<commit_msg>STYLE: Remove repeated GetBufferedRegion() calls from ImageBoundaryFaces<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef itkNeighborhoodAlgorithm_hxx
#define itkNeighborhoodAlgorithm_hxx
#include "itkNeighborhoodAlgorithm.h"
#include "itkImageRegionIterator.h"
#include "itkImageRegion.h"
#include "itkConstSliceIterator.h"

namespace itk
{
namespace NeighborhoodAlgorithm
{
template <typename TImage>
auto
ImageBoundaryFacesCalculator<TImage>::Compute(const TImage & img, RegionType regionToProcess, RadiusType radius)
  -> Result
{
  // Analyze the regionToProcess to determine if any of its faces are
  // along a buffer boundary (we have no data in the buffer for pixels
  // that are outside the boundary, but within the neighborhood radius and will
  // have to treat them differently).  We also determine the size of the non-
  // boundary region that will be processed. For instance, given a 2D image
  // and regionTOProcess (size = 5x5),

  Result result;

  const RegionType & bufferedRegion = img.GetBufferedRegion();

  // The portion of the regionToProcess that is outside of the image bufferedRegion
  // doesn't make sense. If the regionToProcess is completely outside of
  // the image bufferedRegion, return an empty (default-constructed) result.
  if (!regionToProcess.Crop(bufferedRegion))
  {
    return result;
  }

  const IndexType bStart = bufferedRegion.GetIndex();
  const SizeType  bSize = bufferedRegion.GetSize();
  const IndexType rStart = regionToProcess.GetIndex();
  const SizeType  rSize = regionToProcess.GetSize();

  SizeType  nbSize = rSize;   // Non-boundary region
  IndexType nbStart = rStart; // data.

  IndexType vrStart =
    rStart; // start index of variable processed region which has considered the boundary region in last direction
  SizeType vrSize =
    rSize; // size of variable processed region which has considered the boundary region in last direction

  for (unsigned int i = 0; i < ImageDimension; ++i)
  {
    IndexType fStart; // Boundary, "face"
    SizeType  fSize;  // region data.

    auto overlapLow = static_cast<IndexValueType>((rStart[i] - radius[i]) - bStart[i]);
    // image buffered region should be more than twice of the radius,
    // otherwise there would be overlap between two boundary regions.
    // in the case, we reduce upper boundary size to remove overlap.

    IndexValueType overlapHigh;

    if (bSize[i] > 2 * radius[i])
    {
      overlapHigh = static_cast<IndexValueType>((bStart[i] + bSize[i]) - (rStart[i] + rSize[i] + radius[i]));
    }
    else
    {
      overlapHigh = static_cast<IndexValueType>((bStart[i] + radius[i]) - (rStart[i] + rSize[i]));
    }

    if (overlapLow < 0)                                 // out of bounds condition, define
                                                        // a region of
    {                                                   // iteration along this face
      for (unsigned int j = 0; j < ImageDimension; ++j) // define the starting index
      {                                                 // and size of the face region
        fStart[j] = vrStart[j];
        if (j == i)
        {
          // Boundary region cannot be outside the region to process
          if (-overlapLow > static_cast<IndexValueType>(rSize[i]))
          {
            overlapLow = -static_cast<IndexValueType>(rSize[i]);
          }
          fSize[j] = -overlapLow;
          vrSize[j] += overlapLow;  // change start and size in this direction
          vrStart[j] -= overlapLow; // to ensure no duplicate pixels at corners
        }
        else
        {
          fSize[j] = vrSize[j];
        }

        // Boundary region cannot be outside the region to process
        if (fSize[j] > rSize[j])
        {
          fSize[j] = rSize[j];
        }
      }
      // avoid unsigned overflow if the non-boundary region is too small to
      // process
      if (fSize[i] > nbSize[i])
      {
        nbSize[i] = 0;
      }
      else
      {
        nbSize[i] -= fSize[i];
      }
      nbStart[i] += -overlapLow;
      result.m_BoundaryFaces.emplace_back(fStart, fSize);
    }
    if (overlapHigh < 0)
    {
      for (unsigned int j = 0; j < ImageDimension; ++j)
      {
        if (j == i)
        {
          // Boundary region cannot be outside the region to process
          if (-overlapHigh > static_cast<IndexValueType>(rSize[i]))
          {
            overlapHigh = -static_cast<IndexValueType>(rSize[i]);
          }
          fStart[j] = rStart[j] + static_cast<IndexValueType>(rSize[j]) + overlapHigh;
          fSize[j] = -overlapHigh;
          vrSize[j] += overlapHigh; // change size in this direction
        }
        else
        {
          fStart[j] = vrStart[j];
          fSize[j] = vrSize[j];
        }
      }
      // avoid unsigned overflow if the non-boundary region is too small to
      // process
      if (fSize[i] > nbSize[i])
      {
        nbSize[i] = 0;
      }
      else
      {
        nbSize[i] -= fSize[i];
      }
      result.m_BoundaryFaces.emplace_back(fStart, fSize);
    }
  }
  result.m_NonBoundaryRegion.SetSize(nbSize);
  result.m_NonBoundaryRegion.SetIndex(nbStart);
  return result;
}

template <typename TImage>
typename ImageBoundaryFacesCalculator<TImage>::FaceListType
ImageBoundaryFacesCalculator<TImage>::operator()(const TImage * img, RegionType regionToProcess, RadiusType radius)
{
  const auto result = Compute(*img, regionToProcess, radius);

  if (result == Result{})
  {
    return FaceListType{};
  }
  else
  {
    FaceListType faceList = std::move(result.m_BoundaryFaces);
    faceList.push_front(result.m_NonBoundaryRegion);
    return faceList;
  }
}

template <typename TImage>
typename CalculateOutputWrapOffsetModifiers<TImage>::OffsetType
CalculateOutputWrapOffsetModifiers<TImage>::operator()(TImage * input, TImage * output) const
{
  OffsetType ans;

  const Size<TImage::ImageDimension> isz = input->GetBufferedRegion().GetSize();
  const Size<TImage::ImageDimension> osz = output->GetBufferedRegion().GetSize();

  for (int i = 0; i < TImage::ImageDimension; ++i)
  {
    ans[i] = osz[i] - isz[i];
  }
  return ans;
}
} // end namespace NeighborhoodAlgorithm
} // end namespace itk

#endif
<|endoftext|>


<commit_before>// Functions for the symmetric group approach
#include<iostream>
#include<vector>
#include"weyl.h"

class perm_a
{
	public:
		std::vector<int> perm;
		double coeff=1;
		int    n=0;
	// TODO: overload the multiply operator
};

void
print_perm(perm_a P)
{
	std::cout << P.coeff << " * ";
	for(auto p : P.perm)
		std::cout << p <<" ";
	std::cout << "\n";
	return;
}

perm_a
eye(int n)
{
	//unit permutation
	perm_a P;
	P.perm.clear();
	for(int k=0; k<n; k++)
		P.perm.push_back(k);
	P.coeff=1;
	return P;
}

//overload the * operator
perm_a
perm_multiply(const perm_a& P1, const perm_a& P2)
{

	perm_a result;
	std::vector<int> p_result;

	p_result.clear();
	if(P1.n != P2.n)
	{
		std::cout << "Error in perm_multiply, perms must be same size"
			  << std::endl;
		return result;
	}

	p_result.resize(P1.n);

	for(int j=0; j<P1.n; j++)
		p_result[j]=P1.perm[P2.perm[j]];

	result.coeff=P1.coeff*P2.coeff;
	result.perm=p_result;

	return result;
}

//overload the * operator
std::vector<perm_a>
multiply(std::vector<perm_a> A, std::vector<perm_a> B)
{
	std::vector<perm_a>  product;
	for( auto p : A )
		for( auto q : B)
			product.push_back(perm_multiply(p,q));

	//simplify using std::algorithm
	//i.e. combine like terms

	return product;
}

std::vector<perm_a>
Srow(std::vector<int> frame,std::vector<int> tableau)
{
	bool debug=true;
	if(debug) std::cout << "here (young::Srow)\n";
	int N=0; //number of electrons
	for(int r=0; r<frame.size(); r++)
		N=N+frame[r];

	std::vector<perm_a> S;
	std::vector<perm_a> Sr;
	for(int row=0; row<frame.size(); row++)
	{
		Sr.clear();

		if(frame[row]==1)
			continue;
		perm_a P;
		P.perm.clear();

		int col0=tableau_pos(row,0,frame);
		int col1=tableau_pos(row,1,frame);

		P.perm.clear();
		for(int k=0; k< N; k++)
			P.perm.push_back(k);
		P.perm[tableau[col0]]=tableau[col1];
		P.perm[tableau[col1]]=tableau[col0];

		P.coeff=1;

		Sr.push_back(eye(N));
		Sr.push_back(P);

		if(debug) std::cout << "S_before (young::Srow)\n";

		S=multiply(S,Sr);
		if(debug) std::cout << "S_before (young::Srow)\n";
	}
	return S;
}

int Ey(std::vector<int> frame_rows,std::vector<int> yT)
{
	std::cout << "here (young::Ey)\n";
	std::vector<perm_a> S=Srow(frame_rows,yT);
	for(int k=0; k<S.size(); k++)
	{
		std::cout << "k : " << k << "\n";
		print_perm(S[k]);
	}
	return 0;
}

int
main()
{
	int n=3;

	perm_a P12;
	P12.n=n;
	P12.perm={1,0,2};
	P12.coeff=.5;

	//std::cout << ".5 * P12\n";
	//print_perm(P12);

	perm_a id;
	id.n=n;
	id.perm={0,1,2};
	id.coeff=-1;

	//std::cout << "Id\n";
	//print_perm(id);

	std::vector<perm_a> pvec;
	pvec.clear();
	pvec.push_back(id);

	//print_perm(perm_multiply(P12,P12));

	std::vector<int> frame_rows;
	frame_rows.clear();
	frame_rows.push_back(2);
	frame_rows.push_back(2);
	frame_rows.push_back(1);

	std::vector<int> young_tableau;
	young_tableau.clear();
	young_tableau.push_back(0);
	young_tableau.push_back(1);
	young_tableau.push_back(2);
	young_tableau.push_back(3);
	young_tableau.push_back(4);

	Ey(frame_rows,young_tableau);

	return 0;
}

<commit_msg>The symmeterizer of the rows is working<commit_after>// Functions for the symmetric group approach
#include<iostream>
#include<vector>
#include"weyl.h"

class perm_a
{
	public:
		std::vector<int> perm;
		double coeff=1;
		int    n=0;
	// TODO: overload the multiply operator
};

void
print_perm(perm_a P)
{
	std::cout << P.coeff << " * ";
	for(auto p : P.perm)
		std::cout << p <<" ";
	std::cout << "\n";
	return;
}

perm_a
perm_I(int n)
{
	//unit permutation
	perm_a P;
	P.perm.clear();
	for(int k=0; k<n; k++)
		P.perm.push_back(k);
	P.coeff=1;
	return P;
}

//overload the * operator
perm_a
perm_multiply(const perm_a& P1, const perm_a& P2)
{

	bool debug=false;
	perm_a result;
	std::vector<int> p_result;

	p_result.clear();
	if(P1.perm.size() != P2.perm.size())
	{
		std::cout << "Error in perm_multiply, perms must be same size"
			  << std::endl;
		return result;
	}

	p_result.resize(P1.perm.size());

	for(int j=0; j<P1.perm.size(); j++)
	{
		p_result[j]=P1.perm[P2.perm[j]];
		if(debug)
		{
			std::cout << "p_result element " << j << " "
				  << p_result[j] ;
			std::cout << " (young::perm_multiply)\n";
		}
	}

	result.coeff=P1.coeff*P2.coeff;
	result.perm=p_result;

	return result;
}

//overload the * operator
std::vector<perm_a>
multiply(std::vector<perm_a> A, std::vector<perm_a> B)
{
	bool debug=false;
	std::vector<perm_a>  product;
	for( auto p : A )
		for( auto q : B)
		{
			perm_a pq=perm_multiply(p,q);
			if(debug)
			{
				std::cout << "pq (young::multiply)\n";
				print_perm(pq);
			}
			product.push_back(pq);
		}

	//simplify using std::algorithm
	//i.e. combine like terms

	if(debug)
	{
		std::cout << "product (young::multiply)\n";
		for( perm_a p : product)
			print_perm(p);
	}

	return product;
}

std::vector<perm_a>
Srow(std::vector<int> frame,std::vector<int> tableau)
{
	bool debug=false;
	if(debug) std::cout << "here (young::Srow)\n";
	int N=0; //number of electrons
	for(int r=0; r<frame.size(); r++)
		N=N+frame[r];

	//initialize S as I
	std::vector<perm_a> S;
	S.clear(); S.push_back(perm_I(N));

	std::vector<perm_a> Sr;
	for(int row=0; row<frame.size(); row++)
	{
		Sr.clear();

		if(frame[row]==1)
			continue;
		perm_a P;
		P.perm.clear();

		int col0=tableau_pos(row,0,frame);
		int col1=tableau_pos(row,1,frame);

		P.perm.clear();
		for(int k=0; k< N; k++)
			P.perm.push_back(k);
		P.perm[tableau[col0]]=tableau[col1];
		P.perm[tableau[col1]]=tableau[col0];

		P.coeff=1;

		Sr.push_back(perm_I(N));
		Sr.push_back(P);

		if(debug)
		{
			std::cout << "Sr (young::Srow)\n";
			for( perm_a p : Sr)
				print_perm(p);
			std::cout << "\n";
			std::cout << "S  (young::Srow)\n";
			for( perm_a p : S)
				print_perm(p);
			std::cout << "\n";

		}

		S=multiply(S,Sr);
		if(debug)
		{
			std::cout << "after multiply(S,Sr) (young::Srow)\n";
			for( perm_a p : S)
				print_perm(p);
			std::cout << "\n";
		}
	}
	return S;
}

int Ey(std::vector<int> frame_rows,std::vector<int> yT)
{
	std::vector<perm_a> S=Srow(frame_rows,yT);
	std::cout << "Symmetrizer of rows:\n";
	for(int k=0; k<S.size(); k++)
	{
		print_perm(S[k]);
	}
	return 0;
}

int
main()
{
	int n=3;

	perm_a P12;
	P12.perm={1,0,2};
	P12.coeff=.5;

	//std::cout << ".5 * P12\n";
	//print_perm(P12);

	perm_a id;
	id.perm={0,1,2};
	id.coeff=-1;

	//std::cout << "Id\n";
	//print_perm(id);

	std::vector<perm_a> pvec;
	pvec.clear();
	pvec.push_back(id);

	//print_perm(perm_multiply(P12,P12));

	std::vector<int> frame_rows;
	frame_rows.clear();
	frame_rows.push_back(2);
	frame_rows.push_back(2);
	frame_rows.push_back(1);

	std::vector<int> young_tableau;
	young_tableau.clear();
	young_tableau.push_back(0);
	young_tableau.push_back(1);
	young_tableau.push_back(2);
	young_tableau.push_back(3);
	young_tableau.push_back(4);

	print_tableau(young_tableau,frame_rows);

	Ey(frame_rows,young_tableau);

	return 0;
}

<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

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

#include "mitkNavigationDataDelayFilter.h"

mitk::NavigationDataDelayFilter::NavigationDataDelayFilter(unsigned int delay) : m_Delay(delay)
{
  m_Tolerance = 0;
}
mitk::NavigationDataDelayFilter::~NavigationDataDelayFilter()
{
}

void mitk::NavigationDataDelayFilter::GenerateData()
{
  // Check if number of outputs has changed since the previous call. If yes, reset buffer.
  // This actually compares the number of Navigation Datas in each step and compares it to the current number of inputs.
  // If these values differ, the number of inputrs have changed.
  if ( (m_Buffer.size() > 0) &&  (this->GetNumberOfInputs() != m_Buffer.front().second.size()) )
    std::swap(m_Buffer, decltype(m_Buffer)()); // Clear queue with copy-and-swap idiom

  // Put current navigationdatas from input into buffer
  itk::TimeStamp now;
  now.Modified();

  std::vector<mitk::NavigationData::Pointer> ndList;
  for (unsigned int i = 0; i < this->GetNumberOfInputs() ; ++i)
  {
    mitk::NavigationData::Pointer nd = mitk::NavigationData::New();
    nd->Graft(this->GetInput(i));
    ndList.push_back(nd);
  }

  m_Buffer.push( std::make_pair(now.GetMTime(), ndList) );

  // Find most recent member from buffer that is old enough to output, considering the Delay
  // remove all sets that are too old already in the process
  BufferType current;
  bool foundCurrent = false;

  while ( (m_Buffer.size() > 0) && (m_Buffer.front().first + m_Delay <= now.GetMTime() + m_Tolerance ) )
  {
    foundCurrent = true;
    current = m_Buffer.front();
    m_Buffer.pop();
  }

  // update outputs with tracking data from previous step, or none if empty
  if ( !foundCurrent) return;

  for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i)
  {
    mitk::NavigationData* output = this->GetOutput(i);
    assert(output);
    const mitk::NavigationData* input = current.second[i];
    assert(input);

    if (input->IsDataValid() == false)
    {
      output->SetDataValid(false);
      continue;
    }
    output->Graft(input); // First, copy all information from input to output
    output->SetDataValid(true); // operation was successful, therefore data of output is valid.
  }
}
<commit_msg>Use std::queue's own swap function<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

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

#include "mitkNavigationDataDelayFilter.h"

mitk::NavigationDataDelayFilter::NavigationDataDelayFilter(unsigned int delay) : m_Delay(delay)
{
  m_Tolerance = 0;
}
mitk::NavigationDataDelayFilter::~NavigationDataDelayFilter()
{
}

void mitk::NavigationDataDelayFilter::GenerateData()
{
  // Check if number of outputs has changed since the previous call. If yes, reset buffer.
  // This actually compares the number of Navigation Datas in each step and compares it to the current number of inputs.
  // If these values differ, the number of inputrs have changed.
  if ((!m_Buffer.empty()) && (this->GetNumberOfInputs() != m_Buffer.front().second.size()))
    m_Buffer.swap(decltype(m_Buffer)()); // Clear queue with copy-and-swap idiom

  // Put current navigationdatas from input into buffer
  itk::TimeStamp now;
  now.Modified();

  std::vector<mitk::NavigationData::Pointer> ndList;
  for (unsigned int i = 0; i < this->GetNumberOfInputs() ; ++i)
  {
    mitk::NavigationData::Pointer nd = mitk::NavigationData::New();
    nd->Graft(this->GetInput(i));
    ndList.push_back(nd);
  }

  m_Buffer.push( std::make_pair(now.GetMTime(), ndList) );

  // Find most recent member from buffer that is old enough to output, considering the Delay
  // remove all sets that are too old already in the process
  BufferType current;
  bool foundCurrent = false;

  while ( (m_Buffer.size() > 0) && (m_Buffer.front().first + m_Delay <= now.GetMTime() + m_Tolerance ) )
  {
    foundCurrent = true;
    current = m_Buffer.front();
    m_Buffer.pop();
  }

  // update outputs with tracking data from previous step, or none if empty
  if ( !foundCurrent) return;

  for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i)
  {
    mitk::NavigationData* output = this->GetOutput(i);
    assert(output);
    const mitk::NavigationData* input = current.second[i];
    assert(input);

    if (input->IsDataValid() == false)
    {
      output->SetDataValid(false);
      continue;
    }
    output->Graft(input); // First, copy all information from input to output
    output->SetDataValid(true); // operation was successful, therefore data of output is valid.
  }
}
<|endoftext|>


<commit_before>#include "Parser.h"
#include "Operator.h"
#include "Function.h"
#include "MiscTokens.h"
#include "Utils.h"
#include <map>
#include <cmath>

using namespace RPN;

std::map<std::string, std::function<Token*(Parser::Context &context)>> Functions::_functions;

namespace RPN
{
#ifdef RPN_USE_JIT
	namespace impl
	{
		asmjit::JitRuntime& jitRuntime()
		{
			static asmjit::JitRuntime runtime;
			return runtime;
		}

	};
#endif

	bool rule_whitespace_eater(Parser::Context &context)
	{
		auto peek = context.input.peek();
		if (!isspace(peek))
			return false;

		while (true)
		{
			auto peek = context.input.peek();
			if (!isspace(peek))
				return true;
			context.input.get();
		}
	}

	bool rule_value(Parser::Context &context)
	{
		auto peek = context.input.peek();
		if (!isdigit(peek))
			return false;

		float value = 0.0f;
		context.input >> value;

		context.AddToken(new Value(value));
		return true;
	}

	bool rule_string(Parser::Context &context)
	{
		auto peek = context.input.peek();
		if (peek != '\'')
			return false;

		context.input.get();
		auto charsAllowedInString = [](char c, int index) { return c != '\''; };

		std::string value = eat_string_in_stream(context.input, charsAllowedInString);
		context.input.get();

		context.AddToken(new StringValue(value));
		return true;
	}

	bool rule_short_operator(Parser::Context &context)
	{
		auto peek = context.input.peek();

		static std::map<char, std::function<Token*(Parser::Context &context)>> charToToken =
		{
			{ '+', [](Parser::Context &context) { return new BinaryPlusOperator; } },
			{ '-', [](Parser::Context &context) -> Token*
                {
                    if (context.last_operator_type == Token::Type::None || context.last_operator_type == Token::Type::LeftParenthesis || context.last_operator_type == Token::Type::Operator)
                        return new UnaryMinusOperator;
                    return new BinaryMinusOperator;
                } },
			{ '*', [](Parser::Context &context) { return new BinaryMultiplyOperator; } },
			{ '/', [](Parser::Context &context) { return new BinaryDivisionOperator; } },
			{ '(', [](Parser::Context &context) { return new LeftParenthesis; } },
			{ ')', [](Parser::Context &context) { return new RightParenthesis; } },
			{ ',', [](Parser::Context &context) { return new Comma; } },

			{ '<', [](Parser::Context &context) { return new BinaryLesserThanOperator; } },
			{ '>', [](Parser::Context &context) { return new BinaryGreaterThanOperator; } },
		};

		auto it = charToToken.find(peek);
		if (it == charToToken.end())
			return false;
		context.input.get();
		context.AddToken(it->second(context));
		return true;
	}

	bool rule_long_operator(Parser::Context &context)
	{
		static std::map<std::string, std::function<Token*(Parser::Context &context)>> strToToken =
		{
			{ "==", [](Parser::Context &context) { return new BinaryEqualsOperator; } },
			{ "!=", [](Parser::Context &context) { return new BinaryNotEqualsOperator; } },
			{ ">=", [](Parser::Context &context) { return new BinaryGreaterOrEqualsOperator; } },
			{ "<=", [](Parser::Context &context) { return new BinaryLesserOrEqualsOperator; } },

			{ "&&", [](Parser::Context &context) { return new BinaryAndOperator; } },
			{ "||", [](Parser::Context &context) { return new BinaryOrOperator; } },
		};

		for (auto &pair : strToToken)
		{
			if (!eat_string_in_stream_if_equal(context.input, pair.first))
				continue;
			context.AddToken(pair.second(context));
			return true;
		}

		return false;
	}

	bool embedded_function(Parser::Context &context)
	{
		auto position = context.input.tellg();
		auto charsAllowedInFuncName = [](char c, int index) { return isalpha(c) || (index == 0 && isdigit(c)) || (index != 0 && c == '.') || c == '_'; };
		std::string str = eat_string_in_stream(context.input, charsAllowedInFuncName);

		auto token = Functions::getFunction(str, context);
		if (token)
		{
			context.AddToken(token);
			return true;
		}

		context.input.seekg(position);
		return false;
	}

}

void Parser::CompiledFunction::Release()
{
#ifdef RPN_USE_JIT
	auto& runtime = impl::jitRuntime();
	runtime.release((void*)_function);
#endif
}

void _InitializeParser()
{
	Functions::AddStatelessLambda("if", [](float c, float a, float b) { return c != 0.0f ? a : b; });

	{
		using namespace std;
		Functions::AddStatelessLambda("math.max", [](float a, float b) { return a > b ? a : b; });
		Functions::AddStatelessLambda("math.min", [](float a, float b) { return a > b ? b : a; });

		Functions::AddStatelessLambda("math.abs", [](float a) { return fabsf(a); });
		Functions::AddStatelessLambda("math.mod", [](float a, float b) { return fmodf(a, b); });

		Functions::AddStatelessLambda("math.ceil", [](float a) { return ceilf(a); });
		Functions::AddStatelessLambda("math.floor", [](float a) { return floorf(a); });

		Functions::AddStatelessLambda("math.pow", [](float a, float b) { return powf(a, b); });
		Functions::AddStatelessLambda("math.sqrt", [](float a) { return sqrtf(a); });

		Functions::AddStatelessLambda("math.sin", [](float a) { return cosf(a); });
		Functions::AddStatelessLambda("math.cos", [](float a) { return sinf(a); });
		Functions::AddStatelessLambda("math.tan", [](float a) { return tanf(a); });

		Functions::AddStatelessLambda("math.asin", [](float a) { return acosf(a); });
		Functions::AddStatelessLambda("math.acos", [](float a) { return asinf(a); });
		Functions::AddStatelessLambda("math.atan", [](float a) { return atanf(a); });
		Functions::AddStatelessLambda("math.atan2", [](float a, float b) { return atan2f(a,b); });
	}

	{
		Functions::AddLambda("string.equal", [](const std::string &str, const std::string &str2) { return str == str2 ? 1.0f : 0.0f; });
		Functions::AddLambda("string.length", [](const std::string &str) { return (float)str.size(); });
		Functions::AddLambda("string.join", [](const std::vector<TokenPtr>& tokens)
		{
			std::ostringstream ss;
			for (auto &token : tokens)
				ss << token->stringValue();
			return ss.str();
		});

	}

	{
		static std::stack<float> stack;

		auto push = [&](float arg)
		{
			stack.push(arg); return arg;
		};
		auto pop = [&]()
		{
			if (stack.empty())
			{
				assert(false);
				return 0.0f;
			}
			auto a = stack.top();
			stack.pop();
			return a;
		};

		Functions::AddLambda("stack.push", push);
		Functions::AddLambda("stack.pop", pop);
	}

}

Parser::Parser()
{
	static bool initialized = false;
	if (!initialized)
	{
		initialized = true;
		_InitializeParser();
	}

	_rules.push_back(rule_whitespace_eater);
	_rules.push_back(rule_value);
	_rules.push_back(rule_string);
	_rules.push_back(rule_long_operator);
	_rules.push_back(rule_short_operator);
	_rules.push_back(embedded_function);

}

Parser::CompiledFunction Parser::Compile(const std::string& text)
{
	auto token = Parse(text);

	if (!token)
		return {};

#ifdef RPN_USE_JIT
	using namespace asmjit;

	auto& runtime = impl::jitRuntime();
	StringLogger logger;

	X86Assembler a(&runtime);
	X86Compiler c(&a);
	a.setLogger(&logger);

	c.addFunc(FuncBuilder0<float>(kCallConvHost));
	c.ret(token->Compile(c));
	c.endFunc();
	c.finalize();

	auto pointer = asmjit_cast<FunctionPtr>(a.make());

	return{ pointer , std::move(token) };
#else
	return{ nullptr , std::move(token) };
#endif
}
<commit_msg>Unary minus should also check for FunctionArgumentSeparator.<commit_after>#include "Parser.h"
#include "Operator.h"
#include "Function.h"
#include "MiscTokens.h"
#include "Utils.h"
#include <map>
#include <cmath>

using namespace RPN;

std::map<std::string, std::function<Token*(Parser::Context &context)>> Functions::_functions;

namespace RPN
{
#ifdef RPN_USE_JIT
	namespace impl
	{
		asmjit::JitRuntime& jitRuntime()
		{
			static asmjit::JitRuntime runtime;
			return runtime;
		}

	};
#endif

	bool rule_whitespace_eater(Parser::Context &context)
	{
		auto peek = context.input.peek();
		if (!isspace(peek))
			return false;

		while (true)
		{
			auto peek = context.input.peek();
			if (!isspace(peek))
				return true;
			context.input.get();
		}
	}

	bool rule_value(Parser::Context &context)
	{
		auto peek = context.input.peek();
		if (!isdigit(peek))
			return false;

		float value = 0.0f;
		context.input >> value;

		context.AddToken(new Value(value));
		return true;
	}

	bool rule_string(Parser::Context &context)
	{
		auto peek = context.input.peek();
		if (peek != '\'')
			return false;

		context.input.get();
		auto charsAllowedInString = [](char c, int index) { return c != '\''; };

		std::string value = eat_string_in_stream(context.input, charsAllowedInString);
		context.input.get();

		context.AddToken(new StringValue(value));
		return true;
	}

	bool rule_short_operator(Parser::Context &context)
	{
		auto peek = context.input.peek();

		static std::map<char, std::function<Token*(Parser::Context &context)>> charToToken =
		{
			{ '+', [](Parser::Context &context) { return new BinaryPlusOperator; } },
			{ '-', [](Parser::Context &context) -> Token*
                {
                    if (context.last_operator_type == Token::Type::None || context.last_operator_type == Token::Type::LeftParenthesis || context.last_operator_type == Token::Type::Operator || context.last_operator_type == Token::Type::FunctionArgumentSeparator)
                        return new UnaryMinusOperator;
                    return new BinaryMinusOperator;
                } },
			{ '*', [](Parser::Context &context) { return new BinaryMultiplyOperator; } },
			{ '/', [](Parser::Context &context) { return new BinaryDivisionOperator; } },
			{ '(', [](Parser::Context &context) { return new LeftParenthesis; } },
			{ ')', [](Parser::Context &context) { return new RightParenthesis; } },
			{ ',', [](Parser::Context &context) { return new Comma; } },

			{ '<', [](Parser::Context &context) { return new BinaryLesserThanOperator; } },
			{ '>', [](Parser::Context &context) { return new BinaryGreaterThanOperator; } },
		};

		auto it = charToToken.find(peek);
		if (it == charToToken.end())
			return false;
		context.input.get();
		context.AddToken(it->second(context));
		return true;
	}

	bool rule_long_operator(Parser::Context &context)
	{
		static std::map<std::string, std::function<Token*(Parser::Context &context)>> strToToken =
		{
			{ "==", [](Parser::Context &context) { return new BinaryEqualsOperator; } },
			{ "!=", [](Parser::Context &context) { return new BinaryNotEqualsOperator; } },
			{ ">=", [](Parser::Context &context) { return new BinaryGreaterOrEqualsOperator; } },
			{ "<=", [](Parser::Context &context) { return new BinaryLesserOrEqualsOperator; } },

			{ "&&", [](Parser::Context &context) { return new BinaryAndOperator; } },
			{ "||", [](Parser::Context &context) { return new BinaryOrOperator; } },
		};

		for (auto &pair : strToToken)
		{
			if (!eat_string_in_stream_if_equal(context.input, pair.first))
				continue;
			context.AddToken(pair.second(context));
			return true;
		}

		return false;
	}

	bool embedded_function(Parser::Context &context)
	{
		auto position = context.input.tellg();
		auto charsAllowedInFuncName = [](char c, int index) { return isalpha(c) || (index == 0 && isdigit(c)) || (index != 0 && c == '.') || c == '_'; };
		std::string str = eat_string_in_stream(context.input, charsAllowedInFuncName);

		auto token = Functions::getFunction(str, context);
		if (token)
		{
			context.AddToken(token);
			return true;
		}

		context.input.seekg(position);
		return false;
	}

}

void Parser::CompiledFunction::Release()
{
#ifdef RPN_USE_JIT
	auto& runtime = impl::jitRuntime();
	runtime.release((void*)_function);
#endif
}

void _InitializeParser()
{
	Functions::AddStatelessLambda("if", [](float c, float a, float b) { return c != 0.0f ? a : b; });

	{
		using namespace std;
		Functions::AddStatelessLambda("math.max", [](float a, float b) { return a > b ? a : b; });
		Functions::AddStatelessLambda("math.min", [](float a, float b) { return a > b ? b : a; });

		Functions::AddStatelessLambda("math.abs", [](float a) { return fabsf(a); });
		Functions::AddStatelessLambda("math.mod", [](float a, float b) { return fmodf(a, b); });

		Functions::AddStatelessLambda("math.ceil", [](float a) { return ceilf(a); });
		Functions::AddStatelessLambda("math.floor", [](float a) { return floorf(a); });

		Functions::AddStatelessLambda("math.pow", [](float a, float b) { return powf(a, b); });
		Functions::AddStatelessLambda("math.sqrt", [](float a) { return sqrtf(a); });

		Functions::AddStatelessLambda("math.sin", [](float a) { return cosf(a); });
		Functions::AddStatelessLambda("math.cos", [](float a) { return sinf(a); });
		Functions::AddStatelessLambda("math.tan", [](float a) { return tanf(a); });

		Functions::AddStatelessLambda("math.asin", [](float a) { return acosf(a); });
		Functions::AddStatelessLambda("math.acos", [](float a) { return asinf(a); });
		Functions::AddStatelessLambda("math.atan", [](float a) { return atanf(a); });
		Functions::AddStatelessLambda("math.atan2", [](float a, float b) { return atan2f(a,b); });
	}

	{
		Functions::AddLambda("string.equal", [](const std::string &str, const std::string &str2) { return str == str2 ? 1.0f : 0.0f; });
		Functions::AddLambda("string.length", [](const std::string &str) { return (float)str.size(); });
		Functions::AddLambda("string.join", [](const std::vector<TokenPtr>& tokens)
		{
			std::ostringstream ss;
			for (auto &token : tokens)
				ss << token->stringValue();
			return ss.str();
		});

	}

	{
		static std::stack<float> stack;

		auto push = [&](float arg)
		{
			stack.push(arg); return arg;
		};
		auto pop = [&]()
		{
			if (stack.empty())
			{
				assert(false);
				return 0.0f;
			}
			auto a = stack.top();
			stack.pop();
			return a;
		};

		Functions::AddLambda("stack.push", push);
		Functions::AddLambda("stack.pop", pop);
	}

}

Parser::Parser()
{
	static bool initialized = false;
	if (!initialized)
	{
		initialized = true;
		_InitializeParser();
	}

	_rules.push_back(rule_whitespace_eater);
	_rules.push_back(rule_value);
	_rules.push_back(rule_string);
	_rules.push_back(rule_long_operator);
	_rules.push_back(rule_short_operator);
	_rules.push_back(embedded_function);

}

Parser::CompiledFunction Parser::Compile(const std::string& text)
{
	auto token = Parse(text);

	if (!token)
		return {};

#ifdef RPN_USE_JIT
	using namespace asmjit;

	auto& runtime = impl::jitRuntime();
	StringLogger logger;

	X86Assembler a(&runtime);
	X86Compiler c(&a);
	a.setLogger(&logger);

	c.addFunc(FuncBuilder0<float>(kCallConvHost));
	c.ret(token->Compile(c));
	c.endFunc();
	c.finalize();

	auto pointer = asmjit_cast<FunctionPtr>(a.make());

	return{ pointer , std::move(token) };
#else
	return{ nullptr , std::move(token) };
#endif
}
<|endoftext|>


<commit_before>#include "ReQL-test.hpp"

#include "catch.h"

#include <limits>

using namespace ReQL;

TEST_CASE("Connection", "[c++][connect]") {
  Connection conn = connect();

  REQUIRE(conn.isOpen());
}

TEST_CASE("decode errors", "[c][decode]") {
  SECTION("empty string") {
    const uint32_t size = 1;
    uint8_t src[size] = "";

    CHECK(_reql_decode(src, size) == NULL);
  }

  SECTION("unterminated null") {
    const uint32_t size = 4;
    uint8_t src[size] = "nul";

    CHECK(_reql_decode(src, size) == NULL);
  }

  SECTION("unterminated object") {
    const uint32_t size = 2;
    uint8_t src[size] = "{";

    CHECK(_reql_decode(src, size) == NULL);
  }

  SECTION("unterminated array") {
    const uint32_t size = 12;
    uint8_t src[size] = "[{}, [], 10";

    CHECK(_reql_decode(src, size) == NULL);
  }
}

TEST_CASE("decode values", "[c][decode]") {
  SECTION("null") {
    const uint32_t size = 6;
    uint8_t src[size] = " null";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_NULL);

    _reql_json_destroy(obj);
  }

  SECTION("true") {
    const uint32_t size = 6;
    uint8_t src[size] = "true ";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_BOOL);

    _reql_json_destroy(obj);
  }

  SECTION("false") {
    const uint32_t size = 6;
    uint8_t src[size] = "false";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_BOOL);

    _reql_json_destroy(obj);
  }

  SECTION("number") {
    const uint32_t size = 6;
    uint8_t src[size] = "12345";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_NUM);
    REQUIRE(_reql_to_number(obj) == 12345);

    _reql_json_destroy(obj);
  }

  SECTION("string") {
    const uint32_t size = 6;
    uint8_t src[size] = "\"hi!\"";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_STR);
    REQUIRE(3 == _reql_string_size(obj));

    std::string orig("hi!");

    REQUIRE(orig.compare(0, 3, (char *)_reql_string_buf(obj), _reql_string_size(obj)) == 0);

    _reql_json_destroy(obj);
  }

  SECTION("array") {
    const uint32_t size = 7;
    uint8_t src[size] = "[true]";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_ARRAY);

    _ReQL_Obj_t *val = _reql_array_last(obj);

    REQUIRE(val != NULL);
    REQUIRE(_reql_datum_type(val) == _REQL_R_BOOL);

    _reql_json_destroy(obj);
  }

  SECTION("object") {
    const uint32_t size = 10;
    uint8_t src[size] = "{\"key\":0}";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_OBJECT);

    const uint32_t key_size = 3;
    uint8_t key_buf[4];

    _ReQL_Obj_t key;
    _reql_string_init(&key, key_buf, key_size);
    _reql_string_append(&key, (uint8_t *)"key", key_size);

    REQUIRE(_reql_object_get(obj, &key) != NULL);
    REQUIRE(_reql_datum_type(_reql_object_get(obj, &key)) == _REQL_R_NUM);

    _reql_json_destroy(obj);
  }
}

TEST_CASE("decode term", "[c][decode]") {
  const uint32_t size = 95;
  uint8_t src[size] = "[1, [[15, [[30], [17], [12, [13.7, 15.4, 16.8], {}]], {\"key\": \"value\", \"other\":  false}]], {}]";

  _ReQL_Obj_t *obj = _reql_decode(src, size);

  REQUIRE(obj != NULL);

  _reql_json_destroy(obj);
}

TEST_CASE("Expr array", "[c][expr][array]") {
  _ReQL_Obj_t ary;

  const uint32_t size = 5;

  _ReQL_Obj_t *arr[size];

  _reql_array_init(&ary, arr, size);

  CHECK(_reql_datum_type(&ary) == _REQL_R_ARRAY);

  CHECK(_reql_array_size(&ary) == 0);

  SECTION("over fill array") {
    uint32_t i;

    for (i=0; i<size; ++i) {
      CHECK(_reql_array_append(&ary, &ary) == 0);
    }

    CHECK(_reql_array_append(&ary, &ary) != 0);
  }

  SECTION("grow and shrink") {
    _reql_array_append(&ary, &ary);

    CHECK(_reql_array_pop(&ary) != NULL);
    CHECK(_reql_array_last(&ary) == NULL);
    CHECK(_reql_array_pop(&ary) == NULL);
  }

  SECTION("insert after end") {
    CHECK(_reql_array_insert(&ary, &ary, size * 2) != 0);
  }
}

TEST_CASE("Expr object", "[c][expr][object]") {
  _ReQL_Obj_t obj, key, val;

  _ReQL_Pair_t pair[1];

  _reql_object_init(&obj, pair, 1);

  CHECK(_reql_datum_type(&obj) == _REQL_R_OBJECT);

  const uint32_t size = 4;

  uint8_t *buf = new uint8_t[size];
  const uint8_t string[] = "key";

  _reql_string_init(&key, buf, size);
  _reql_string_append(&key, string, size);

  _reql_null_init(&val);

  CHECK(_reql_object_add(&obj, &key, &val) == 0);

  SECTION("verify insert") {
    CHECK(_reql_object_get(&obj, &key) != NULL);

    _ReQL_Obj_t *res = _reql_object_get(&obj, &key);

    CHECK(_reql_datum_type(res) == _REQL_R_NULL);
  }

  SECTION("reuse key") {
    _ReQL_Obj_t new_val;

    const double num = 3.14;

    _reql_number_init(&new_val, num);

    CHECK(_reql_object_add(&obj, &key, &new_val) == 0);
    CHECK(_reql_object_get(&obj, &key) != NULL);

    _ReQL_Obj_t *res = _reql_object_get(&obj, &key);

    CHECK(_reql_datum_type(res) == _REQL_R_NUM);
    CHECK(_reql_to_number(res) == num);
  }

  SECTION("duplicate key") {
    _ReQL_Obj_t new_key, new_val;

    const double num = 3.14;

    uint8_t *new_buf = new uint8_t[size];
    const uint8_t new_string[] = "key";

    _reql_string_init(&new_key, new_buf, size);
    _reql_string_append(&new_key, new_string, size);

    _reql_number_init(&new_val, num);

    CHECK(_reql_object_add(&obj, &new_key, &new_val) == 0);
    CHECK(_reql_object_get(&obj, &new_key) != NULL);

    _ReQL_Obj_t *res = _reql_object_get(&obj, &new_key);

    CHECK(_reql_datum_type(res) == _REQL_R_NUM);

    delete [] new_buf;
  }

  SECTION("out of space") {
    _ReQL_Obj_t new_key, new_val;

    const double num = 3.14;

    uint8_t *new_buf = new uint8_t[size];
    const uint8_t new_string[] = "new";

    _reql_string_init(&new_key, new_buf, size);
    _reql_string_append(&new_key, new_string, size);

    _reql_number_init(&new_val, num);

    CHECK(_reql_object_add(&obj, &new_key, &new_val) != 0);
    CHECK(_reql_object_get(&obj, &new_key) == NULL);

    _ReQL_Obj_t *res = _reql_object_get(&obj, &key);

    CHECK(_reql_datum_type(res) == _REQL_R_NULL);

    delete [] new_buf;
  }

  delete [] buf;
}

TEST_CASE("Expr", "[c][expr]") {
  _ReQL_Obj_t val;

  SECTION("bool") {
    _reql_bool_init(&val, 10);

    CHECK(_reql_datum_type(&val) == _REQL_R_BOOL);

    CHECK(_reql_to_bool(&val) == true);

    _reql_bool_init(&val, false);

    CHECK(_reql_to_bool(&val) == false);
  }

  SECTION("null") {
    _reql_null_init(&val);

    CHECK(_reql_datum_type(&val) == _REQL_R_NULL);
  }

  SECTION("number") {
    const double num = 42.0;

    _reql_number_init(&val, num);

    CHECK(_reql_datum_type(&val) == _REQL_R_NUM);

    CHECK(num == _reql_to_number(&val));
  }

  SECTION("number edges") {
    const double num = std::numeric_limits<std::double_t>::max();

    _reql_number_init(&val, num);

    CHECK(num == _reql_to_number(&val));
  }

  SECTION("string") {
    const uint32_t size = 12;

    uint8_t *buf = new uint8_t[size];
    const uint8_t hello[] = "Hello World";

    std::string orig = std::string((char *)hello, size);

    _reql_string_init(&val, buf, size);
    _reql_string_append(&val, hello, size);

    CHECK(_reql_datum_type(&val) == _REQL_R_STR);

    CHECK(orig.compare(0, size, (char *)_reql_string_buf(&val), size) == 0);
    CHECK(size == _reql_string_size(&val));

    delete [] buf;
  }
}
<commit_msg>Add encode value tests.<commit_after>#include "ReQL-test.hpp"

#include "catch.h"

#include <limits>

using namespace ReQL;

TEST_CASE("Connection", "[c++][connect]") {
  Connection conn = connect();

  REQUIRE(conn.isOpen());
}

TEST_CASE("decode errors", "[c][decode]") {
  SECTION("empty string") {
    const uint32_t size = 1;
    uint8_t src[size] = "";

    CHECK(_reql_decode(src, size) == NULL);
  }

  SECTION("unterminated null") {
    const uint32_t size = 4;
    uint8_t src[size] = "nul";

    CHECK(_reql_decode(src, size) == NULL);
  }

  SECTION("unterminated object") {
    const uint32_t size = 2;
    uint8_t src[size] = "{";

    CHECK(_reql_decode(src, size) == NULL);
  }

  SECTION("unterminated array") {
    const uint32_t size = 12;
    uint8_t src[size] = "[{}, [], 10";

    CHECK(_reql_decode(src, size) == NULL);
  }
}

TEST_CASE("decode values", "[c][decode]") {
  SECTION("null") {
    const uint32_t size = 6;
    uint8_t src[size] = " null";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_NULL);

    _reql_json_destroy(obj);
  }

  SECTION("true") {
    const uint32_t size = 6;
    uint8_t src[size] = "true ";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_BOOL);

    _reql_json_destroy(obj);
  }

  SECTION("false") {
    const uint32_t size = 6;
    uint8_t src[size] = "false";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_BOOL);

    _reql_json_destroy(obj);
  }

  SECTION("number") {
    const uint32_t size = 6;
    uint8_t src[size] = "12345";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_NUM);
    REQUIRE(_reql_to_number(obj) == 12345);

    _reql_json_destroy(obj);
  }

  SECTION("string") {
    const uint32_t size = 6;
    uint8_t src[size] = "\"hi!\"";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_STR);
    REQUIRE(3 == _reql_string_size(obj));

    std::string orig("hi!");

    REQUIRE(orig.compare(0, 3, (char *)_reql_string_buf(obj), _reql_string_size(obj)) == 0);

    _reql_json_destroy(obj);
  }

  SECTION("array") {
    const uint32_t size = 7;
    uint8_t src[size] = "[true]";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_ARRAY);

    _ReQL_Obj_t *val = _reql_array_last(obj);

    REQUIRE(val != NULL);
    REQUIRE(_reql_datum_type(val) == _REQL_R_BOOL);

    _reql_json_destroy(obj);
  }

  SECTION("object") {
    const uint32_t size = 10;
    uint8_t src[size] = "{\"key\":0}";

    _ReQL_Obj_t *obj = _reql_decode(src, size);

    REQUIRE(obj != NULL);
    REQUIRE(_reql_datum_type(obj) == _REQL_R_OBJECT);

    const uint32_t key_size = 3;
    uint8_t key_buf[4];

    _ReQL_Obj_t key;
    _reql_string_init(&key, key_buf, key_size);
    _reql_string_append(&key, (uint8_t *)"key", key_size);

    REQUIRE(_reql_object_get(obj, &key) != NULL);
    REQUIRE(_reql_datum_type(_reql_object_get(obj, &key)) == _REQL_R_NUM);

    _reql_json_destroy(obj);
  }
}

TEST_CASE("decode term", "[c][decode]") {
  const uint32_t size = 95;
  uint8_t src[size] = "[1, [[15, [[30], [17], [12, [13.7, 15.4, 16.8], {}]], {\"key\": \"value\", \"other\":  false}]], {}]";

  _ReQL_Obj_t *obj = _reql_decode(src, size);

  REQUIRE(obj != NULL);

  _reql_json_destroy(obj);
}

TEST_CASE("encode values", "[c][encode]") {
  _ReQL_Obj_t val;

  SECTION("null") {
    _reql_null_init(&val);

    _ReQL_String_t *str = _reql_encode(&val);

    REQUIRE(str != NULL);

    REQUIRE(str->size == 4);
  }

  SECTION("true") {
    _reql_bool_init(&val, 1);

    _ReQL_String_t *str = _reql_encode(&val);

    REQUIRE(str != NULL);

    REQUIRE(str->size == 4);
  }

  SECTION("false") {
    _reql_bool_init(&val, 0);

    _ReQL_String_t *str = _reql_encode(&val);

    REQUIRE(str != NULL);

    REQUIRE(str->size == 5);
  }

  SECTION("number") {
    _reql_number_init(&val, 1.01);

    _ReQL_String_t *str = _reql_encode(&val);

    REQUIRE(str != NULL);

    REQUIRE(str->size == 4);

    std::string comp("1.01");

    REQUIRE(comp.compare((char *)str->str) == 0);
  }

  SECTION("string") {
    const uint32_t size = 11;

    uint8_t *buf = new uint8_t[size];
    const uint8_t hello[] = "Hello World";

    _reql_string_init(&val, buf, size);
    _reql_string_append(&val, hello, size);

    _ReQL_String_t *str = _reql_encode(&val);

    REQUIRE(str != NULL);

    REQUIRE(str->size == size + 2);

    delete [] buf;
  }

  SECTION("array") {
    _reql_array_init(&val, NULL, 0);

    _ReQL_String_t *str = _reql_encode(&val);

    REQUIRE(str != NULL);

    REQUIRE(str->size == 2);
  }

  SECTION("object") {
    _reql_object_init(&val, NULL, 0);

    _ReQL_String_t *str = _reql_encode(&val);

    REQUIRE(str != NULL);

    REQUIRE(str->size == 2);
  }
}

TEST_CASE("Expr array", "[c][expr][array]") {
  _ReQL_Obj_t ary;

  const uint32_t size = 5;

  _ReQL_Obj_t *arr[size];

  _reql_array_init(&ary, arr, size);

  CHECK(_reql_datum_type(&ary) == _REQL_R_ARRAY);

  CHECK(_reql_array_size(&ary) == 0);

  SECTION("over fill array") {
    uint32_t i;

    for (i=0; i<size; ++i) {
      CHECK(_reql_array_append(&ary, &ary) == 0);
    }

    CHECK(_reql_array_append(&ary, &ary) != 0);
  }

  SECTION("grow and shrink") {
    _reql_array_append(&ary, &ary);

    CHECK(_reql_array_pop(&ary) != NULL);
    CHECK(_reql_array_last(&ary) == NULL);
    CHECK(_reql_array_pop(&ary) == NULL);
  }

  SECTION("insert after end") {
    CHECK(_reql_array_insert(&ary, &ary, size * 2) != 0);
  }
}

TEST_CASE("Expr object", "[c][expr][object]") {
  _ReQL_Obj_t obj, key, val;

  _ReQL_Pair_t pair[1];

  _reql_object_init(&obj, pair, 1);

  CHECK(_reql_datum_type(&obj) == _REQL_R_OBJECT);

  const uint32_t size = 4;

  uint8_t *buf = new uint8_t[size];
  const uint8_t string[] = "key";

  _reql_string_init(&key, buf, size);
  _reql_string_append(&key, string, size);

  _reql_null_init(&val);

  CHECK(_reql_object_add(&obj, &key, &val) == 0);

  SECTION("verify insert") {
    CHECK(_reql_object_get(&obj, &key) != NULL);

    _ReQL_Obj_t *res = _reql_object_get(&obj, &key);

    CHECK(_reql_datum_type(res) == _REQL_R_NULL);
  }

  SECTION("reuse key") {
    _ReQL_Obj_t new_val;

    const double num = 3.14;

    _reql_number_init(&new_val, num);

    CHECK(_reql_object_add(&obj, &key, &new_val) == 0);
    CHECK(_reql_object_get(&obj, &key) != NULL);

    _ReQL_Obj_t *res = _reql_object_get(&obj, &key);

    CHECK(_reql_datum_type(res) == _REQL_R_NUM);
    CHECK(_reql_to_number(res) == num);
  }

  SECTION("duplicate key") {
    _ReQL_Obj_t new_key, new_val;

    const double num = 3.14;

    uint8_t *new_buf = new uint8_t[size];
    const uint8_t new_string[] = "key";

    _reql_string_init(&new_key, new_buf, size);
    _reql_string_append(&new_key, new_string, size);

    _reql_number_init(&new_val, num);

    CHECK(_reql_object_add(&obj, &new_key, &new_val) == 0);
    CHECK(_reql_object_get(&obj, &new_key) != NULL);

    _ReQL_Obj_t *res = _reql_object_get(&obj, &new_key);

    CHECK(_reql_datum_type(res) == _REQL_R_NUM);

    delete [] new_buf;
  }

  SECTION("out of space") {
    _ReQL_Obj_t new_key, new_val;

    const double num = 3.14;

    uint8_t *new_buf = new uint8_t[size];
    const uint8_t new_string[] = "new";

    _reql_string_init(&new_key, new_buf, size);
    _reql_string_append(&new_key, new_string, size);

    _reql_number_init(&new_val, num);

    CHECK(_reql_object_add(&obj, &new_key, &new_val) != 0);
    CHECK(_reql_object_get(&obj, &new_key) == NULL);

    _ReQL_Obj_t *res = _reql_object_get(&obj, &key);

    CHECK(_reql_datum_type(res) == _REQL_R_NULL);

    delete [] new_buf;
  }

  delete [] buf;
}

TEST_CASE("Expr", "[c][expr]") {
  _ReQL_Obj_t val;

  SECTION("bool") {
    _reql_bool_init(&val, 10);

    CHECK(_reql_datum_type(&val) == _REQL_R_BOOL);

    CHECK(_reql_to_bool(&val) == true);

    _reql_bool_init(&val, false);

    CHECK(_reql_to_bool(&val) == false);
  }

  SECTION("null") {
    _reql_null_init(&val);

    CHECK(_reql_datum_type(&val) == _REQL_R_NULL);
  }

  SECTION("number") {
    const double num = 42.0;

    _reql_number_init(&val, num);

    CHECK(_reql_datum_type(&val) == _REQL_R_NUM);

    CHECK(num == _reql_to_number(&val));
  }

  SECTION("number edges") {
    const double num = std::numeric_limits<std::double_t>::max();

    _reql_number_init(&val, num);

    CHECK(num == _reql_to_number(&val));
  }

  SECTION("string") {
    const uint32_t size = 12;

    uint8_t *buf = new uint8_t[size];
    const uint8_t hello[] = "Hello World";

    std::string orig = std::string((char *)hello, size);

    _reql_string_init(&val, buf, size);
    _reql_string_append(&val, hello, size);

    CHECK(_reql_datum_type(&val) == _REQL_R_STR);

    CHECK(orig.compare(0, size, (char *)_reql_string_buf(&val), size) == 0);
    CHECK(size == _reql_string_size(&val));

    delete [] buf;
  }
}
<|endoftext|>