<commit_before>#include "3DOFile.hpp"

#include "HPIFile.hpp"
#include <iostream>
#include <string.h>
#include <cmath>
#include <unordered_map>
#include "Gaf.hpp"

std::unordered_map<std::string,GLuint> TextureMap;
extern HPI * hpi;
void LoadTexture(std::string Name);
Gaf ** TextureGafs;
int NumTextureGafs;

GLuint GetGLTexture(std::string Name)
{
    if(TextureMap.count(Name)==0)
	LoadTexture(Name);

    return TextureMap[Name];
}

void LoadTextureList()
{
    //load all gafs from /textures
    HPIDirectory * TexturesDirectory=hpi->GetDirectory("/textures");
    NumTextureGafs=TexturesDirectory->NumFiles;
    TextureGafs=new Gaf*[NumTextureGafs];
    for(int FileIndex=0;FileIndex<TexturesDirectory->NumFiles;FileIndex++)
    {
	unsigned char * temp=new unsigned char[TexturesDirectory->Files[FileIndex]->GetData(nullptr)];
	TexturesDirectory->Files[FileIndex]->GetData(temp);
    	TextureGafs[FileIndex]=new Gaf(temp);
	delete [] temp;
    }
}

void LoadTexture(std::string Name)
{
    GLuint NewTexture=0;
    for(int TextureIndex=0;TextureIndex<NumTextureGafs;TextureIndex++)
    {
	NewTexture=TextureGafs[TextureIndex]->GetGLTexture(Name);
	if(NewTexture!=0)
	    break;
    }
    if(NewTexture!=0)
	TextureMap[Name]=NewTexture;
}

const float TA_TO_GL_SCALE=1/2500000.0f;//this gives an arm solar collector of approximately size 2x2 units
const int FLOATS_PER_TRIANGLE=15;//each triangle has 3x3 position coords, and 3x2 texture coords
const int COLORS_PER_TRIANGLE=3;
void FillArraysForTriangle(GLfloat * PosTexArray,uint16_t * Indexes, float * Vertices,float * UVCoords,int16_t ColorIndex,int16_t * ColorIndexes)
{
    for(int vertex=0;vertex<3;vertex++)
    {
	PosTexArray[vertex*5]=Vertices[Indexes[vertex]*3];
	PosTexArray[vertex*5+1]=Vertices[Indexes[vertex]*3+1];
	PosTexArray[vertex*5+2]=Vertices[Indexes[vertex]*3+2];
	PosTexArray[vertex*5+3]=UVCoords[vertex*3];
	PosTexArray[vertex*5+4]=UVCoords[vertex*3+1];
	ColorIndexes[vertex]=ColorIndex;
    }
}

Unit3DObject::Unit3DObject(unsigned char * buffer, int offset)
{
    if(*(int32_t*)&buffer[offset]!=1)
    {
	std::cout<<"Unknown signature "<<*(int32_t*)&buffer[offset]<<std::endl;
	return;
    }
    offset+=4;
    int NumVertices=*(int32_t*)(&buffer[offset]);
    offset+=4;

    int NumPrimitives=*(int32_t*)(&buffer[offset]);
    offset+=4;

    //this will apparently be -1 for all child objects - will need ignore in that case
    int OffsetToSelectionPrimitive=*(int32_t*)(&buffer[offset]);
    offset+=4;

    int X=*(int32_t*)(&buffer[offset]);
    offset+=4;
    int Y=*(int32_t*)(&buffer[offset]);
    offset+=4;
    int Z=*(int32_t*)(&buffer[offset]);
    offset+=4;
    GLfloat pos[]={X*TA_TO_GL_SCALE,Y*TA_TO_GL_SCALE,Z*TA_TO_GL_SCALE};
    LocationMatrix.SetPosition(pos);

    int NameOffset=*(int32_t*)(&buffer[offset]);
    Name=std::string((char *)&buffer[NameOffset]);
    offset+=4;
    //Dont care about apparently always 0 field
    //TODO: check field for all cavedog models in case some are not 0 and this field is significant
    offset+=4;

    int VertexArrayOffset=*(int32_t*)(&buffer[offset]);
    offset+=4;
    int PrimitiveArrayOffset=*(int32_t*)(&buffer[offset]);
    offset+=4;

    const int OffsetToSibling=44;
    offset+=4;
    int ChildOffset=*(int32_t*)(&buffer[offset]);

    NumChildren=0;
    if(ChildOffset!=0)
    {
	NumChildren++;
	int SiblingOffset=*(int32_t *)&buffer[ChildOffset+OffsetToSibling];
	while(SiblingOffset!=0)
	{
	    SiblingOffset=*(int32_t *)&buffer[SiblingOffset+OffsetToSibling];
	    NumChildren++;
	}
    }

    int32_t IntVertices[NumVertices*3];
    memcpy(IntVertices,&buffer[VertexArrayOffset],NumVertices*4*3);//read 3 32-bit integers per vertex
    GLfloat Vertices[NumVertices*3];
    for(int vertIndex=0;vertIndex<NumVertices*3;vertIndex++)
    {
	Vertices[vertIndex]=IntVertices[vertIndex]*TA_TO_GL_SCALE;
    }

    int32_t PossibleTextures[NumPrimitives];
    int PrimitiveToTextureMap[NumPrimitives];
    int CurrentTexNum=0;
    for(int PrimIndex=0;PrimIndex<NumPrimitives;PrimIndex++)
    {
	//docs were unclear on this, but data shows this is the primitive index, not a buffer offset
	if(OffsetToSelectionPrimitive == PrimIndex)
	{
	    //this is the selection primitive - just ignore for now, should load it into the
	    //selection VAO for rendering later
	    PrimitiveToTextureMap[PrimIndex]=-1;
	    continue;
	}
	int32_t TexOffset=*(int32_t*)&buffer[PrimitiveArrayOffset+16+PrimIndex*32];//texture offset is at the 5th 32-bit int, Primitive has 8 32-bit ints
	//Not ignoring 0 here as we need to group no texture primitives and render them separately from the others
	bool found=false;
	for(int TexIndex=0;TexIndex<CurrentTexNum;TexIndex++)
	{
	    if(PossibleTextures[TexIndex]==TexOffset)
	    {
		found=true;
		PrimitiveToTextureMap[PrimIndex]=TexIndex;
		break;
	    }
	}
	if(!found)
	{
	    PrimitiveToTextureMap[PrimIndex]=CurrentTexNum;
	    PossibleTextures[CurrentTexNum++]=TexOffset;
	}
    }
    NumTextures=CurrentTexNum;
    NumTriangles=new int[NumTextures];
    Textures=new GLuint[NumTextures];
    VertexArrayObjects=new GLuint[NumTextures];
    glGenVertexArrays(NumTextures,VertexArrayObjects);
    memset(Textures,0,sizeof(GLuint)*NumTextures);

    for(int TextureIndex=0; TextureIndex<NumTextures;TextureIndex++)
    {
	if(PossibleTextures[TextureIndex]!=0)
	{
	    //TODO: Load texture from global pool
	}
	NumTriangles[TextureIndex]=0;
	for(int PrimIndex=0;PrimIndex<NumPrimitives;PrimIndex++)
	{
	    if(PrimitiveToTextureMap[PrimIndex]==TextureIndex)
	    {
		int offset=PrimitiveArrayOffset+PrimIndex*32;
		offset+=4;

		int32_t NumberOfVertices=*(int32_t *)&buffer[offset];
		NumTriangles[TextureIndex]+=NumberOfVertices-2>0?NumberOfVertices-2:0;
	    }
	}
	GLfloat PositionAndTexCoord[NumTriangles[TextureIndex]*FLOATS_PER_TRIANGLE];
	int16_t ColorIndexes[NumTriangles[TextureIndex]*COLORS_PER_TRIANGLE];
	int CurrentTriangle=0;
	for(int PrimIndex=0;PrimIndex<NumPrimitives;PrimIndex++)
	{
	    if(PrimitiveToTextureMap[PrimIndex]==TextureIndex)
	    {
		int offset=PrimitiveArrayOffset+PrimIndex*32;
		int32_t ColorIndex=*(int32_t *)&buffer[offset];
		offset+=4;

		int32_t NumberOfVertices=*(int32_t *)&buffer[offset];
		offset+=4;

		offset+=4;//this field is apparently always 0, maybe test later?

		int32_t VertexIndexArrayOffset=*(int32_t *)&buffer[offset];
		offset+=4;

		offset+=4;//this is the texture offset, which we have already stored

		//the final three 32-bit ints are apparently cavedog specific and only used for their editor?
		uint16_t * IndexArray=(uint16_t*)&buffer[VertexIndexArrayOffset];

		switch(NumberOfVertices)
		{
		case 1:
		case 2:
		    //Ignore points and lines for rendering, at least for now
		    std::cout<<"Line or point ignored"<<std::endl;
		    break;
		case 3:
		{
		    GLfloat UVCoords[]={0,0,0,1,1,1};
		    FillArraysForTriangle(&PositionAndTexCoord[CurrentTriangle*FLOATS_PER_TRIANGLE],IndexArray,Vertices,UVCoords,ColorIndex,&ColorIndexes[CurrentTriangle*COLORS_PER_TRIANGLE]);
		    CurrentTriangle++;
		}
		    break;
		case 4:
		{
		    GLfloat UVCoords[]={0,0,1,0,1,1,0,0,1,1,0,1};
		    uint16_t TempIndexes[]={IndexArray[0],IndexArray[3],IndexArray[2]};
		    FillArraysForTriangle(&PositionAndTexCoord[CurrentTriangle*FLOATS_PER_TRIANGLE],TempIndexes,Vertices,&UVCoords[6],ColorIndex,&ColorIndexes[CurrentTriangle*COLORS_PER_TRIANGLE]);
		    TempIndexes[1]=IndexArray[2];
		    TempIndexes[2]=IndexArray[1];
		    CurrentTriangle++;
		    FillArraysForTriangle(&PositionAndTexCoord[CurrentTriangle*FLOATS_PER_TRIANGLE],TempIndexes,Vertices,UVCoords,ColorIndex,&ColorIndexes[CurrentTriangle*COLORS_PER_TRIANGLE]);
		    CurrentTriangle++;
		}
		    break;
		case 5:
		    std::cout<<"Currently not treating pentagons specially"<<std::endl;
		default:
		{
		    std::cout<<"Found a primitive of size "<<NumberOfVertices<<", using default 6+ side polygon code"<<std::endl;
		    for(int i=0;i<NumberOfVertices-2;i++)
		    {
			uint16_t TempIndexes[]={IndexArray[i],IndexArray[i+1],IndexArray[NumberOfVertices-1]};
			GLfloat UVCoords[6];
			for(int j=0;j<3;j++)
			{
			    UVCoords[j*2]=0.5f*(1-(sin((2.0f*(i+j)+1)*PI/float(NumberOfVertices))/cos(PI/NumberOfVertices)));
			    UVCoords[j*2+1]=0.5f*(1-(cos(PI/NumberOfVertices*(2.0f*(i+j)+1))/cos(PI/NumberOfVertices)));
			}
			FillArraysForTriangle(&PositionAndTexCoord[CurrentTriangle*FLOATS_PER_TRIANGLE],TempIndexes,Vertices,UVCoords,ColorIndex,&ColorIndexes[CurrentTriangle*COLORS_PER_TRIANGLE]);
			CurrentTriangle++;
		    }
		}
		    break;
		}
	    }
	}
	glBindVertexArray(VertexArrayObjects[TextureIndex]);

	GLuint VertexBuffer;
	glGenBuffers(1,&VertexBuffer);

	glBindBuffer(GL_ARRAY_BUFFER,VertexBuffer);
	glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*NumTriangles[TextureIndex]*FLOATS_PER_TRIANGLE,PositionAndTexCoord,GL_STATIC_DRAW);
	glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*FLOATS_PER_TRIANGLE/3,0);
	glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*FLOATS_PER_TRIANGLE/3,(GLvoid*)(sizeof(GLfloat)*3));

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	GLuint ColorBuffer;
	glGenBuffers(1,&ColorBuffer);
	glBindBuffer(GL_ARRAY_BUFFER,ColorBuffer);
	glBufferData(GL_ARRAY_BUFFER,sizeof(int16_t)*NumTriangles[TextureIndex]*COLORS_PER_TRIANGLE,ColorIndexes,GL_STATIC_DRAW);
	glVertexAttribPointer(2,1,GL_SHORT,GL_FALSE,0,0);
	glEnableVertexAttribArray(2);

	glBindVertexArray(0);
	glDeleteBuffers(1,&VertexBuffer);
	glDeleteBuffers(1,&ColorBuffer);
    }

    Children = new Unit3DObject *[NumChildren];
    for(int i=0;i<NumChildren;i++)
    {
	Children[i]=new Unit3DObject(buffer,ChildOffset);
	ChildOffset=*(int32_t *)&buffer[ChildOffset+OffsetToSibling];
    }

}

void Unit3DObject::Render(Matrix Model,GLuint ModelViewLoc,Matrix ParentTrans)
{
    Matrix NewTrans=LocationMatrix*ParentTrans;
    (Model*NewTrans).Upload(ModelViewLoc);
    for(int TextureIndex=0;TextureIndex<NumTextures;TextureIndex++)
    {
	glBindVertexArray(VertexArrayObjects[TextureIndex]);
	glDrawArrays(GL_TRIANGLES,0,NumTriangles[TextureIndex]*3);
    }
    for(int ChildIndex=0;ChildIndex<NumChildren;ChildIndex++)
    {
	Children[ChildIndex]->Render(Model,ModelViewLoc,NewTrans);
    }
}
<commit_msg>Fix arbitrary sized polygon tex coord generation to actually work.<commit_after>#include "3DOFile.hpp"

#include "HPIFile.hpp"
#include <iostream>
#include <string.h>
#include <cmath>
#include <unordered_map>
#include "Gaf.hpp"

std::unordered_map<std::string,GLuint> TextureMap;
extern HPI * hpi;
void LoadTexture(std::string Name);
Gaf ** TextureGafs;
int NumTextureGafs;

GLuint GetGLTexture(std::string Name)
{
    if(TextureMap.count(Name)==0)
	LoadTexture(Name);

    return TextureMap[Name];
}

void LoadTextureList()
{
    //load all gafs from /textures
    HPIDirectory * TexturesDirectory=hpi->GetDirectory("/textures");
    NumTextureGafs=TexturesDirectory->NumFiles;
    TextureGafs=new Gaf*[NumTextureGafs];
    for(int FileIndex=0;FileIndex<TexturesDirectory->NumFiles;FileIndex++)
    {
	unsigned char * temp=new unsigned char[TexturesDirectory->Files[FileIndex]->GetData(nullptr)];
	TexturesDirectory->Files[FileIndex]->GetData(temp);
    	TextureGafs[FileIndex]=new Gaf(temp);
	delete [] temp;
    }
}

void LoadTexture(std::string Name)
{
    GLuint NewTexture=0;
    for(int TextureIndex=0;TextureIndex<NumTextureGafs;TextureIndex++)
    {
	NewTexture=TextureGafs[TextureIndex]->GetGLTexture(Name);
	if(NewTexture!=0)
	    break;
    }
    if(NewTexture!=0)
	TextureMap[Name]=NewTexture;
}

const float TA_TO_GL_SCALE=1/2500000.0f;//this gives an arm solar collector of approximately size 2x2 units
const int FLOATS_PER_TRIANGLE=15;//each triangle has 3x3 position coords, and 3x2 texture coords
const int COLORS_PER_TRIANGLE=3;
void FillArraysForTriangle(GLfloat * PosTexArray,uint16_t * Indexes, float * Vertices,float * UVCoords,int16_t ColorIndex,int16_t * ColorIndexes)
{
    for(int vertex=0;vertex<3;vertex++)
    {
	PosTexArray[vertex*5]=Vertices[Indexes[vertex]*3];
	PosTexArray[vertex*5+1]=Vertices[Indexes[vertex]*3+1];
	PosTexArray[vertex*5+2]=Vertices[Indexes[vertex]*3+2];
	PosTexArray[vertex*5+3]=UVCoords[vertex*3];
	PosTexArray[vertex*5+4]=UVCoords[vertex*3+1];
	ColorIndexes[vertex]=ColorIndex;
    }
}

Unit3DObject::Unit3DObject(unsigned char * buffer, int offset)
{
    if(*(int32_t*)&buffer[offset]!=1)
    {
	std::cout<<"Unknown signature "<<*(int32_t*)&buffer[offset]<<std::endl;
	return;
    }
    offset+=4;
    int NumVertices=*(int32_t*)(&buffer[offset]);
    offset+=4;

    int NumPrimitives=*(int32_t*)(&buffer[offset]);
    offset+=4;

    //this will apparently be -1 for all child objects - will need ignore in that case
    int OffsetToSelectionPrimitive=*(int32_t*)(&buffer[offset]);
    offset+=4;

    int X=*(int32_t*)(&buffer[offset]);
    offset+=4;
    int Y=*(int32_t*)(&buffer[offset]);
    offset+=4;
    int Z=*(int32_t*)(&buffer[offset]);
    offset+=4;
    GLfloat pos[]={X*TA_TO_GL_SCALE,Y*TA_TO_GL_SCALE,Z*TA_TO_GL_SCALE};
    LocationMatrix.SetPosition(pos);

    int NameOffset=*(int32_t*)(&buffer[offset]);
    Name=std::string((char *)&buffer[NameOffset]);
    offset+=4;
    //Dont care about apparently always 0 field
    //TODO: check field for all cavedog models in case some are not 0 and this field is significant
    offset+=4;

    int VertexArrayOffset=*(int32_t*)(&buffer[offset]);
    offset+=4;
    int PrimitiveArrayOffset=*(int32_t*)(&buffer[offset]);
    offset+=4;

    const int OffsetToSibling=44;
    offset+=4;
    int ChildOffset=*(int32_t*)(&buffer[offset]);

    NumChildren=0;
    if(ChildOffset!=0)
    {
	NumChildren++;
	int SiblingOffset=*(int32_t *)&buffer[ChildOffset+OffsetToSibling];
	while(SiblingOffset!=0)
	{
	    SiblingOffset=*(int32_t *)&buffer[SiblingOffset+OffsetToSibling];
	    NumChildren++;
	}
    }

    int32_t IntVertices[NumVertices*3];
    memcpy(IntVertices,&buffer[VertexArrayOffset],NumVertices*4*3);//read 3 32-bit integers per vertex
    GLfloat Vertices[NumVertices*3];
    for(int vertIndex=0;vertIndex<NumVertices*3;vertIndex++)
    {
	Vertices[vertIndex]=IntVertices[vertIndex]*TA_TO_GL_SCALE;
    }

    int32_t PossibleTextures[NumPrimitives];
    int PrimitiveToTextureMap[NumPrimitives];
    int CurrentTexNum=0;
    for(int PrimIndex=0;PrimIndex<NumPrimitives;PrimIndex++)
    {
	//docs were unclear on this, but data shows this is the primitive index, not a buffer offset
	if(OffsetToSelectionPrimitive == PrimIndex)
	{
	    //this is the selection primitive - just ignore for now, should load it into the
	    //selection VAO for rendering later
	    PrimitiveToTextureMap[PrimIndex]=-1;
	    continue;
	}
	int32_t TexOffset=*(int32_t*)&buffer[PrimitiveArrayOffset+16+PrimIndex*32];//texture offset is at the 5th 32-bit int, Primitive has 8 32-bit ints
	//Not ignoring 0 here as we need to group no texture primitives and render them separately from the others
	bool found=false;
	for(int TexIndex=0;TexIndex<CurrentTexNum;TexIndex++)
	{
	    if(PossibleTextures[TexIndex]==TexOffset)
	    {
		found=true;
		PrimitiveToTextureMap[PrimIndex]=TexIndex;
		break;
	    }
	}
	if(!found)
	{
	    PrimitiveToTextureMap[PrimIndex]=CurrentTexNum;
	    PossibleTextures[CurrentTexNum++]=TexOffset;
	}
    }
    NumTextures=CurrentTexNum;
    NumTriangles=new int[NumTextures];
    Textures=new GLuint[NumTextures];
    VertexArrayObjects=new GLuint[NumTextures];
    glGenVertexArrays(NumTextures,VertexArrayObjects);
    memset(Textures,0,sizeof(GLuint)*NumTextures);

    for(int TextureIndex=0; TextureIndex<NumTextures;TextureIndex++)
    {
	if(PossibleTextures[TextureIndex]!=0)
	{
	    //TODO: Load texture from global pool
	}
	NumTriangles[TextureIndex]=0;
	for(int PrimIndex=0;PrimIndex<NumPrimitives;PrimIndex++)
	{
	    if(PrimitiveToTextureMap[PrimIndex]==TextureIndex)
	    {
		int offset=PrimitiveArrayOffset+PrimIndex*32;
		offset+=4;

		int32_t NumberOfVertices=*(int32_t *)&buffer[offset];
		NumTriangles[TextureIndex]+=NumberOfVertices-2>0?NumberOfVertices-2:0;
	    }
	}
	GLfloat PositionAndTexCoord[NumTriangles[TextureIndex]*FLOATS_PER_TRIANGLE];
	int16_t ColorIndexes[NumTriangles[TextureIndex]*COLORS_PER_TRIANGLE];
	int CurrentTriangle=0;
	for(int PrimIndex=0;PrimIndex<NumPrimitives;PrimIndex++)
	{
	    if(PrimitiveToTextureMap[PrimIndex]==TextureIndex)
	    {
		int offset=PrimitiveArrayOffset+PrimIndex*32;
		int32_t ColorIndex=*(int32_t *)&buffer[offset];
		offset+=4;

		int32_t NumberOfVertices=*(int32_t *)&buffer[offset];
		offset+=4;

		offset+=4;//this field is apparently always 0, maybe test later?

		int32_t VertexIndexArrayOffset=*(int32_t *)&buffer[offset];
		offset+=4;

		offset+=4;//this is the texture offset, which we have already stored

		//the final three 32-bit ints are apparently cavedog specific and only used for their editor?
		uint16_t * IndexArray=(uint16_t*)&buffer[VertexIndexArrayOffset];

		switch(NumberOfVertices)
		{
		case 1:
		case 2:
		    //Ignore points and lines for rendering, at least for now
		    std::cout<<"Line or point ignored"<<std::endl;
		    break;
		case 3:
		{
		    GLfloat UVCoords[]={0,0,0,1,1,1};
		    FillArraysForTriangle(&PositionAndTexCoord[CurrentTriangle*FLOATS_PER_TRIANGLE],IndexArray,Vertices,UVCoords,ColorIndex,&ColorIndexes[CurrentTriangle*COLORS_PER_TRIANGLE]);
		    CurrentTriangle++;
		}
		    break;
		case 4:
		{
		    GLfloat UVCoords[]={0,0,1,0,1,1,0,0,1,1,0,1};
		    uint16_t TempIndexes[]={IndexArray[0],IndexArray[3],IndexArray[2]};
		    FillArraysForTriangle(&PositionAndTexCoord[CurrentTriangle*FLOATS_PER_TRIANGLE],TempIndexes,Vertices,&UVCoords[6],ColorIndex,&ColorIndexes[CurrentTriangle*COLORS_PER_TRIANGLE]);
		    TempIndexes[1]=IndexArray[2];
		    TempIndexes[2]=IndexArray[1];
		    CurrentTriangle++;
		    FillArraysForTriangle(&PositionAndTexCoord[CurrentTriangle*FLOATS_PER_TRIANGLE],TempIndexes,Vertices,UVCoords,ColorIndex,&ColorIndexes[CurrentTriangle*COLORS_PER_TRIANGLE]);
		    CurrentTriangle++;
		}
		    break;
		case 5:
		    std::cout<<"Currently not treating pentagons specially"<<std::endl;
		default:
		{
		    std::cout<<"Found a primitive of size "<<NumberOfVertices<<", using default 6+ side polygon code"<<std::endl;
		    GLfloat UVCoords[6];
		    //Map sin/cos unit circle at (0,0) onto 1/2 unit circle at (0.5,0.5)
		    UVCoords[2*2]=0.5f*(1-(sin((2.0f*(NumberOfVertices-1)+1)*PI/float(NumberOfVertices))/cos(PI/NumberOfVertices)));
		    UVCoords[2*2+1]=0.5f*(1-(cos(PI/NumberOfVertices*(2.0f*(NumberOfVertices-1)+1))/cos(PI/NumberOfVertices)));

		    for(int i=0;i<NumberOfVertices-2;i++)
		    {
			uint16_t TempIndexes[]={IndexArray[i],IndexArray[i+1],IndexArray[NumberOfVertices-1]};

			for(int j=0;j<2;j++)
			{
			    //Map sin/cos unit circle at (0,0) onto 1/2 unit circle at (0.5,0.5)
			    UVCoords[j*2]=0.5f*(1-(sin((2.0f*(i+j)+1)*PI/float(NumberOfVertices))/cos(PI/NumberOfVertices)));
			    UVCoords[j*2+1]=0.5f*(1-(cos(PI/NumberOfVertices*(2.0f*(i+j)+1))/cos(PI/NumberOfVertices)));
			}
			FillArraysForTriangle(&PositionAndTexCoord[CurrentTriangle*FLOATS_PER_TRIANGLE],TempIndexes,Vertices,UVCoords,ColorIndex,&ColorIndexes[CurrentTriangle*COLORS_PER_TRIANGLE]);
			CurrentTriangle++;
		    }
		    break;
		}
		}
	    }
	}
	glBindVertexArray(VertexArrayObjects[TextureIndex]);

	GLuint VertexBuffer;
	glGenBuffers(1,&VertexBuffer);

	glBindBuffer(GL_ARRAY_BUFFER,VertexBuffer);
	glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*NumTriangles[TextureIndex]*FLOATS_PER_TRIANGLE,PositionAndTexCoord,GL_STATIC_DRAW);
	glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*FLOATS_PER_TRIANGLE/3,0);
	glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*FLOATS_PER_TRIANGLE/3,(GLvoid*)(sizeof(GLfloat)*3));

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	GLuint ColorBuffer;
	glGenBuffers(1,&ColorBuffer);
	glBindBuffer(GL_ARRAY_BUFFER,ColorBuffer);
	glBufferData(GL_ARRAY_BUFFER,sizeof(int16_t)*NumTriangles[TextureIndex]*COLORS_PER_TRIANGLE,ColorIndexes,GL_STATIC_DRAW);
	glVertexAttribPointer(2,1,GL_SHORT,GL_FALSE,0,0);
	glEnableVertexAttribArray(2);

	glBindVertexArray(0);
	glDeleteBuffers(1,&VertexBuffer);
	glDeleteBuffers(1,&ColorBuffer);
    }

    Children = new Unit3DObject *[NumChildren];
    for(int i=0;i<NumChildren;i++)
    {
	Children[i]=new Unit3DObject(buffer,ChildOffset);
	ChildOffset=*(int32_t *)&buffer[ChildOffset+OffsetToSibling];
    }

}

void Unit3DObject::Render(Matrix Model,GLuint ModelViewLoc,Matrix ParentTrans)
{
    Matrix NewTrans=LocationMatrix*ParentTrans;
    (Model*NewTrans).Upload(ModelViewLoc);
    for(int TextureIndex=0;TextureIndex<NumTextures;TextureIndex++)
    {
	glBindVertexArray(VertexArrayObjects[TextureIndex]);
	glDrawArrays(GL_TRIANGLES,0,NumTriangles[TextureIndex]*3);
    }
    for(int ChildIndex=0;ChildIndex<NumChildren;ChildIndex++)
    {
	Children[ChildIndex]->Render(Model,ModelViewLoc,NewTrans);
    }
}
<|endoftext|>


<commit_before>#ifndef OPENFLOW_METER_H
#define OPENFLOW_METER_H

#include <stddef.h>
#include "openflow-13.h"
#include <list>
#include <vector>

namespace fluid_msg {

namespace of13 {

class MeterBand {
protected:
    uint16_t type_;
    uint16_t len_;
    uint32_t rate_;
    uint32_t burst_size_;
public:
    MeterBand();
    MeterBand(uint16_t type, uint32_t rate, uint32_t burst_size);
    virtual ~MeterBand() {
    }
    virtual bool equals(const MeterBand & other);
    virtual MeterBand* clone() {
        return new MeterBand(*this);
    }
    virtual size_t pack(uint8_t* buffer);
    virtual of_error unpack(uint8_t* buffer);
    uint16_t type() {
        return this->type_;
    }
    uint16_t len() {
        return this->len_;
    }
    uint32_t rate() {
        return this->rate_;
    }
    uint32_t burst_size() {
        return this->burst_size_;
    }
    void type(uint16_t type) {
        this->type_ = type;
    }
    void rate(uint32_t rate) {
        this->rate_ = rate;
    }
    void burst_size(uint32_t burst_size) {
        this->burst_size_ = burst_size;
    }
    static bool delete_all(MeterBand * band) {
        delete band;
        return true;
    }
    static MeterBand * make_meter_band(uint16_t type);
};

class MeterBandList {
private:
    uint16_t length_;
    std::list<MeterBand*> band_list_;
public:
    MeterBandList()
        : length_(0) {
    }
    MeterBandList(std::list<MeterBand*> band_list);
    MeterBandList(const MeterBandList &other);
    MeterBandList& operator=(MeterBandList other);
    ~MeterBandList();
    bool operator==(const MeterBandList &other) const;
    bool operator!=(const MeterBandList &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    std::vector<MeterBand*> meter_bands() const {
      return std::vector<MeterBand*>(band_list_.begin(), band_list_.end());
    }
    friend void swap(MeterBandList& first, MeterBandList& second);
    uint16_t length() {
        return this->length_;
    }
    void add_band(MeterBand *band);
    void length(uint16_t length) {
        this->length_ = length;
    }
};

class MeterBandDrop: public MeterBand {
public:
    MeterBandDrop();
    MeterBandDrop(uint32_t rate, uint32_t burst_size);
    ~MeterBandDrop() {
    }
    virtual MeterBandDrop* clone() {
        return new MeterBandDrop(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
};

class MeterBandDSCPRemark: public MeterBand {
private:
    uint8_t prec_level_;
public:
    MeterBandDSCPRemark();
    MeterBandDSCPRemark(uint32_t rate, uint32_t burst_size, uint8_t prec_level);
    ~MeterBandDSCPRemark() {
    }
    virtual bool equals(const MeterBand & other);
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    virtual MeterBandDSCPRemark* clone() {
        return new MeterBandDSCPRemark(*this);
    }
    uint8_t prec_level() {
        return this->prec_level_;
    }
    void prec_level(uint8_t prec_level) {
        this->prec_level_ = prec_level;
    }
};

class MeterBandExperimenter: public MeterBand {
protected:
    uint32_t experimenter_;
public:
    MeterBandExperimenter();
    MeterBandExperimenter(uint32_t rate, uint32_t burst_size,
        uint32_t experimenter);
    ~MeterBandExperimenter() {
    }
    virtual bool equals(const MeterBand & other);
    virtual MeterBandExperimenter* clone() {
        return new MeterBandExperimenter(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t experimenter() {
        return this->experimenter_;
    }
    void experimenter(uint32_t experimenter) {
        this->experimenter_ = experimenter;
    }
};

class MeterConfig {
private:
    uint16_t length_;
    uint16_t flags_;
    uint32_t meter_id_;
    MeterBandList bands_;
public:
    MeterConfig();
    MeterConfig(uint16_t flags, uint32_t meter_id);
    MeterConfig(uint16_t flags, uint32_t meter_id, MeterBandList bands);
    ~MeterConfig() {
    }
    bool operator==(const MeterConfig &other) const;
    bool operator!=(const MeterConfig &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint16_t length() {
        return this->length_;
    }
    uint16_t flags() {
        return this->flags_;
    }
    uint32_t meter_id() {
        return this->meter_id_;
    }
    MeterBandList bands() {
        return this->bands_;
    }
    void bands(MeterBandList bands);
    void add_band(MeterBand* band);
};

class MeterFeatures {
private:
    uint32_t max_meter_;
    uint32_t band_types_;
    uint32_t capabilities_;
    uint8_t max_bands_;
    uint8_t max_color_;
public:
    MeterFeatures();
    MeterFeatures(uint32_t max_meter, uint32_t band_types,
        uint32_t capabilities, uint8_t max_bands, uint8_t max_color);
    ~MeterFeatures() {
    }
    bool operator==(const MeterFeatures &other) const;
    bool operator!=(const MeterFeatures &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t max_meter() {
        return this->max_meter_;
    }
    uint32_t band_types() {
        return this->band_types_;
    }
    uint32_t capabilities() {
        return this->capabilities_;
    }
    uint8_t max_bands() {
        return this->max_bands_;
    }
    uint8_t max_color() {
        return this->max_color_;
    }
    void max_meter(uint32_t max_meter) {
        this->max_meter_ = max_meter;
    }
    void banc_types(uint32_t band_types) {
        this->band_types_ = band_types;
    }
    void capabilities(uint32_t capabilities) {
        this->capabilities_ = capabilities;
    }
    void max_bands(uint8_t max_bands) {
        this->max_bands_ = max_bands;
    }
    void max_color(uint8_t max_color) {
        this->max_color_ = max_color;
    }
};

class BandStats {
private:
    uint64_t packet_band_count_;
    uint64_t byte_band_count_;
public:
    BandStats();
    BandStats(uint64_t packet_band_count, uint64_t byte_band_count);
    ~BandStats() {
    }
    bool operator==(const BandStats &other) const;
    bool operator!=(const BandStats &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint64_t packet_band_count() {
        return this->packet_band_count_;
    }
    uint64_t byte_band_count() {
        return this->byte_band_count_;
    }
};

class MeterStats {
private:
    uint32_t meter_id_;
    uint16_t len_;
    uint32_t flow_count_;
    uint64_t packet_in_count_;
    uint64_t byte_in_count_;
    uint32_t duration_sec_;
    uint32_t duration_nsec_;
    std::vector<BandStats> band_stats_;

public:
    MeterStats();
    MeterStats(uint32_t meter_id, uint32_t flow_count, uint64_t packet_in_count,
        uint64_t byte_in_count, uint32_t duration_sec, uint32_t duration_nsec);
    MeterStats(uint32_t meter_id, uint32_t flow_count, uint64_t packet_in_count,
        uint64_t byte_in_count, uint32_t duration_sec, uint32_t duration_nsec,
        std::vector<BandStats> band_stats);
    ~MeterStats() {
    }
    bool operator==(const MeterStats &other) const;
    bool operator!=(const MeterStats &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t meter_id() {
        return this->meter_id_;
    }
    uint16_t len() {
        return this->len_;
    }
    uint64_t packet_in_count() {
        return this->packet_in_count_;
    }
    uint64_t byte_in_count() {
        return this->byte_in_count_;
    }
    uint32_t duration_sec() {
        return this->duration_sec_;
    }
    uint32_t duration_nsec() {
        return this->duration_nsec_;
    }
    std::vector<BandStats> band_stats() {
        return this->band_stats_;
    }
    void meter_id(uint32_t meter_id) {
        this->meter_id_ = meter_id;
    }
    void packet_in_count(uint64_t packet_in_count) {
        this->packet_in_count_ = packet_in_count;
    }
    void byte_in_count(uint64_t byte_in_count) {
        this->byte_in_count_ = byte_in_count;
    }
    void duration_sec(uint32_t duration_sec) {
        this->duration_sec_ = duration_sec;
    }
    void duration_nsec(uint64_t duration_nsec) {
        this->duration_nsec_ = duration_nsec;
    }
    void band_stats(std::vector<BandStats> band_stats);

    void add_band_stats(BandStats stats);
};

} //End of namespace of13

} //End of namespace fluid_msg
#endif
<commit_msg>Fix band_types spelling error<commit_after>#ifndef OPENFLOW_METER_H
#define OPENFLOW_METER_H

#include <stddef.h>
#include "openflow-13.h"
#include <list>
#include <vector>

namespace fluid_msg {

namespace of13 {

class MeterBand {
protected:
    uint16_t type_;
    uint16_t len_;
    uint32_t rate_;
    uint32_t burst_size_;
public:
    MeterBand();
    MeterBand(uint16_t type, uint32_t rate, uint32_t burst_size);
    virtual ~MeterBand() {
    }
    virtual bool equals(const MeterBand & other);
    virtual MeterBand* clone() {
        return new MeterBand(*this);
    }
    virtual size_t pack(uint8_t* buffer);
    virtual of_error unpack(uint8_t* buffer);
    uint16_t type() {
        return this->type_;
    }
    uint16_t len() {
        return this->len_;
    }
    uint32_t rate() {
        return this->rate_;
    }
    uint32_t burst_size() {
        return this->burst_size_;
    }
    void type(uint16_t type) {
        this->type_ = type;
    }
    void rate(uint32_t rate) {
        this->rate_ = rate;
    }
    void burst_size(uint32_t burst_size) {
        this->burst_size_ = burst_size;
    }
    static bool delete_all(MeterBand * band) {
        delete band;
        return true;
    }
    static MeterBand * make_meter_band(uint16_t type);
};

class MeterBandList {
private:
    uint16_t length_;
    std::list<MeterBand*> band_list_;
public:
    MeterBandList()
        : length_(0) {
    }
    MeterBandList(std::list<MeterBand*> band_list);
    MeterBandList(const MeterBandList &other);
    MeterBandList& operator=(MeterBandList other);
    ~MeterBandList();
    bool operator==(const MeterBandList &other) const;
    bool operator!=(const MeterBandList &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    std::vector<MeterBand*> meter_bands() const {
      return std::vector<MeterBand*>(band_list_.begin(), band_list_.end());
    }
    friend void swap(MeterBandList& first, MeterBandList& second);
    uint16_t length() {
        return this->length_;
    }
    void add_band(MeterBand *band);
    void length(uint16_t length) {
        this->length_ = length;
    }
};

class MeterBandDrop: public MeterBand {
public:
    MeterBandDrop();
    MeterBandDrop(uint32_t rate, uint32_t burst_size);
    ~MeterBandDrop() {
    }
    virtual MeterBandDrop* clone() {
        return new MeterBandDrop(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
};

class MeterBandDSCPRemark: public MeterBand {
private:
    uint8_t prec_level_;
public:
    MeterBandDSCPRemark();
    MeterBandDSCPRemark(uint32_t rate, uint32_t burst_size, uint8_t prec_level);
    ~MeterBandDSCPRemark() {
    }
    virtual bool equals(const MeterBand & other);
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    virtual MeterBandDSCPRemark* clone() {
        return new MeterBandDSCPRemark(*this);
    }
    uint8_t prec_level() {
        return this->prec_level_;
    }
    void prec_level(uint8_t prec_level) {
        this->prec_level_ = prec_level;
    }
};

class MeterBandExperimenter: public MeterBand {
protected:
    uint32_t experimenter_;
public:
    MeterBandExperimenter();
    MeterBandExperimenter(uint32_t rate, uint32_t burst_size,
        uint32_t experimenter);
    ~MeterBandExperimenter() {
    }
    virtual bool equals(const MeterBand & other);
    virtual MeterBandExperimenter* clone() {
        return new MeterBandExperimenter(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t experimenter() {
        return this->experimenter_;
    }
    void experimenter(uint32_t experimenter) {
        this->experimenter_ = experimenter;
    }
};

class MeterConfig {
private:
    uint16_t length_;
    uint16_t flags_;
    uint32_t meter_id_;
    MeterBandList bands_;
public:
    MeterConfig();
    MeterConfig(uint16_t flags, uint32_t meter_id);
    MeterConfig(uint16_t flags, uint32_t meter_id, MeterBandList bands);
    ~MeterConfig() {
    }
    bool operator==(const MeterConfig &other) const;
    bool operator!=(const MeterConfig &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint16_t length() {
        return this->length_;
    }
    uint16_t flags() {
        return this->flags_;
    }
    uint32_t meter_id() {
        return this->meter_id_;
    }
    MeterBandList bands() {
        return this->bands_;
    }
    void bands(MeterBandList bands);
    void add_band(MeterBand* band);
};

class MeterFeatures {
private:
    uint32_t max_meter_;
    uint32_t band_types_;
    uint32_t capabilities_;
    uint8_t max_bands_;
    uint8_t max_color_;
public:
    MeterFeatures();
    MeterFeatures(uint32_t max_meter, uint32_t band_types,
        uint32_t capabilities, uint8_t max_bands, uint8_t max_color);
    ~MeterFeatures() {
    }
    bool operator==(const MeterFeatures &other) const;
    bool operator!=(const MeterFeatures &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t max_meter() {
        return this->max_meter_;
    }
    uint32_t band_types() {
        return this->band_types_;
    }
    uint32_t capabilities() {
        return this->capabilities_;
    }
    uint8_t max_bands() {
        return this->max_bands_;
    }
    uint8_t max_color() {
        return this->max_color_;
    }
    void max_meter(uint32_t max_meter) {
        this->max_meter_ = max_meter;
    }
    void band_types(uint32_t band_types) {
        this->band_types_ = band_types;
    }
    void capabilities(uint32_t capabilities) {
        this->capabilities_ = capabilities;
    }
    void max_bands(uint8_t max_bands) {
        this->max_bands_ = max_bands;
    }
    void max_color(uint8_t max_color) {
        this->max_color_ = max_color;
    }
};

class BandStats {
private:
    uint64_t packet_band_count_;
    uint64_t byte_band_count_;
public:
    BandStats();
    BandStats(uint64_t packet_band_count, uint64_t byte_band_count);
    ~BandStats() {
    }
    bool operator==(const BandStats &other) const;
    bool operator!=(const BandStats &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint64_t packet_band_count() {
        return this->packet_band_count_;
    }
    uint64_t byte_band_count() {
        return this->byte_band_count_;
    }
};

class MeterStats {
private:
    uint32_t meter_id_;
    uint16_t len_;
    uint32_t flow_count_;
    uint64_t packet_in_count_;
    uint64_t byte_in_count_;
    uint32_t duration_sec_;
    uint32_t duration_nsec_;
    std::vector<BandStats> band_stats_;

public:
    MeterStats();
    MeterStats(uint32_t meter_id, uint32_t flow_count, uint64_t packet_in_count,
        uint64_t byte_in_count, uint32_t duration_sec, uint32_t duration_nsec);
    MeterStats(uint32_t meter_id, uint32_t flow_count, uint64_t packet_in_count,
        uint64_t byte_in_count, uint32_t duration_sec, uint32_t duration_nsec,
        std::vector<BandStats> band_stats);
    ~MeterStats() {
    }
    bool operator==(const MeterStats &other) const;
    bool operator!=(const MeterStats &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t meter_id() {
        return this->meter_id_;
    }
    uint16_t len() {
        return this->len_;
    }
    uint64_t packet_in_count() {
        return this->packet_in_count_;
    }
    uint64_t byte_in_count() {
        return this->byte_in_count_;
    }
    uint32_t duration_sec() {
        return this->duration_sec_;
    }
    uint32_t duration_nsec() {
        return this->duration_nsec_;
    }
    std::vector<BandStats> band_stats() {
        return this->band_stats_;
    }
    void meter_id(uint32_t meter_id) {
        this->meter_id_ = meter_id;
    }
    void packet_in_count(uint64_t packet_in_count) {
        this->packet_in_count_ = packet_in_count;
    }
    void byte_in_count(uint64_t byte_in_count) {
        this->byte_in_count_ = byte_in_count;
    }
    void duration_sec(uint32_t duration_sec) {
        this->duration_sec_ = duration_sec;
    }
    void duration_nsec(uint64_t duration_nsec) {
        this->duration_nsec_ = duration_nsec;
    }
    void band_stats(std::vector<BandStats> band_stats);

    void add_band_stats(BandStats stats);
};

} //End of namespace of13

} //End of namespace fluid_msg
#endif
<|endoftext|>


<commit_before>// Copyright (c) Facebook, Inc. and its affiliates.

#include <torch/extension.h>
#include "ROIAlignRotated/ROIAlignRotated.h"
#include "box_iou_rotated/box_iou_rotated.h"
#include "cocoeval/cocoeval.h"
#include "deformable/deform_conv.h"
#include "nms_rotated/nms_rotated.h"

namespace detectron2 {

#if defined(WITH_CUDA) || defined(WITH_HIP)
extern int get_cudart_version();
#endif

std::string get_cuda_version() {
#if defined(WITH_CUDA) || defined(WITH_HIP)
  std::ostringstream oss;

#if defined(WITH_CUDA)
  oss << "CUDA ";
#else
  oss << "HIP ";
#endif

  // copied from
  // https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/cuda/detail/CUDAHooks.cpp#L231
  auto printCudaStyleVersion = [&](int v) {
    oss << (v / 1000) << "." << (v / 10 % 100);
    if (v % 10 != 0) {
      oss << "." << (v % 10);
    }
  };
  printCudaStyleVersion(get_cudart_version());
  return oss.str();
#else // neither CUDA nor HIP
  return std::string("not available");
#endif
}

bool has_cuda() {
#if defined(WITH_CUDA)
  return true;
#else
  return false;
#endif
}

// similar to
// https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/Version.cpp
std::string get_compiler_version() {
  std::ostringstream ss;
#if defined(__GNUC__)
#ifndef __clang__

#if ((__GNUC__ <= 4) && (__GNUC_MINOR__ <= 8))
#error "GCC >= 4.9 is required!"
#endif

  { ss << "GCC " << __GNUC__ << "." << __GNUC_MINOR__; }
#endif
#endif

#if defined(__clang_major__)
  {
    ss << "clang " << __clang_major__ << "." << __clang_minor__ << "."
       << __clang_patchlevel__;
  }
#endif

#if defined(_MSC_VER)
  { ss << "MSVC " << _MSC_FULL_VER; }
#endif
  return ss.str();
}

PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
  m.def("get_compiler_version", &get_compiler_version, "get_compiler_version");
  m.def("get_cuda_version", &get_cuda_version, "get_cuda_version");
  m.def("has_cuda", &has_cuda, "has_cuda");

  m.def("deform_conv_forward", &deform_conv_forward, "deform_conv_forward");
  m.def(
      "deform_conv_backward_input",
      &deform_conv_backward_input,
      "deform_conv_backward_input");
  m.def(
      "deform_conv_backward_filter",
      &deform_conv_backward_filter,
      "deform_conv_backward_filter");
  m.def(
      "modulated_deform_conv_forward",
      &modulated_deform_conv_forward,
      "modulated_deform_conv_forward");
  m.def(
      "modulated_deform_conv_backward",
      &modulated_deform_conv_backward,
      "modulated_deform_conv_backward");

  m.def("COCOevalAccumulate", &COCOeval::Accumulate, "COCOeval::Accumulate");
  m.def(
      "COCOevalEvaluateImages",
      &COCOeval::EvaluateImages,
      "COCOeval::EvaluateImages");
  pybind11::class_<COCOeval::InstanceAnnotation>(m, "InstanceAnnotation")
      .def(pybind11::init<uint64_t, double, double, bool, bool>());
  pybind11::class_<COCOeval::ImageEvaluation>(m, "ImageEvaluation")
      .def(pybind11::init<>());
}

TORCH_LIBRARY(detectron2, m) {
  m.def("nms_rotated", &nms_rotated);
  m.def("box_iou_rotated", &box_iou_rotated);
  m.def("roi_align_rotated_forward", &ROIAlignRotated_forward);
  m.def("roi_align_rotated_backward", &ROIAlignRotated_backward);
}
} // namespace detectron2
<commit_msg>Daily `arc lint --take CLANGFORMAT`<commit_after>// Copyright (c) Facebook, Inc. and its affiliates.

#include <torch/extension.h>
#include "ROIAlignRotated/ROIAlignRotated.h"
#include "box_iou_rotated/box_iou_rotated.h"
#include "cocoeval/cocoeval.h"
#include "deformable/deform_conv.h"
#include "nms_rotated/nms_rotated.h"

namespace detectron2 {

#if defined(WITH_CUDA) || defined(WITH_HIP)
extern int get_cudart_version();
#endif

std::string get_cuda_version() {
#if defined(WITH_CUDA) || defined(WITH_HIP)
  std::ostringstream oss;

#if defined(WITH_CUDA)
  oss << "CUDA ";
#else
  oss << "HIP ";
#endif

  // copied from
  // https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/cuda/detail/CUDAHooks.cpp#L231
  auto printCudaStyleVersion = [&](int v) {
    oss << (v / 1000) << "." << (v / 10 % 100);
    if (v % 10 != 0) {
      oss << "." << (v % 10);
    }
  };
  printCudaStyleVersion(get_cudart_version());
  return oss.str();
#else // neither CUDA nor HIP
  return std::string("not available");
#endif
}

bool has_cuda() {
#if defined(WITH_CUDA)
  return true;
#else
  return false;
#endif
}

// similar to
// https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/Version.cpp
std::string get_compiler_version() {
  std::ostringstream ss;
#if defined(__GNUC__)
#ifndef __clang__

#if ((__GNUC__ <= 4) && (__GNUC_MINOR__ <= 8))
#error "GCC >= 4.9 is required!"
#endif

  { ss << "GCC " << __GNUC__ << "." << __GNUC_MINOR__; }
#endif
#endif

#if defined(__clang_major__)
  {
    ss << "clang " << __clang_major__ << "." << __clang_minor__ << "."
       << __clang_patchlevel__;
  }
#endif

#if defined(_MSC_VER)
  { ss << "MSVC " << _MSC_FULL_VER; }
#endif
  return ss.str();
}

PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
  m.def("get_compiler_version", &get_compiler_version, "get_compiler_version");
  m.def("get_cuda_version", &get_cuda_version, "get_cuda_version");
  m.def("has_cuda", &has_cuda, "has_cuda");

  m.def("deform_conv_forward", &deform_conv_forward, "deform_conv_forward");
  m.def(
      "deform_conv_backward_input",
      &deform_conv_backward_input,
      "deform_conv_backward_input");
  m.def(
      "deform_conv_backward_filter",
      &deform_conv_backward_filter,
      "deform_conv_backward_filter");
  m.def(
      "modulated_deform_conv_forward",
      &modulated_deform_conv_forward,
      "modulated_deform_conv_forward");
  m.def(
      "modulated_deform_conv_backward",
      &modulated_deform_conv_backward,
      "modulated_deform_conv_backward");

  m.def("COCOevalAccumulate", &COCOeval::Accumulate, "COCOeval::Accumulate");
  m.def(
      "COCOevalEvaluateImages",
      &COCOeval::EvaluateImages,
      "COCOeval::EvaluateImages");
  pybind11::class_<COCOeval::InstanceAnnotation>(m, "InstanceAnnotation")
      .def(pybind11::init<uint64_t, double, double, bool, bool>());
  pybind11::class_<COCOeval::ImageEvaluation>(m, "ImageEvaluation")
      .def(pybind11::init<>());
}

TORCH_LIBRARY(detectron2, m) {
  m.def("nms_rotated", &nms_rotated);
  m.def("box_iou_rotated", &box_iou_rotated);
  m.def("roi_align_rotated_forward", &ROIAlignRotated_forward);
  m.def("roi_align_rotated_backward", &ROIAlignRotated_backward);
}
} // namespace detectron2
<|endoftext|>


<commit_before><commit_msg>Gui: fix property link editor for PropertyLinkSubList<commit_after><|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) 2014 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
# include <algorithm>
# include <sstream>
# include <QTreeWidgetItem>
# include <QMessageBox>
#endif

#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/GeoFeature.h>

#include "BitmapFactory.h"
#include "DlgPropertyLink.h"
#include "Application.h"
#include "ViewProviderDocumentObject.h"
#include "ui_DlgPropertyLink.h"

using namespace Gui::Dialog;

/* TRANSLATOR Gui::Dialog::DlgPropertyLink */

DlgPropertyLink::DlgPropertyLink(const QStringList& list, QWidget* parent, Qt::WindowFlags fl, bool xlink)
  : QDialog(parent, fl), link(list), ui(new Ui_DlgPropertyLink)
{
#ifdef FC_DEBUG
    assert(list.size() >= 4);
#endif

    // populate inList to filter out any objects that contains the owner object
    // of the editing link property
    auto doc = App::GetApplication().getDocument(qPrintable(link[0]));
    if(doc) {
        auto obj = doc->getObject(qPrintable(link[3]));
        if(obj && obj->getNameInDocument()) {
            inList = obj->getInListEx(true);
            inList.insert(obj);
        }
    }

    ui->setupUi(this);
    ui->typeTree->hide();

    if(!xlink)
        ui->comboBox->hide();
    else {
        std::string linkDoc = qPrintable(link[0]);
        for(auto doc : App::GetApplication().getDocuments()) {
            QString name(QString::fromUtf8(doc->Label.getValue()));
            ui->comboBox->addItem(name,QVariant(QString::fromLatin1(doc->getName())));
            if(linkDoc == doc->getName())
                ui->comboBox->setCurrentIndex(ui->comboBox->count()-1);
        }
    }

    Base::Type baseType;

    App::Document *linkedDoc = doc;
    if (link.size()>FC_XLINK_VALUE_INDEX)
        linkedDoc = App::GetApplication().getDocument(qPrintable(link[FC_XLINK_VALUE_INDEX]));
    if(linkedDoc) {
        QString objName = link[1]; // linked object name
        auto obj = linkedDoc->getObject((const char*)objName.toLatin1());
        if (obj && inList.find(obj)==inList.end()) {
            Base::Type objType = obj->getTypeId();
            // get only geometric types
            if (objType.isDerivedFrom(App::GeoFeature::getClassTypeId()))
                baseType = App::GeoFeature::getClassTypeId();
            else
                baseType = App::DocumentObject::getClassTypeId();

            // get the direct base class of App::DocumentObject which 'obj' is derived from
            while (!objType.isBad()) {
                std::string name = objType.getName();
                Base::Type parType = objType.getParent();
                if (parType == baseType) {
                    baseType = objType;
                    break;
                }
                objType = parType;
            }
        }
    }
    if(!baseType.isBad()) {
        types.insert(baseType.getName());
        ui->checkObjectType->setChecked(true);
    }else
        findObjects();

    connect(ui->treeWidget, SIGNAL(itemExpanded(QTreeWidgetItem*)),
            this, SLOT(onItemExpanded(QTreeWidgetItem*)));
}

/**
 *  Destroys the object and frees any allocated resources
 */
DlgPropertyLink::~DlgPropertyLink()
{
    // no need to delete child widgets, Qt does it all for us
    delete ui;
}

void DlgPropertyLink::setSelectionMode(QAbstractItemView::SelectionMode mode)
{
    ui->treeWidget->setSelectionMode(mode);
    findObjects();
}

void DlgPropertyLink::accept()
{
    if (ui->treeWidget->selectionMode() == QAbstractItemView::SingleSelection) {
        QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
        if (items.isEmpty()) {
            QMessageBox::warning(this, tr("No selection"), tr("Please select an object from the list"));
            return;
        }
    }

    QDialog::accept();
}

static QStringList getLinkFromItem(const QStringList &link, QTreeWidgetItem *selItem) {
    QStringList list = link;
    if(link.size()>FC_XLINK_VALUE_INDEX) {
        QString subname;
        auto parent = selItem;
        for(auto item=parent;;item=parent) {
            parent = item->parent();
            if(!parent) {
                list[1] = item->data(0,Qt::UserRole).toString();
                break;
            }
            subname = QString::fromLatin1("%1.%2").
                arg(item->data(0,Qt::UserRole).toString()).arg(subname);
        }
        list[FC_XLINK_VALUE_INDEX] = subname;
        if(subname.size())
            list[2] = QString::fromLatin1("%1 (%2.%3)").
                arg(selItem->text(0)).arg(list[1]).arg(subname);
        else
            list[2] = selItem->text(0);
        QString docName(selItem->data(0, Qt::UserRole+1).toString());
        if(list.size()>FC_XLINK_VALUE_INDEX+1)
            list[FC_XLINK_VALUE_INDEX+1] = docName;
        else
            list << docName;
    }else{
        list[1] = selItem->data(0,Qt::UserRole).toString();
        list[2] = selItem->text(0);
        if (list[1].isEmpty())
            list[2] = QString::fromUtf8("");
    }
    return list;
}

QStringList DlgPropertyLink::propertyLink() const
{
    auto items = ui->treeWidget->selectedItems();
    if (items.isEmpty()) {
        return link;
    }
    return getLinkFromItem(link,items[0]);
}

QVariantList DlgPropertyLink::propertyLinkList() const
{
    QVariantList varList;
    QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
    for (QList<QTreeWidgetItem*>::iterator it = items.begin(); it != items.end(); ++it)
        varList << getLinkFromItem(link,*it);
    return varList;
}

void DlgPropertyLink::findObjects()
{
    bool filterType = ui->checkObjectType->isChecked();
    ui->treeWidget->clear();

    QString docName = link[0]; // document name of the owner object of this editing property

    bool isSingleSelection = (ui->treeWidget->selectionMode() == QAbstractItemView::SingleSelection);
    App::Document* doc = App::GetApplication().getDocument((const char*)docName.toLatin1());
    if (doc) {

        // build list of objects names already in property so we can mark them as selected later on
        std::set<std::string> selectedNames;

        // Add a "None" entry on top
        if (isSingleSelection) {
            auto* item = new QTreeWidgetItem(ui->treeWidget);
            item->setText(0,tr("None (Remove link)"));
            QByteArray ba("");
            item->setData(0,Qt::UserRole, ba);
        }else {
            QString ownerName = link[3];
            QString proName = link[4];
            auto owner = doc->getObject(ownerName.toLatin1());
            if(owner) {
                App::Property* prop = owner->getPropertyByName((const char*)proName.toLatin1());
                // gather names of objects currently in property
                if (prop && prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
                    const App::PropertyLinkList* propll = static_cast<const App::PropertyLinkList*>(prop);
                    std::vector<App::DocumentObject*> links = propll->getValues();
                    for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
                        selectedNames.insert((*it)->getNameInDocument());
                    }
                }
            }
        }

        Base::PyGILStateLocker lock;
        std::map<std::string,QIcon> typeInfos;

        QTreeWidgetItem *selected = 0;
        for(auto obj : doc->getObjects()) {
            auto it = types.end();
            auto prop = Base::freecad_dynamic_cast<App::PropertyPythonObject>(
                    obj->getPropertyByName("Proxy"));
            bool pass = false;
            if(prop && !prop->getValue().isNone()) {
                std::string typeName = prop->getValue().type().as_string();
                if(refreshTypes) {
                    QIcon &icon = typeInfos[typeName];
                    if(icon.isNull()) {
                        auto vp = Application::Instance->getViewProvider(obj);
                        if(vp)
                            icon = vp->getIcon();
                    }
                }
                if(filterType)
                    pass = types.count(typeName);
            }
            if(refreshTypes) {
                auto type = obj->getTypeId();
                QIcon &icon = typeInfos[type.getName()];
                if(!prop && icon.isNull()) {
                    auto vp = Application::Instance->getViewProvider(obj);
                    if(vp)
                        icon = vp->getIcon();
                }
                for(type = type.getParent();!type.isBad();type=type.getParent())
                    typeInfos.emplace(type.getName(),QIcon());
            }
            if(filterType && !pass && types.size()) {
                for(auto type = obj->getTypeId();!type.isBad();type=type.getParent()) {
                    it = types.find(type.getName());
                    if(it!=types.end())
                        break;
                }
                if(it == types.end())
                    continue;
            }

            auto item = createItem(obj,0);
            if(item && selectedNames.count(obj->getNameInDocument())) {
                if(!selected)
                    selected = item;
                item->setSelected(true);
            }
        }
        if(selected)
            ui->treeWidget->scrollToItem(selected);

        if(refreshTypes) {
            refreshTypes = false;
            ui->typeTree->blockSignals(true);
            ui->typeTree->clear();
            QTreeWidgetItem *selected = 0;
            QIcon icon = BitmapFactory().pixmap("px");
            for(auto &v : typeInfos) {
                auto item = new QTreeWidgetItem(ui->typeTree);
                item->setText(0,QString::fromLatin1(v.first.c_str()));
                item->setIcon(0,v.second.isNull()?icon:v.second);
                if(types.count(v.first)) {
                    item->setSelected(true);
                    if(!selected)
                        selected = item;
                }
            }
            if(selected)
                ui->typeTree->scrollToItem(selected);
            ui->typeTree->blockSignals(false);
            if(types.size() && !selected) {
                types.clear();
                findObjects();
            }
        }
    }
}

QTreeWidgetItem *DlgPropertyLink::createItem(App::DocumentObject *obj, QTreeWidgetItem *parent) {
    if(!obj || !obj->getNameInDocument())
        return 0;

    if(inList.find(obj)!=inList.end())
        return 0;

    auto vp = Gui::Application::Instance->getViewProvider(obj);
    if(!vp)
        return 0;
    QString searchText = ui->searchBox->text();
    if (!searchText.isEmpty()) {
        QString label = QString::fromUtf8((obj)->Label.getValue());
        if (!label.contains(searchText,Qt::CaseInsensitive))
            return 0;
    }
    QTreeWidgetItem* item;
    if(parent)
        item = new QTreeWidgetItem(parent);
    else
        item = new QTreeWidgetItem(ui->treeWidget);
    item->setIcon(0, vp->getIcon());
    item->setText(0, QString::fromUtf8((obj)->Label.getValue()));
    item->setData(0, Qt::UserRole, QByteArray(obj->getNameInDocument()));
    item->setData(0, Qt::UserRole+1, QByteArray(obj->getDocument()->getName()));
    if(link.size()>=5) {
        item->setChildIndicatorPolicy(obj->hasChildElement()||vp->getChildRoot()?
                QTreeWidgetItem::ShowIndicator:QTreeWidgetItem::DontShowIndicator);
    }
    return item;
}

void DlgPropertyLink::onItemExpanded(QTreeWidgetItem * item) {
    if(link.size()<5 || item->childCount())
        return;

    std::string name(qPrintable(item->data(0, Qt::UserRole).toString()));
    std::string docName(qPrintable(item->data(0, Qt::UserRole+1).toString()));
    auto doc = App::GetApplication().getDocument(docName.c_str());
    if(doc) {
        auto obj = doc->getObject(name.c_str());
        if(!obj) return;
        auto vp = Application::Instance->getViewProvider(obj);
        if(!vp) return;
        for(auto obj : vp->claimChildren())
            createItem(obj,item);
    }
}

void DlgPropertyLink::on_checkObjectType_toggled(bool on)
{
    ui->typeTree->setVisible(on);
    findObjects();
}

void DlgPropertyLink::on_typeTree_itemSelectionChanged() {
    types.clear();
    for(auto item : ui->typeTree->selectedItems())
        types.insert(item->text(0).toLatin1().constData());
    findObjects();
}

void DlgPropertyLink::on_searchBox_textChanged(const QString& /*search*/)
{
    findObjects();
}

void DlgPropertyLink::on_comboBox_currentIndexChanged(int index)
{
    link[0] = ui->comboBox->itemData(index).toString();
    refreshTypes = true;
    findObjects();
}

#include "moc_DlgPropertyLink.cpp"
<commit_msg>Gui: fix crash on editing PropertyLinkList<commit_after>/***************************************************************************
 *   Copyright (c) 2014 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
# include <algorithm>
# include <sstream>
# include <QTreeWidgetItem>
# include <QMessageBox>
#endif

#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/GeoFeature.h>

#include "BitmapFactory.h"
#include "DlgPropertyLink.h"
#include "Application.h"
#include "ViewProviderDocumentObject.h"
#include "ui_DlgPropertyLink.h"

using namespace Gui::Dialog;

/* TRANSLATOR Gui::Dialog::DlgPropertyLink */

DlgPropertyLink::DlgPropertyLink(const QStringList& list, QWidget* parent, Qt::WindowFlags fl, bool xlink)
  : QDialog(parent, fl), link(list), ui(new Ui_DlgPropertyLink)
{
#ifdef FC_DEBUG
    assert(list.size() >= 4);
#endif

    // populate inList to filter out any objects that contains the owner object
    // of the editing link property
    auto doc = App::GetApplication().getDocument(qPrintable(link[0]));
    if(doc) {
        auto obj = doc->getObject(qPrintable(link[3]));
        if(obj && obj->getNameInDocument()) {
            inList = obj->getInListEx(true);
            inList.insert(obj);
        }
    }

    ui->setupUi(this);
    ui->typeTree->hide();

    if(!xlink)
        ui->comboBox->hide();
    else {
        std::string linkDoc = qPrintable(link[0]);
        for(auto doc : App::GetApplication().getDocuments()) {
            QString name(QString::fromUtf8(doc->Label.getValue()));
            ui->comboBox->addItem(name,QVariant(QString::fromLatin1(doc->getName())));
            if(linkDoc == doc->getName())
                ui->comboBox->setCurrentIndex(ui->comboBox->count()-1);
        }
    }

    Base::Type baseType;

    App::Document *linkedDoc = doc;
    if (link.size()>FC_XLINK_VALUE_INDEX)
        linkedDoc = App::GetApplication().getDocument(qPrintable(link[FC_XLINK_VALUE_INDEX]));
    if(linkedDoc) {
        QString objName = link[1]; // linked object name
        auto obj = linkedDoc->getObject((const char*)objName.toLatin1());
        if (obj && inList.find(obj)==inList.end()) {
            Base::Type objType = obj->getTypeId();
            // get only geometric types
            if (objType.isDerivedFrom(App::GeoFeature::getClassTypeId()))
                baseType = App::GeoFeature::getClassTypeId();
            else
                baseType = App::DocumentObject::getClassTypeId();

            // get the direct base class of App::DocumentObject which 'obj' is derived from
            while (!objType.isBad()) {
                std::string name = objType.getName();
                Base::Type parType = objType.getParent();
                if (parType == baseType) {
                    baseType = objType;
                    break;
                }
                objType = parType;
            }
        }
    }
    if(!baseType.isBad()) {
        types.insert(baseType.getName());
        ui->checkObjectType->setChecked(true);
    }else
        findObjects();

    connect(ui->treeWidget, SIGNAL(itemExpanded(QTreeWidgetItem*)),
            this, SLOT(onItemExpanded(QTreeWidgetItem*)));
}

/**
 *  Destroys the object and frees any allocated resources
 */
DlgPropertyLink::~DlgPropertyLink()
{
    // no need to delete child widgets, Qt does it all for us
    delete ui;
}

void DlgPropertyLink::setSelectionMode(QAbstractItemView::SelectionMode mode)
{
    ui->treeWidget->setSelectionMode(mode);
    findObjects();
}

void DlgPropertyLink::accept()
{
    QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
    if (items.isEmpty()) {
        QMessageBox::warning(this, tr("No selection"), tr("Please select an object from the list"));
        return;
    }

    QDialog::accept();
}

static QStringList getLinkFromItem(const QStringList &link, QTreeWidgetItem *selItem) {
    QStringList list = link;
    if(link.size()>FC_XLINK_VALUE_INDEX) {
        QString subname;
        auto parent = selItem;
        for(auto item=parent;;item=parent) {
            parent = item->parent();
            if(!parent) {
                list[1] = item->data(0,Qt::UserRole).toString();
                break;
            }
            subname = QString::fromLatin1("%1.%2").
                arg(item->data(0,Qt::UserRole).toString()).arg(subname);
        }
        list[FC_XLINK_VALUE_INDEX] = subname;
        if(subname.size())
            list[2] = QString::fromLatin1("%1 (%2.%3)").
                arg(selItem->text(0)).arg(list[1]).arg(subname);
        else
            list[2] = selItem->text(0);
        QString docName(selItem->data(0, Qt::UserRole+1).toString());
        if(list.size()>FC_XLINK_VALUE_INDEX+1)
            list[FC_XLINK_VALUE_INDEX+1] = docName;
        else
            list << docName;
    }else{
        list[1] = selItem->data(0,Qt::UserRole).toString();
        list[2] = selItem->text(0);
        if (list[1].isEmpty())
            list[2] = QString::fromUtf8("");
    }
    return list;
}

QStringList DlgPropertyLink::propertyLink() const
{
    auto items = ui->treeWidget->selectedItems();
    if (items.isEmpty()) {
        return link;
    }
    return getLinkFromItem(link,items[0]);
}

QVariantList DlgPropertyLink::propertyLinkList() const
{
    QVariantList varList;
    QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
    if (items.isEmpty()) {
        QStringList l = link;
        l[1] = QString();
        l[2] = QString();
        varList << l;
    } else {
        for (QList<QTreeWidgetItem*>::iterator it = items.begin(); it != items.end(); ++it)
            varList << getLinkFromItem(link,*it);
    }
    return varList;
}

void DlgPropertyLink::findObjects()
{
    bool filterType = ui->checkObjectType->isChecked();
    ui->treeWidget->clear();

    QString docName = link[0]; // document name of the owner object of this editing property

    bool isSingleSelection = (ui->treeWidget->selectionMode() == QAbstractItemView::SingleSelection);
    App::Document* doc = App::GetApplication().getDocument((const char*)docName.toLatin1());
    if (doc) {

        // build list of objects names already in property so we can mark them as selected later on
        std::set<std::string> selectedNames;

        // Add a "None" entry on top
        auto* item = new QTreeWidgetItem(ui->treeWidget);
        item->setText(0,tr("None (Remove link)"));
        QByteArray ba("");
        item->setData(0,Qt::UserRole, ba);

        if (!isSingleSelection) {

            QString ownerName = link[3];
            QString proName = link[4];
            auto owner = doc->getObject(ownerName.toLatin1());
            if(owner) {
                App::Property* prop = owner->getPropertyByName((const char*)proName.toLatin1());
                // gather names of objects currently in property
                if (prop && prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
                    const App::PropertyLinkList* propll = static_cast<const App::PropertyLinkList*>(prop);
                    std::vector<App::DocumentObject*> links = propll->getValues();
                    for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
                        selectedNames.insert((*it)->getNameInDocument());
                    }
                }
            }
        }

        Base::PyGILStateLocker lock;
        std::map<std::string,QIcon> typeInfos;

        QTreeWidgetItem *selected = 0;
        for(auto obj : doc->getObjects()) {
            auto it = types.end();
            auto prop = Base::freecad_dynamic_cast<App::PropertyPythonObject>(
                    obj->getPropertyByName("Proxy"));
            bool pass = false;
            if(prop && !prop->getValue().isNone()) {
                std::string typeName = prop->getValue().type().as_string();
                if(refreshTypes) {
                    QIcon &icon = typeInfos[typeName];
                    if(icon.isNull()) {
                        auto vp = Application::Instance->getViewProvider(obj);
                        if(vp)
                            icon = vp->getIcon();
                    }
                }
                if(filterType)
                    pass = types.count(typeName);
            }
            if(refreshTypes) {
                auto type = obj->getTypeId();
                QIcon &icon = typeInfos[type.getName()];
                if(!prop && icon.isNull()) {
                    auto vp = Application::Instance->getViewProvider(obj);
                    if(vp)
                        icon = vp->getIcon();
                }
                for(type = type.getParent();!type.isBad();type=type.getParent())
                    typeInfos.emplace(type.getName(),QIcon());
            }
            if(filterType && !pass && types.size()) {
                for(auto type = obj->getTypeId();!type.isBad();type=type.getParent()) {
                    it = types.find(type.getName());
                    if(it!=types.end())
                        break;
                }
                if(it == types.end())
                    continue;
            }

            auto item = createItem(obj,0);
            if(item && selectedNames.count(obj->getNameInDocument())) {
                if(!selected)
                    selected = item;
                item->setSelected(true);
            }
        }
        if(selected)
            ui->treeWidget->scrollToItem(selected);

        if(refreshTypes) {
            refreshTypes = false;
            ui->typeTree->blockSignals(true);
            ui->typeTree->clear();
            QTreeWidgetItem *selected = 0;
            QIcon icon = BitmapFactory().pixmap("px");
            for(auto &v : typeInfos) {
                auto item = new QTreeWidgetItem(ui->typeTree);
                item->setText(0,QString::fromLatin1(v.first.c_str()));
                item->setIcon(0,v.second.isNull()?icon:v.second);
                if(types.count(v.first)) {
                    item->setSelected(true);
                    if(!selected)
                        selected = item;
                }
            }
            if(selected)
                ui->typeTree->scrollToItem(selected);
            ui->typeTree->blockSignals(false);
            if(types.size() && !selected) {
                types.clear();
                findObjects();
            }
        }
    }
}

QTreeWidgetItem *DlgPropertyLink::createItem(App::DocumentObject *obj, QTreeWidgetItem *parent) {
    if(!obj || !obj->getNameInDocument())
        return 0;

    if(inList.find(obj)!=inList.end())
        return 0;

    auto vp = Gui::Application::Instance->getViewProvider(obj);
    if(!vp)
        return 0;
    QString searchText = ui->searchBox->text();
    if (!searchText.isEmpty()) {
        QString label = QString::fromUtf8((obj)->Label.getValue());
        if (!label.contains(searchText,Qt::CaseInsensitive))
            return 0;
    }
    QTreeWidgetItem* item;
    if(parent)
        item = new QTreeWidgetItem(parent);
    else
        item = new QTreeWidgetItem(ui->treeWidget);
    item->setIcon(0, vp->getIcon());
    item->setText(0, QString::fromUtf8((obj)->Label.getValue()));
    item->setData(0, Qt::UserRole, QByteArray(obj->getNameInDocument()));
    item->setData(0, Qt::UserRole+1, QByteArray(obj->getDocument()->getName()));
    if(link.size()>=5) {
        item->setChildIndicatorPolicy(obj->hasChildElement()||vp->getChildRoot()?
                QTreeWidgetItem::ShowIndicator:QTreeWidgetItem::DontShowIndicator);
    }
    return item;
}

void DlgPropertyLink::onItemExpanded(QTreeWidgetItem * item) {
    if(link.size()<5 || item->childCount())
        return;

    std::string name(qPrintable(item->data(0, Qt::UserRole).toString()));
    std::string docName(qPrintable(item->data(0, Qt::UserRole+1).toString()));
    auto doc = App::GetApplication().getDocument(docName.c_str());
    if(doc) {
        auto obj = doc->getObject(name.c_str());
        if(!obj) return;
        auto vp = Application::Instance->getViewProvider(obj);
        if(!vp) return;
        for(auto obj : vp->claimChildren())
            createItem(obj,item);
    }
}

void DlgPropertyLink::on_checkObjectType_toggled(bool on)
{
    ui->typeTree->setVisible(on);
    findObjects();
}

void DlgPropertyLink::on_typeTree_itemSelectionChanged() {
    types.clear();
    for(auto item : ui->typeTree->selectedItems())
        types.insert(item->text(0).toLatin1().constData());
    findObjects();
}

void DlgPropertyLink::on_searchBox_textChanged(const QString& /*search*/)
{
    findObjects();
}

void DlgPropertyLink::on_comboBox_currentIndexChanged(int index)
{
    link[0] = ui->comboBox->itemData(index).toString();
    refreshTypes = true;
    findObjects();
}

#include "moc_DlgPropertyLink.cpp"
<|endoftext|>


<commit_before>#ifndef BUW_SDFLOADER_HPP
#define BUW_SDFLOADER_HPP

#include <string>
#include <scene.hpp>
#include <iostream>
#include <fstream>
#include <ifstream>

void loadScene(std::ifstream& file, Scene& scene) {
	std::cout << "funst endlich" << std::endl;
}

#endif<commit_msg>mannoooo<commit_after>#ifndef BUW_SDFLOADER_HPP
#define BUW_SDFLOADER_HPP

#include <string>
#include <scene.hpp>
#include <iostream>
#include <fstream>

void loadScene(std::ifstream& file, Scene& scene) {
	std::cout << "funst endlich" << std::endl;
}

#endif<|endoftext|>


<commit_before>#ifndef BUW_SDFLOADER_HPP
#define BUW_SDFLOADER_HPP

#include <string>
#include <scene.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <regex>

void sdf_splitString(std::string const& input, std::vector<std::string>& output) {
	std::istringstream tmp{input};
	do {
		std::string sub{""};
		tmp >> sub;
		output.push_back(sub);
	} while(tmp);
}

bool sdf_isMaterial(std::string const& input, Material*& material) {
	std::regex rgx_material{"define[\\s\\t]material[\\s\\t]\\S+[\\s\\t]([0-9][\\s\\t]){9}[0-9].*"};
	if(std::regex_match(input,rgx_material)) {
		std::vector<std::string> parsed;
		sdf_splitString(input,parsed);
		Color ka = {std::stof(parsed[3]),std::stof(parsed[4]),std::stof(parsed[5])};
		Color kd = {std::stof(parsed[6]),std::stof(parsed[7]),std::stof(parsed[8])};
		Color ks = {std::stof(parsed[9]),std::stof(parsed[10]),std::stof(parsed[11])};
		material = new Material{parsed[2],ka,kd,ks,std::stof(parsed[12])};
		return true;
	}
	return false;
}

bool sdf_isComment(std::string const& input) {
	std::regex rgx_comment{"^#.*"};
	if(std::regex_match(input, rgx_comment)) {
		return true;
	}
	return false;
}

void sdf_loadScene(std::ifstream& file, Scene& scene) {
	std::string line{""};
	while(std::getline(file,line)) {
		//Comment
		if(sdf_isComment(line)) {
			continue;
		}
		// Material
		Material* tmp_material{nullptr};
		if(sdf_isMaterial(line,tmp_material)) {
			scene.materials.push_back(tmp_material);
			continue;
		}
	}
}

#endif
<commit_msg>Change idea of sdfloader (hopefully)<commit_after>#ifndef BUW_SDFLOADER_HPP
#define BUW_SDFLOADER_HPP

#include <string>
#include <scene.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <regex>

void sdf_splitString(std::string const& input, std::vector<std::string>& output) {
	std::istringstream tmp{input};
	do {
		std::string sub{""};
		tmp >> sub;
		output.push_back(sub);
	} while(tmp);
}

bool sdf_isMaterial(std::string const& input) {
	std::regex rgx_material{"define[\\s\\t]material[\\s\\t]\\S+[\\s\\t]([0-9][\\s\\t]){9}[0-9].*"};
	if(std::regex_match(input,rgx_material)) {
		return true;
	}
	return false;
}

void sdf_parseMaterial(std::string const& input, std::map<Material>& materials) {
	std::vector<std::string> parsed;
	sdf_splitString(input,parsed);
	Color ka = {std::stof(parsed[3]),std::stof(parsed[4]),std::stof(parsed[5])};
	Color kd = {std::stof(parsed[6]),std::stof(parsed[7]),std::stof(parsed[8])};
	Color ks = {std::stof(parsed[9]),std::stof(parsed[10]),std::stof(parsed[11])};
	materials.push_back(parsed[2],ka,kd,ks,std::stof(parsed[12]));
}

bool sdf_isComment(std::string const& input) {
	std::regex rgx_comment{"^#.*"};
	if(std::regex_match(input, rgx_comment)) {
		return true;
	}
	return false;
}

void sdf_loadScene(std::ifstream& file, Scene& scene) {
	std::string line{""};
	while(std::getline(file,line)) {
		//Comment
		if(sdf_isComment(line)) {
			continue;
		}
		// Material
		Material* tmp_material{nullptr};
		if(sdf_isMaterial(line)) {
			sdf_parseMaterial(line,scene.materials);
			//scene.materials.push_back(tmp_material);
			continue;
		}
	}
}

#endif
<|endoftext|>


<commit_before>//===- MemorySSA.cpp - Unit tests for MemorySSA ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/DataLayout.h"
#include "llvm/Transforms/Utils/MemorySSA.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "gtest/gtest.h"

using namespace llvm;

const static char DLString[] = "e-i64:64-f80:128-n8:16:32:64-S128";

/// There's a lot of common setup between these tests. This fixture helps reduce
/// that. Tests should mock up a function, store it in F, and then call
/// setupAnalyses().
class MemorySSATest : public testing::Test {
protected:
  // N.B. Many of these members depend on each other (e.g. the Module depends on
  // the Context, etc.). So, order matters here (and in TestAnalyses).
  LLVMContext C;
  Module M;
  IRBuilder<> B;
  DataLayout DL;
  TargetLibraryInfoImpl TLII;
  TargetLibraryInfo TLI;
  Function *F;

  // Things that we need to build after the function is created.
  struct TestAnalyses {
    DominatorTree DT;
    AssumptionCache AC;
    AAResults AA;
    BasicAAResult BAA;
    MemorySSA MSSA;
    MemorySSAWalker *Walker;

    TestAnalyses(MemorySSATest &Test)
        : DT(*Test.F), AC(*Test.F), AA(Test.TLI),
          BAA(Test.DL, Test.TLI, AC, &DT), MSSA(*Test.F, &AA, &DT) {
      AA.addAAResult(BAA);
      Walker = MSSA.getWalker();
    }
  };

  std::unique_ptr<TestAnalyses> Analyses;

  void setupAnalyses() {
    assert(F);
    Analyses.reset(new TestAnalyses(*this));
  }

public:
  MemorySSATest()
      : M("MemorySSATest", C), B(C), DL(DLString), TLI(TLII), F(nullptr) {}
};

TEST_F(MemorySSATest, RemoveMemoryAccess) {
  // We create a diamond where there is a store on one side, and then a load
  // after the merge point.  This enables us to test a bunch of different
  // removal cases.
  F = Function::Create(
      FunctionType::get(B.getVoidTy(), {B.getInt8PtrTy()}, false),
      GlobalValue::ExternalLinkage, "F", &M);
  BasicBlock *Entry(BasicBlock::Create(C, "", F));
  BasicBlock *Left(BasicBlock::Create(C, "", F));
  BasicBlock *Right(BasicBlock::Create(C, "", F));
  BasicBlock *Merge(BasicBlock::Create(C, "", F));
  B.SetInsertPoint(Entry);
  B.CreateCondBr(B.getTrue(), Left, Right);
  B.SetInsertPoint(Left);
  Argument *PointerArg = &*F->arg_begin();
  StoreInst *StoreInst = B.CreateStore(B.getInt8(16), PointerArg);
  BranchInst::Create(Merge, Left);
  BranchInst::Create(Merge, Right);
  B.SetInsertPoint(Merge);
  LoadInst *LoadInst = B.CreateLoad(PointerArg);

  setupAnalyses();
  MemorySSA &MSSA = Analyses->MSSA;
  MemorySSAWalker *Walker = &*Analyses->Walker;

  // Before, the load will be a use of a phi<store, liveonentry>. It should be
  // the same after.
  MemoryUse *LoadAccess = cast<MemoryUse>(MSSA.getMemoryAccess(LoadInst));
  MemoryDef *StoreAccess = cast<MemoryDef>(MSSA.getMemoryAccess(StoreInst));
  MemoryAccess *DefiningAccess = LoadAccess->getDefiningAccess();
  EXPECT_TRUE(isa<MemoryPhi>(DefiningAccess));
  // The load is currently clobbered by one of the phi arguments, so the walker
  // should determine the clobbering access as the phi.
  EXPECT_EQ(DefiningAccess, Walker->getClobberingMemoryAccess(LoadInst));
  MSSA.removeMemoryAccess(StoreAccess);
  MSSA.verifyMemorySSA();
  // After the removeaccess, let's see if we got the right accesses
  // The load should still point to the phi ...
  EXPECT_EQ(DefiningAccess, LoadAccess->getDefiningAccess());
  // but we should now get live on entry for the clobbering definition of the
  // load, since it will walk past the phi node since every argument is the
  // same.
  EXPECT_TRUE(
      MSSA.isLiveOnEntryDef(Walker->getClobberingMemoryAccess(LoadInst)));

  // The phi should now be a two entry phi with two live on entry defs.
  for (const auto &Op : DefiningAccess->operands()) {
    MemoryAccess *Operand = cast<MemoryAccess>(&*Op);
    EXPECT_TRUE(MSSA.isLiveOnEntryDef(Operand));
  }

  // Now we try to remove the single valued phi
  MSSA.removeMemoryAccess(DefiningAccess);
  MSSA.verifyMemorySSA();
  // Now the load should be a load of live on entry.
  EXPECT_TRUE(MSSA.isLiveOnEntryDef(LoadAccess->getDefiningAccess()));
}

// We had a bug with caching where the walker would report MemoryDef#3's clobber
// (below) was MemoryDef#1.
//
// define void @F(i8*) {
//   %A = alloca i8, i8 1
// ; 1 = MemoryDef(liveOnEntry)
//   store i8 0, i8* %A
// ; 2 = MemoryDef(1)
//   store i8 1, i8* %A
// ; 3 = MemoryDef(2)
//   store i8 2, i8* %A
// }
TEST_F(MemorySSATest, TestTripleStore) {
  F = Function::Create(
      FunctionType::get(B.getVoidTy(), {}, false),
      GlobalValue::ExternalLinkage, "F", &M);
  B.SetInsertPoint(BasicBlock::Create(C, "", F));
  Type *Int8 = Type::getInt8Ty(C);
  Value *Alloca = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
  StoreInst *S1 = B.CreateStore(ConstantInt::get(Int8, 0), Alloca);
  StoreInst *S2 = B.CreateStore(ConstantInt::get(Int8, 1), Alloca);
  StoreInst *S3 = B.CreateStore(ConstantInt::get(Int8, 2), Alloca);

  setupAnalyses();
  MemorySSA &MSSA = Analyses->MSSA;
  MemorySSAWalker *Walker = &*Analyses->Walker;

  unsigned I = 0;
  for (StoreInst *V : {S1, S2, S3}) {
    // Everything should be clobbered by its defining access
    MemoryAccess *DefiningAccess =
        cast<MemoryUseOrDef>(MSSA.getMemoryAccess(V))->getDefiningAccess();
    MemoryAccess *WalkerClobber = Walker->getClobberingMemoryAccess(V);
    EXPECT_EQ(DefiningAccess, WalkerClobber)
        << "Store " << I << " doesn't have the correct clobbering access";
    // EXPECT_EQ expands such that if we increment I above, it won't get
    // incremented except when we try to print the error message.
    ++I;
  }
}

// ...And fixing the above bug made it obvious that, when walking, MemorySSA's
// walker was caching the initial node it walked. This was fine (albeit
// mostly redundant) unless the initial node being walked is a clobber for the
// query. In that case, we'd cache that the node clobbered itself.
TEST_F(MemorySSATest, TestStoreAndLoad) {
  F = Function::Create(
      FunctionType::get(B.getVoidTy(), {}, false),
      GlobalValue::ExternalLinkage, "F", &M);
  B.SetInsertPoint(BasicBlock::Create(C, "", F));
  Type *Int8 = Type::getInt8Ty(C);
  Value *Alloca = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
  Instruction *SI = B.CreateStore(ConstantInt::get(Int8, 0), Alloca);
  Instruction *LI = B.CreateLoad(Alloca);

  setupAnalyses();
  MemorySSA &MSSA = Analyses->MSSA;
  MemorySSAWalker *Walker = &*Analyses->Walker;

  MemoryAccess *LoadClobber = Walker->getClobberingMemoryAccess(LI);
  EXPECT_EQ(LoadClobber, MSSA.getMemoryAccess(SI));
  EXPECT_TRUE(MSSA.isLiveOnEntryDef(Walker->getClobberingMemoryAccess(SI)));
}

// Another bug (related to the above two fixes): It was noted that, given the
// following code:
// ; 1 = MemoryDef(liveOnEntry)
// store i8 0, i8* %1
//
// ...A query to getClobberingMemoryAccess(MemoryAccess*, MemoryLocation) would
// hand back the store (correctly). A later call to
// getClobberingMemoryAccess(const Instruction*) would also hand back the store
// (incorrectly; it should return liveOnEntry).
//
// This test checks that repeated calls to either function returns what they're
// meant to.
TEST_F(MemorySSATest, TestStoreDoubleQuery) {
  F = Function::Create(
      FunctionType::get(B.getVoidTy(), {}, false),
      GlobalValue::ExternalLinkage, "F", &M);
  B.SetInsertPoint(BasicBlock::Create(C, "", F));
  Type *Int8 = Type::getInt8Ty(C);
  Value *Alloca = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
  StoreInst *SI = B.CreateStore(ConstantInt::get(Int8, 0), Alloca);

  setupAnalyses();
  MemorySSA &MSSA = Analyses->MSSA;
  MemorySSAWalker *Walker = &*Analyses->Walker;

  MemoryAccess *StoreAccess = MSSA.getMemoryAccess(SI);
  MemoryLocation StoreLoc = MemoryLocation::get(SI);
  MemoryAccess *Clobber = Walker->getClobberingMemoryAccess(StoreAccess, StoreLoc);
  MemoryAccess *LiveOnEntry = Walker->getClobberingMemoryAccess(SI);

  EXPECT_EQ(Clobber, StoreAccess);
  EXPECT_TRUE(MSSA.isLiveOnEntryDef(LiveOnEntry));

  // Try again (with entries in the cache already) for good measure...
  Clobber = Walker->getClobberingMemoryAccess(StoreAccess, StoreLoc);
  LiveOnEntry = Walker->getClobberingMemoryAccess(SI);
  EXPECT_EQ(Clobber, StoreAccess);
  EXPECT_TRUE(MSSA.isLiveOnEntryDef(LiveOnEntry));
}
<commit_msg>[MemorySSA] Clean up unit tests a tiny bit. NFC.<commit_after>//===- MemorySSA.cpp - Unit tests for MemorySSA ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/DataLayout.h"
#include "llvm/Transforms/Utils/MemorySSA.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "gtest/gtest.h"

using namespace llvm;

const static char DLString[] = "e-i64:64-f80:128-n8:16:32:64-S128";

/// There's a lot of common setup between these tests. This fixture helps reduce
/// that. Tests should mock up a function, store it in F, and then call
/// setupAnalyses().
class MemorySSATest : public testing::Test {
protected:
  // N.B. Many of these members depend on each other (e.g. the Module depends on
  // the Context, etc.). So, order matters here (and in TestAnalyses).
  LLVMContext C;
  Module M;
  IRBuilder<> B;
  DataLayout DL;
  TargetLibraryInfoImpl TLII;
  TargetLibraryInfo TLI;
  Function *F;

  // Things that we need to build after the function is created.
  struct TestAnalyses {
    DominatorTree DT;
    AssumptionCache AC;
    AAResults AA;
    BasicAAResult BAA;
    MemorySSA MSSA;
    MemorySSAWalker *Walker;

    TestAnalyses(MemorySSATest &Test)
        : DT(*Test.F), AC(*Test.F), AA(Test.TLI),
          BAA(Test.DL, Test.TLI, AC, &DT), MSSA(*Test.F, &AA, &DT) {
      AA.addAAResult(BAA);
      Walker = MSSA.getWalker();
    }
  };

  std::unique_ptr<TestAnalyses> Analyses;

  void setupAnalyses() {
    assert(F);
    Analyses.reset(new TestAnalyses(*this));
  }

public:
  MemorySSATest()
      : M("MemorySSATest", C), B(C), DL(DLString), TLI(TLII), F(nullptr) {}
};

TEST_F(MemorySSATest, RemoveMemoryAccess) {
  // We create a diamond where there is a store on one side, and then a load
  // after the merge point.  This enables us to test a bunch of different
  // removal cases.
  F = Function::Create(
      FunctionType::get(B.getVoidTy(), {B.getInt8PtrTy()}, false),
      GlobalValue::ExternalLinkage, "F", &M);
  BasicBlock *Entry(BasicBlock::Create(C, "", F));
  BasicBlock *Left(BasicBlock::Create(C, "", F));
  BasicBlock *Right(BasicBlock::Create(C, "", F));
  BasicBlock *Merge(BasicBlock::Create(C, "", F));
  B.SetInsertPoint(Entry);
  B.CreateCondBr(B.getTrue(), Left, Right);
  B.SetInsertPoint(Left);
  Argument *PointerArg = &*F->arg_begin();
  StoreInst *StoreInst = B.CreateStore(B.getInt8(16), PointerArg);
  BranchInst::Create(Merge, Left);
  BranchInst::Create(Merge, Right);
  B.SetInsertPoint(Merge);
  LoadInst *LoadInst = B.CreateLoad(PointerArg);

  setupAnalyses();
  MemorySSA &MSSA = Analyses->MSSA;
  MemorySSAWalker *Walker = Analyses->Walker;

  // Before, the load will be a use of a phi<store, liveonentry>. It should be
  // the same after.
  MemoryUse *LoadAccess = cast<MemoryUse>(MSSA.getMemoryAccess(LoadInst));
  MemoryDef *StoreAccess = cast<MemoryDef>(MSSA.getMemoryAccess(StoreInst));
  MemoryAccess *DefiningAccess = LoadAccess->getDefiningAccess();
  EXPECT_TRUE(isa<MemoryPhi>(DefiningAccess));
  // The load is currently clobbered by one of the phi arguments, so the walker
  // should determine the clobbering access as the phi.
  EXPECT_EQ(DefiningAccess, Walker->getClobberingMemoryAccess(LoadInst));
  MSSA.removeMemoryAccess(StoreAccess);
  MSSA.verifyMemorySSA();
  // After the removeaccess, let's see if we got the right accesses
  // The load should still point to the phi ...
  EXPECT_EQ(DefiningAccess, LoadAccess->getDefiningAccess());
  // but we should now get live on entry for the clobbering definition of the
  // load, since it will walk past the phi node since every argument is the
  // same.
  EXPECT_TRUE(
      MSSA.isLiveOnEntryDef(Walker->getClobberingMemoryAccess(LoadInst)));

  // The phi should now be a two entry phi with two live on entry defs.
  for (const auto &Op : DefiningAccess->operands()) {
    MemoryAccess *Operand = cast<MemoryAccess>(&*Op);
    EXPECT_TRUE(MSSA.isLiveOnEntryDef(Operand));
  }

  // Now we try to remove the single valued phi
  MSSA.removeMemoryAccess(DefiningAccess);
  MSSA.verifyMemorySSA();
  // Now the load should be a load of live on entry.
  EXPECT_TRUE(MSSA.isLiveOnEntryDef(LoadAccess->getDefiningAccess()));
}

// We had a bug with caching where the walker would report MemoryDef#3's clobber
// (below) was MemoryDef#1.
//
// define void @F(i8*) {
//   %A = alloca i8, i8 1
// ; 1 = MemoryDef(liveOnEntry)
//   store i8 0, i8* %A
// ; 2 = MemoryDef(1)
//   store i8 1, i8* %A
// ; 3 = MemoryDef(2)
//   store i8 2, i8* %A
// }
TEST_F(MemorySSATest, TestTripleStore) {
  F = Function::Create(
      FunctionType::get(B.getVoidTy(), {}, false),
      GlobalValue::ExternalLinkage, "F", &M);
  B.SetInsertPoint(BasicBlock::Create(C, "", F));
  Type *Int8 = Type::getInt8Ty(C);
  Value *Alloca = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
  StoreInst *S1 = B.CreateStore(ConstantInt::get(Int8, 0), Alloca);
  StoreInst *S2 = B.CreateStore(ConstantInt::get(Int8, 1), Alloca);
  StoreInst *S3 = B.CreateStore(ConstantInt::get(Int8, 2), Alloca);

  setupAnalyses();
  MemorySSA &MSSA = Analyses->MSSA;
  MemorySSAWalker *Walker = Analyses->Walker;

  unsigned I = 0;
  for (StoreInst *V : {S1, S2, S3}) {
    // Everything should be clobbered by its defining access
    MemoryAccess *DefiningAccess =
        cast<MemoryUseOrDef>(MSSA.getMemoryAccess(V))->getDefiningAccess();
    MemoryAccess *WalkerClobber = Walker->getClobberingMemoryAccess(V);
    EXPECT_EQ(DefiningAccess, WalkerClobber)
        << "Store " << I << " doesn't have the correct clobbering access";
    // EXPECT_EQ expands such that if we increment I above, it won't get
    // incremented except when we try to print the error message.
    ++I;
  }
}

// ...And fixing the above bug made it obvious that, when walking, MemorySSA's
// walker was caching the initial node it walked. This was fine (albeit
// mostly redundant) unless the initial node being walked is a clobber for the
// query. In that case, we'd cache that the node clobbered itself.
TEST_F(MemorySSATest, TestStoreAndLoad) {
  F = Function::Create(
      FunctionType::get(B.getVoidTy(), {}, false),
      GlobalValue::ExternalLinkage, "F", &M);
  B.SetInsertPoint(BasicBlock::Create(C, "", F));
  Type *Int8 = Type::getInt8Ty(C);
  Value *Alloca = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
  Instruction *SI = B.CreateStore(ConstantInt::get(Int8, 0), Alloca);
  Instruction *LI = B.CreateLoad(Alloca);

  setupAnalyses();
  MemorySSA &MSSA = Analyses->MSSA;
  MemorySSAWalker *Walker = Analyses->Walker;

  MemoryAccess *LoadClobber = Walker->getClobberingMemoryAccess(LI);
  EXPECT_EQ(LoadClobber, MSSA.getMemoryAccess(SI));
  EXPECT_TRUE(MSSA.isLiveOnEntryDef(Walker->getClobberingMemoryAccess(SI)));
}

// Another bug (related to the above two fixes): It was noted that, given the
// following code:
// ; 1 = MemoryDef(liveOnEntry)
// store i8 0, i8* %1
//
// ...A query to getClobberingMemoryAccess(MemoryAccess*, MemoryLocation) would
// hand back the store (correctly). A later call to
// getClobberingMemoryAccess(const Instruction*) would also hand back the store
// (incorrectly; it should return liveOnEntry).
//
// This test checks that repeated calls to either function returns what they're
// meant to.
TEST_F(MemorySSATest, TestStoreDoubleQuery) {
  F = Function::Create(
      FunctionType::get(B.getVoidTy(), {}, false),
      GlobalValue::ExternalLinkage, "F", &M);
  B.SetInsertPoint(BasicBlock::Create(C, "", F));
  Type *Int8 = Type::getInt8Ty(C);
  Value *Alloca = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
  StoreInst *SI = B.CreateStore(ConstantInt::get(Int8, 0), Alloca);

  setupAnalyses();
  MemorySSA &MSSA = Analyses->MSSA;
  MemorySSAWalker *Walker = Analyses->Walker;

  MemoryAccess *StoreAccess = MSSA.getMemoryAccess(SI);
  MemoryLocation StoreLoc = MemoryLocation::get(SI);
  MemoryAccess *Clobber = Walker->getClobberingMemoryAccess(StoreAccess, StoreLoc);
  MemoryAccess *LiveOnEntry = Walker->getClobberingMemoryAccess(SI);

  EXPECT_EQ(Clobber, StoreAccess);
  EXPECT_TRUE(MSSA.isLiveOnEntryDef(LiveOnEntry));

  // Try again (with entries in the cache already) for good measure...
  Clobber = Walker->getClobberingMemoryAccess(StoreAccess, StoreLoc);
  LiveOnEntry = Walker->getClobberingMemoryAccess(SI);
  EXPECT_EQ(Clobber, StoreAccess);
  EXPECT_TRUE(MSSA.isLiveOnEntryDef(LiveOnEntry));
}
<|endoftext|>


<commit_before>/*
 *  Author:
 *     Guido Tack <guido.tack@monash.edu>
 *
 *  Copyright:
 *     NICTA 2013
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "paramdialog.h"
#include "ui_paramdialog.h"

#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QFormLayout>
#include <QFileInfo>
#include <QDebug>

ParamDialog::ParamDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ParamDialog)
{
    ui->setupUi(this);
}

void ParamDialog::getParams(QStringList params, const QStringList& dataFiles, QStringList &values, QString &dataFile)
{
    QVector<QLineEdit*> le;
    QFormLayout* formLayout = new QFormLayout;
    ui->frame->setLayout(formLayout);
    QComboBox* cb = NULL;
    if (dataFiles.size() > 0) {
        cb = new QComboBox();
        connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(dataFileChanged(int)));
        cb->addItem("Select data file or input values");
        int selectItem = 0;
        for (int i=0; i<dataFiles.size(); i++) {
            QFileInfo fi(dataFiles[i]);
            cb->addItem(fi.fileName(),dataFiles[i]);
            if (previousDataFile==dataFiles[i])
                selectItem = i+1;
        }
        cb->setCurrentIndex(selectItem);
        formLayout->addRow(cb);
    }
    bool fillPrevious = previousParams == params;
    for (int i=0; i<params.size(); i++) {
        QLineEdit* e = new QLineEdit(fillPrevious ? previousValues[i] : "");
        if (cb && cb->currentIndex()!=0)
            e->setEnabled(false);
        le.append(e);
        formLayout->addRow(new QLabel(params[i]+" ="), le.back());
    }
    if (cb==NULL || cb->currentIndex()==0)
        le[0]->setFocus();
    if (QDialog::exec()==QDialog::Accepted) {
        if (cb && cb->currentIndex() != 0) {
            dataFile = cb->currentData().toString();
            previousDataFile = dataFile;
        } else {
            for (int i=0; i<le.size(); i++)
                values << le[i]->text();
            previousParams = params;
            previousValues = values;
        }
    }
    delete ui->frame;
    ui->frame = new QFrame;
    ui->frame->setFrameShape(QFrame::StyledPanel);
    ui->frame->setFrameShadow(QFrame::Raised);
    ui->verticalLayout->insertWidget(0, ui->frame);
}

void ParamDialog::dataFileChanged(int i)
{
    bool disable = (i>0);
    QFormLayout* l = static_cast<QFormLayout*>(ui->frame->layout());
    for (int i=1; i<l->rowCount(); i++) {
        QWidget* w = l->itemAt(i,QFormLayout::FieldRole)->widget();
        w->setDisabled(disable);
    }
}

ParamDialog::~ParamDialog()
{
    delete ui;
}
<commit_msg>Remember whether previous run used a data file or direct parameter input<commit_after>/*
 *  Author:
 *     Guido Tack <guido.tack@monash.edu>
 *
 *  Copyright:
 *     NICTA 2013
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "paramdialog.h"
#include "ui_paramdialog.h"

#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QFormLayout>
#include <QFileInfo>
#include <QDebug>

ParamDialog::ParamDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ParamDialog)
{
    ui->setupUi(this);
}

void ParamDialog::getParams(QStringList params, const QStringList& dataFiles, QStringList &values, QString &dataFile)
{
    QVector<QLineEdit*> le;
    QFormLayout* formLayout = new QFormLayout;
    ui->frame->setLayout(formLayout);
    QComboBox* cb = NULL;
    if (dataFiles.size() > 0) {
        cb = new QComboBox();
        connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(dataFileChanged(int)));
        cb->addItem("Select data file or input values");
        int selectItem = 0;
        for (int i=0; i<dataFiles.size(); i++) {
            QFileInfo fi(dataFiles[i]);
            cb->addItem(fi.fileName(),dataFiles[i]);
            if (previousDataFile==dataFiles[i])
                selectItem = i+1;
        }
        cb->setCurrentIndex(selectItem);
        formLayout->addRow(cb);
    }
    bool fillPrevious = previousParams == params;
    for (int i=0; i<params.size(); i++) {
        QLineEdit* e = new QLineEdit(fillPrevious ? previousValues[i] : "");
        if (cb && cb->currentIndex()!=0)
            e->setEnabled(false);
        le.append(e);
        formLayout->addRow(new QLabel(params[i]+" ="), le.back());
    }
    if (cb==NULL || cb->currentIndex()==0)
        le[0]->setFocus();
    if (QDialog::exec()==QDialog::Accepted) {
        if (cb && cb->currentIndex() != 0) {
            dataFile = cb->currentData().toString();
            previousDataFile = dataFile;
        } else {
            for (int i=0; i<le.size(); i++)
                values << le[i]->text();
            previousParams = params;
            previousValues = values;
            previousDataFile = "";
        }
    }
    delete ui->frame;
    ui->frame = new QFrame;
    ui->frame->setFrameShape(QFrame::StyledPanel);
    ui->frame->setFrameShadow(QFrame::Raised);
    ui->verticalLayout->insertWidget(0, ui->frame);
}

void ParamDialog::dataFileChanged(int i)
{
    bool disable = (i>0);
    QFormLayout* l = static_cast<QFormLayout*>(ui->frame->layout());
    for (int i=1; i<l->rowCount(); i++) {
        QWidget* w = l->itemAt(i,QFormLayout::FieldRole)->widget();
        w->setDisabled(disable);
    }
}

ParamDialog::~ParamDialog()
{
    delete ui;
}
<|endoftext|>