<commit_before>/* Copyright (c) 2009, Simeon Bird <spb41@cam.ac.uk>
 *               Based on code (c) 2005 by J. Bolton
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include <math.h>
#include "global_vars.h"
#include "parameters.h"
#include "gadgetreader.hpp"

/* this routine loads particle data from Gadget's default
 * binary file format. (A snapshot may be distributed
 * into multiple files. */
extern "C" int load_snapshot(char *fname, pdata *P,
  double  *atime, double *redshift, double * Hz, double *box100, double *h100, double *omegab)
{
  GadgetReader::GSnap snap(fname);
  int64_t NumPart;
  (*atime)= snap.GetHeader().time;
  (*redshift)= snap.GetHeader().redshift;
  (*box100) = snap.GetHeader().BoxSize;
  (*h100) = snap.GetHeader().HubbleParam;
  (*Hz)=100.0*(*h100) * sqrt(1.+snap.GetHeader().Omega0*(1./(*atime)-1.)+snap.GetHeader().OmegaLambda*((pow(*atime,2)) -1.))/(*atime);
  NumPart = snap.GetNpart(PARTTYPE);
  if(NumPart ==0)
          return 0;
  printf("NumPart=[%ld,%ld,%ld,%ld,%ld,%ld), ",snap.GetNpart(0),snap.GetNpart(1),snap.GetNpart(2),snap.GetNpart(3),snap.GetNpart(4),snap.GetNpart(5));
  printf("Masses=[%g %g %g %g %g %g], ",snap.GetHeader().mass[0],snap.GetHeader().mass[1],snap.GetHeader().mass[2],snap.GetHeader().mass[3],snap.GetHeader().mass[4],snap.GetHeader().mass[5]);
  printf("Redshift=%g, Ω_M=%g Ω_L=%g\n",(*redshift),snap.GetHeader().Omega0,snap.GetHeader().OmegaLambda);
  printf("Expansion factor = %f\n",(*atime));
  printf("Hubble = %g Box=%g \n",(*h100),(*box100));

  if(!(alloc_parts(P,NumPart)))
  {
    fprintf(stderr,"failed to allocate memory.\n\n");
    exit(1);
  }
  printf("Reading position and velocity...\n");
  snap.GetBlock("POS ",(*P).Pos,NumPart,0, (1<<N_TYPE)-1-(1<<PARTTYPE));
  snap.GetBlock("VEL ",(*P).Vel,NumPart,0, (1<<N_TYPE)-1-(1<<PARTTYPE));
  /* Particles masses  */
  printf("Reading mass and temp...\n");
  if(snap.GetHeader().mass[PARTTYPE])
        for(int i=0; i< NumPart;i++)
           (*P).Mass[i] = snap.GetHeader().mass[PARTTYPE];
  else{
        /*Set up types to skip; skip all types not in the mass array*/
        int skip = (1<<N_TYPE)-1-(1<<PARTTYPE);
        for(int i=0; i< N_TYPE; i++)
           if(snap.GetHeader().mass[i])
                   skip-=1<<i;
        snap.GetBlock("MASS",(*P).Mass,NumPart,0, skip);
  }
  for(int i=0; i< NumPart;i++)
  if ((*P).Mass[i] != (*P).Mass[0]){
        fprintf(stderr, "i=%d N = %ld Mass change: %g\n",i,NumPart, (*P).Mass[i]);
        exit(0);
  }
  (*omegab) = (*P).Mass[0]/((*P).Mass[0]+snap.GetHeader().mass[1])*snap.GetHeader().Omega0;
  /*Seek past the last masses*/
  if(PARTTYPE == 0)
    {
      /*The internal energy of all the Sph particles is read in */
      snap.GetBlock("U   ",(*P).U,NumPart,0,0);
      /* The free electron fraction */
      if(snap.GetHeader().flag_cooling)
        {
          int k;
          printf("Reading electron fractions...\n");
          /* Some versions of Gadget have Ne, some have NHP, NHEP and NHEPP,
           * which I map to NHEQ.*/
          /* Use that the universe is neutral, so
           * NE = NHP + NHEP +2 NHEPP*/
      #ifndef GADGET3
          snap.GetBlock("NHP ",(*P).Ne,NumPart,0,0);
          /*Use the space for HSML as temp space*/
          snap.GetBlock("NHEP",(*P).h,NumPart,0,0);
          for(k=0;k<NumPart;k++){
                  (*P).Ne[k]+=(*P).h[k];
          }
          snap.GetBlock("NHEQ",(*P).h,NumPart,0,0);
          for(k=0;k<NumPart;k++){
                  (*P).Ne[k]+=2*(*P).h[k];
          }
      #else
          snap.GetBlock("NE  ",(*P).Ne,NumPart,0,0);
      #endif
      #ifdef HELIUM
          snap.GetBlock("NHE ",(*P).NHep,NumPart,0,0);
      #endif
          /* The HI fraction, nHI/nH */
          snap.GetBlock("NH  ",(*P).NH0,NumPart,0,0);
          /*An NHE block*/
        }
     /* The smoothing length */
     snap.GetBlock("HSML",(*P).h,NumPart,0,0);
    }
  printf("P[%d].Pos = [%g %g %g]\n", 0, (*P).Pos[0], (*P).Pos[1],(*P).Pos[2]);
  printf("P[%d].Vel = [%g %g %g]\n", 0, (*P).Vel[0], (*P).Vel[1],(*P).Vel[2]);
  printf("P[%ld].Mass = %e Ω_B=%g\n\n", NumPart, (*P).Mass[0],(*omegab));
  printf("P[%ld].U = %f\n\n", NumPart, (*P).U[NumPart-1]);
  printf("P[%ld].Ne = %e\n", NumPart, (*P).Ne[NumPart-1]);
  printf("P[%ld].NH0 = %e\n", NumPart, (*P).NH0[NumPart-1]);
  printf("P[%ld].h = %f\n",NumPart, (*P).h[NumPart-1]);
#if 0
    int i;
  /*   Convert to SI units from GADGET-3 units */
  #pragma omp for schedule(static, 128)
  for(i=0;i<Ntype;i++)
  {
      double mu;
      int ic;
      for(ic=0;ic<3;ic++)
	{
	  (*P).Pos[3*i+ic] *= rscale; /* m, physical */
	  (*P).Vel[3*i+ic] *= vscale; /* km s^-1, physical */
	}

      (*P).h[i] *= hscale;   /* m, physical */
/*      (*P).Mass[i] = (*P).Mass[i] * mscale; *//* kg */
      /*We leave mass in GADGET units, to prevent a floating overflow
       * when we have poor resolution. (*P).Mass[i] only affects rhoker,
       * so we simply rescale rhoker later.*/

      /* Mean molecular weight */
      mu = 1.0/(XH*(0.75+(*P).Ne[i]) + 0.25);
      (*P).U[i] *= ((GAMMA-1.0) * mu * HMASS * PROTONMASS * escale ) / BOLTZMANN; /* K */
  }
  #pragma omp master
  {
    printf("Converted units.\n");
  }
  #pragma omp barrier
#endif
  return NumPart;
}

extern "C" int alloc_parts(pdata* P, int np)
{
    return ((*P).Vel=(float *)malloc(np*3*sizeof(float))) &&
    ((*P).Pos=(float *)malloc(np*3*sizeof(float))) &&
     ((*P).Mass=(float *) malloc(np*sizeof(float))) &&
    ((*P).U=(float *)malloc(np*sizeof(float))) &&
    ((*P).NH0=(float *)malloc(np*sizeof(float))) &&
    ((*P).Ne=(float *)malloc(np*sizeof(float))) &&
#ifdef HELIUM
    ((*P).NHep=(float *)malloc(np*sizeof(float))) &&
#endif
    ((*P).h=(float *)malloc(np*sizeof(float)));
}

extern "C" void free_parts(pdata* P)
{
    free((*P).Vel);
    free((*P).Pos);
    free((*P).Mass);
    free((*P).U);
    free((*P).NH0);
    free((*P).Ne);
    free((*P).h);
#ifdef HELIUM
    free((*P).NHep);
#endif
    return;
}
<commit_msg>Read format 1 files correctly when they are NHP, NHEP, etc<commit_after>/* Copyright (c) 2009, Simeon Bird <spb41@cam.ac.uk>
 *               Based on code (c) 2005 by J. Bolton
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include <math.h>
#include "global_vars.h"
#include "parameters.h"
#include "gadgetreader.hpp"

/* this routine loads particle data from Gadget's default
 * binary file format. (A snapshot may be distributed
 * into multiple files. */
extern "C" int load_snapshot(char *fname, pdata *P,
  double  *atime, double *redshift, double * Hz, double *box100, double *h100, double *omegab)
{
#ifdef GADGET3
  GadgetReader::GSnap snap(fname);
#else
  const std::string blocks[14]={"HEAD","POS ","VEL ","ID  ","MASS","U   ","RHO ","NHP ","NHEP","NHEQ","NH  ","NHE ","HSML","SFR "};
  std::vector<std::string> BlockNames(blocks,blocks+14);
  GadgetReader::GSnap snap(fname, &BlockNames);
#endif
  int64_t NumPart;
  (*atime)= snap.GetHeader().time;
  (*redshift)= snap.GetHeader().redshift;
  (*box100) = snap.GetHeader().BoxSize;
  (*h100) = snap.GetHeader().HubbleParam;
  (*Hz)=100.0*(*h100) * sqrt(1.+snap.GetHeader().Omega0*(1./(*atime)-1.)+snap.GetHeader().OmegaLambda*((pow(*atime,2)) -1.))/(*atime);
  NumPart = snap.GetNpart(PARTTYPE);
  if(NumPart ==0)
          return 0;
  printf("NumPart=[%ld,%ld,%ld,%ld,%ld,%ld), ",snap.GetNpart(0),snap.GetNpart(1),snap.GetNpart(2),snap.GetNpart(3),snap.GetNpart(4),snap.GetNpart(5));
  printf("Masses=[%g %g %g %g %g %g], ",snap.GetHeader().mass[0],snap.GetHeader().mass[1],snap.GetHeader().mass[2],snap.GetHeader().mass[3],snap.GetHeader().mass[4],snap.GetHeader().mass[5]);
  printf("Redshift=%g, Ω_M=%g Ω_L=%g\n",(*redshift),snap.GetHeader().Omega0,snap.GetHeader().OmegaLambda);
  printf("Expansion factor = %f\n",(*atime));
  printf("Hubble = %g Box=%g \n",(*h100),(*box100));

  if(!(alloc_parts(P,NumPart)))
  {
    fprintf(stderr,"failed to allocate memory.\n\n");
    exit(1);
  }
  printf("Reading position and velocity...\n");
  snap.GetBlock("POS ",(*P).Pos,NumPart,0, (1<<N_TYPE)-1-(1<<PARTTYPE));
  snap.GetBlock("VEL ",(*P).Vel,NumPart,0, (1<<N_TYPE)-1-(1<<PARTTYPE));
  /* Particles masses  */
  printf("Reading mass and temp...\n");
  if(snap.GetHeader().mass[PARTTYPE])
        for(int i=0; i< NumPart;i++)
           (*P).Mass[i] = snap.GetHeader().mass[PARTTYPE];
  else{
        /*Set up types to skip; skip all types not in the mass array*/
        int skip = (1<<N_TYPE)-1-(1<<PARTTYPE);
        for(int i=0; i< N_TYPE; i++)
           if(snap.GetHeader().mass[i])
                   skip-=1<<i;
        snap.GetBlock("MASS",(*P).Mass,NumPart,0, skip);
  }
  for(int i=0; i< NumPart;i++)
  if ((*P).Mass[i] != (*P).Mass[0]){
        fprintf(stderr, "i=%d N = %ld Mass change: %g\n",i,NumPart, (*P).Mass[i]);
        exit(0);
  }
  (*omegab) = (*P).Mass[0]/((*P).Mass[0]+snap.GetHeader().mass[1])*snap.GetHeader().Omega0;
  /*Seek past the last masses*/
  if(PARTTYPE == 0)
    {
      /*The internal energy of all the Sph particles is read in */
      snap.GetBlock("U   ",(*P).U,NumPart,0,0);
      /* The free electron fraction */
      if(snap.GetHeader().flag_cooling)
        {
          int k;
          printf("Reading electron fractions...\n");
          /* Some versions of Gadget have Ne, some have NHP, NHEP and NHEPP,
           * which I map to NHEQ.*/
          /* Use that the universe is neutral, so
           * NE = NHP + NHEP +2 NHEPP*/
      #ifndef GADGET3
          snap.GetBlock("NHP ",(*P).Ne,NumPart,0,0);
          /*Use the space for HSML as temp space*/
          snap.GetBlock("NHEP",(*P).h,NumPart,0,0);
          for(k=0;k<NumPart;k++){
                  (*P).Ne[k]+=(*P).h[k];
          }
          snap.GetBlock("NHEQ",(*P).h,NumPart,0,0);
          for(k=0;k<NumPart;k++){
                  (*P).Ne[k]+=2*(*P).h[k];
          }
      #else
          snap.GetBlock("NE  ",(*P).Ne,NumPart,0,0);
      #endif
      #ifdef HELIUM
          snap.GetBlock("NHE ",(*P).NHep,NumPart,0,0);
      #endif
          /* The HI fraction, nHI/nH */
          snap.GetBlock("NH  ",(*P).NH0,NumPart,0,0);
          /*An NHE block*/
        }
     /* The smoothing length */
     snap.GetBlock("HSML",(*P).h,NumPart,0,0);
    }
  printf("P[%d].Pos = [%g %g %g]\n", 0, (*P).Pos[0], (*P).Pos[1],(*P).Pos[2]);
  printf("P[%d].Vel = [%g %g %g]\n", 0, (*P).Vel[0], (*P).Vel[1],(*P).Vel[2]);
  printf("P[%ld].Mass = %e Ω_B=%g\n\n", NumPart, (*P).Mass[0],(*omegab));
  printf("P[%ld].U = %f\n\n", NumPart, (*P).U[NumPart-1]);
  printf("P[%ld].Ne = %e\n", NumPart, (*P).Ne[NumPart-1]);
  printf("P[%ld].NH0 = %e\n", NumPart, (*P).NH0[NumPart-1]);
  printf("P[%ld].h = %f\n",NumPart, (*P).h[NumPart-1]);
#if 0
    int i;
  /*   Convert to SI units from GADGET-3 units */
  #pragma omp for schedule(static, 128)
  for(i=0;i<Ntype;i++)
  {
      double mu;
      int ic;
      for(ic=0;ic<3;ic++)
	{
	  (*P).Pos[3*i+ic] *= rscale; /* m, physical */
	  (*P).Vel[3*i+ic] *= vscale; /* km s^-1, physical */
	}

      (*P).h[i] *= hscale;   /* m, physical */
/*      (*P).Mass[i] = (*P).Mass[i] * mscale; *//* kg */
      /*We leave mass in GADGET units, to prevent a floating overflow
       * when we have poor resolution. (*P).Mass[i] only affects rhoker,
       * so we simply rescale rhoker later.*/

      /* Mean molecular weight */
      mu = 1.0/(XH*(0.75+(*P).Ne[i]) + 0.25);
      (*P).U[i] *= ((GAMMA-1.0) * mu * HMASS * PROTONMASS * escale ) / BOLTZMANN; /* K */
  }
  #pragma omp master
  {
    printf("Converted units.\n");
  }
  #pragma omp barrier
#endif
  return NumPart;
}

extern "C" int alloc_parts(pdata* P, int np)
{
    return ((*P).Vel=(float *)malloc(np*3*sizeof(float))) &&
    ((*P).Pos=(float *)malloc(np*3*sizeof(float))) &&
     ((*P).Mass=(float *) malloc(np*sizeof(float))) &&
    ((*P).U=(float *)malloc(np*sizeof(float))) &&
    ((*P).NH0=(float *)malloc(np*sizeof(float))) &&
    ((*P).Ne=(float *)malloc(np*sizeof(float))) &&
#ifdef HELIUM
    ((*P).NHep=(float *)malloc(np*sizeof(float))) &&
#endif
    ((*P).h=(float *)malloc(np*sizeof(float)));
}

extern "C" void free_parts(pdata* P)
{
    free((*P).Vel);
    free((*P).Pos);
    free((*P).Mass);
    free((*P).U);
    free((*P).NH0);
    free((*P).Ne);
    free((*P).h);
#ifdef HELIUM
    free((*P).NHep);
#endif
    return;
}
<|endoftext|>


<commit_before>#define PWN_ENGINE_NO_AUTOLINK

#include "system_vfs.hpp"

#include "system.hpp"
#include <physfs.h>
#include <pwn/engine/game>
#include <pwn/assert>

#include <boost/filesystem.hpp>

#pragma comment (lib, "physfs.lib")

namespace pwn
{
	namespace engine
	{
		namespace // local
		{
			void ThrowPhysFsError()
			{
				const char* error = PHYSFS_getLastError();
				Assert(error);
				const std::string message = error;
				throw message;
			}

			bool& gPhysFsCreated()
			{
				static bool created = false;
				return created;
			}
		}

		struct PhysFsStarter
		{
			bool deinitInDestructor;

			PhysFsStarter(const pwn::string& argv0)
				: deinitInDestructor(true)
			{
				Assert(gPhysFsCreated()==false);
				const int result = PHYSFS_init(argv0.c_str());
				if( result == 0) ThrowPhysFsError();
			}

			~PhysFsStarter()
			{
				if( deinitInDestructor )
				{
					PHYSFS_deinit();
				}
			}
		};

		namespace // local
		{
			const pwn::string GetParent(const pwn::string& app)
			{
				return (boost::filesystem::path(app).parent_path().parent_path() / "dummy.exe" ).file_string();
			}
		}

		class System_Vfs : public System
		{
		public:
			System_Vfs(const pwn::string& argv0, const pwn::string& company, const pwn::string& app)
			{
				{
					const pwn::string parentdir = GetParent(argv0);
					PhysFsStarter start(parentdir);
					const int result = PHYSFS_setSaneConfig(company.c_str(), app.c_str(), "vfs", 0, 0); // ignore cd-rom, append archives to search-list
					if( result == 0 ) ThrowPhysFsError();

					start.deinitInDestructor = false;
				}
				gPhysFsCreated() = true;
			}

			~System_Vfs()
			{
				PHYSFS_deinit();
				gPhysFsCreated() = false;
			}

			void update()
			{
				// nothing to do
			}
		};

		namespace
		{
			std::vector<pwn::string> FilesSeen(const pwn::string& dir)
			{
				std::vector<pwn::string> files;
				char **rc = PHYSFS_enumerateFiles(dir.c_str());
				char **i;

				for (i = rc; *i != NULL; i++)
				{
					files.push_back(*i);
				}

				PHYSFS_freeList(rc);

				return files;
			}

			void WriteFilesSeen()
			{
				std::vector<pwn::string> root = FilesSeen("");
			}
		}

		void SystemInstall_Vfs(Game* game, const pwn::string& argv0, const pwn::string& company, const pwn::string& app)
		{
			game->install(new System_Vfs(argv0, company, app));

			WriteFilesSeen();
		}

		/*
		FMOD_RESULT F_CALLBACK Open(const char *name, int unicode, unsigned int *filesize, void **handle, void **userdata) {
			if (name) {

				if ( !PHYSFS_exists(name) ) {
					return FMOD_ERR_FILE_NOTFOUND;
				}

				PHYSFS_file* fp = PHYSFS_openRead(name);
				if( !fp ) {
					return FMOD_ERR_FILE_BAD;
				}

				*filesize = PHYSFS_fileLength(fp);
				*userdata = (void *)0x12345678;
				*handle = fp;
			}

			return FMOD_OK;
		}

		FMOD_RESULT F_CALLBACK Close(void *handle, void *userdata) {
			if (!handle) {
				return FMOD_ERR_INVALID_PARAM;
			}
			PHYSFS_file* fp = (PHYSFS_file*) handle;
			PHYSFS_close(fp);

			return FMOD_OK;
		}

		FMOD_RESULT F_CALLBACK Read(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void *userdata) {
			if (!handle) {
				return FMOD_ERR_INVALID_PARAM;
			}

			if (bytesread) {
				PHYSFS_file* fp = (PHYSFS_file*) handle;
				*bytesread = (int)PHYSFS_read(fp, buffer, 1, sizebytes);

				if (*bytesread < sizebytes) {
					return FMOD_ERR_FILE_EOF;
				}
			}

			return FMOD_OK;
		}

		FMOD_RESULT F_CALLBACK Seek(void *handle, unsigned int pos, void *userdata) {
			if (!handle) {
				return FMOD_ERR_INVALID_PARAM;
			}

			PHYSFS_file* fp = (PHYSFS_file*) handle;
			//fseek((FILE *)handle, pos, SEEK_SET);
			int result = PHYSFS_seek(fp, pos);
			if( result == 0 ) {
				return FMOD_ERR_FILE_COULDNOTSEEK;
			}
			return FMOD_OK;
		}

		typedef std::list<std::string> SoundSource;
		typedef std::map<std::string, std::string> SoundDefinitionMap2;
		typedef std::map<std::string, SoundSource> SoundDefinitionMap3;
		typedef std::map<std::string, FMOD::Sound*> StringSoundMap;
		typedef std::map<std::string, FMOD::Channel*> StringChannelMap;

		std::string AsValidPath(const std::string& iPath) {
			if( EndsWith(iPath, "/") ) {
				return iPath;
			}
			else {
				return iPath + "/";
			}
		}

		class SoundSystem : public System {
		public:
			SoundSystem() : System(GetNameAndVersion()), mSystem(0) {
				Assert(!gSoundSystem, "Already has a sound system");
				test( FMOD::System_Create(&mSystem), "creating system" );
				Assert(mSystem, "internal error, bug?");
				// A buffer of 0 means all reads go directly to the pointer specified. 2048 bytes is the size of a CD sector on most CD ISO formats so it is chosen as the default, for optimal reading speed from CD media.
				test(mSystem->setFileSystem(Open, Close, Read, Seek, 2048), "setting file system");
			*/
	}
}<commit_msg>fixed physfs starter bug<commit_after>#define PWN_ENGINE_NO_AUTOLINK

#include "system_vfs.hpp"

#include "system.hpp"
#include <physfs.h>
#include <pwn/engine/game>
#include <pwn/assert>

#include <boost/filesystem.hpp>

#pragma comment (lib, "physfs.lib")

namespace pwn
{
	namespace engine
	{
		namespace // local
		{
			void ThrowPhysFsError()
			{
				const char* error = PHYSFS_getLastError();
				Assert(error);
				const std::string message = error;
				throw message;
			}

			bool& gPhysFsCreated()
			{
				static bool created = false;
				return created;
			}
		}

		struct PhysFsStarter
		{
			bool deinitInDestructor;

			PhysFsStarter(const pwn::string& argv0)
				: deinitInDestructor(false)
			{
				Assert(gPhysFsCreated()==false);
				const int result = PHYSFS_init(argv0.c_str());
				deinitInDestructor = true;
				if( result == 0) ThrowPhysFsError();
			}

			~PhysFsStarter()
			{
				if( deinitInDestructor )
				{
					PHYSFS_deinit();
				}
			}
		};

		namespace // local
		{
			const pwn::string GetParent(const pwn::string& app)
			{
				return (boost::filesystem::path(app).parent_path().parent_path() / "dummy.exe" ).file_string();
			}
		}

		class System_Vfs : public System
		{
		public:
			System_Vfs(const pwn::string& argv0, const pwn::string& company, const pwn::string& app)
			{
				{
					const pwn::string parentdir = GetParent(argv0);
					PhysFsStarter start(parentdir);
					const int result = PHYSFS_setSaneConfig(company.c_str(), app.c_str(), "vfs", 0, 0); // ignore cd-rom, append archives to search-list
					if( result == 0 ) ThrowPhysFsError();

					start.deinitInDestructor = false;
				}
				gPhysFsCreated() = true;
			}

			~System_Vfs()
			{
				PHYSFS_deinit();
				gPhysFsCreated() = false;
			}

			void update()
			{
				// nothing to do
			}
		};

		namespace
		{
			std::vector<pwn::string> FilesSeen(const pwn::string& dir)
			{
				std::vector<pwn::string> files;
				char **rc = PHYSFS_enumerateFiles(dir.c_str());
				char **i;

				for (i = rc; *i != NULL; i++)
				{
					files.push_back(*i);
				}

				PHYSFS_freeList(rc);

				return files;
			}

			void WriteFilesSeen()
			{
				std::vector<pwn::string> root = FilesSeen("");
			}
		}

		void SystemInstall_Vfs(Game* game, const pwn::string& argv0, const pwn::string& company, const pwn::string& app)
		{
			game->install(new System_Vfs(argv0, company, app));

			WriteFilesSeen();
		}

		/*
		FMOD_RESULT F_CALLBACK Open(const char *name, int unicode, unsigned int *filesize, void **handle, void **userdata) {
			if (name) {

				if ( !PHYSFS_exists(name) ) {
					return FMOD_ERR_FILE_NOTFOUND;
				}

				PHYSFS_file* fp = PHYSFS_openRead(name);
				if( !fp ) {
					return FMOD_ERR_FILE_BAD;
				}

				*filesize = PHYSFS_fileLength(fp);
				*userdata = (void *)0x12345678;
				*handle = fp;
			}

			return FMOD_OK;
		}

		FMOD_RESULT F_CALLBACK Close(void *handle, void *userdata) {
			if (!handle) {
				return FMOD_ERR_INVALID_PARAM;
			}
			PHYSFS_file* fp = (PHYSFS_file*) handle;
			PHYSFS_close(fp);

			return FMOD_OK;
		}

		FMOD_RESULT F_CALLBACK Read(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void *userdata) {
			if (!handle) {
				return FMOD_ERR_INVALID_PARAM;
			}

			if (bytesread) {
				PHYSFS_file* fp = (PHYSFS_file*) handle;
				*bytesread = (int)PHYSFS_read(fp, buffer, 1, sizebytes);

				if (*bytesread < sizebytes) {
					return FMOD_ERR_FILE_EOF;
				}
			}

			return FMOD_OK;
		}

		FMOD_RESULT F_CALLBACK Seek(void *handle, unsigned int pos, void *userdata) {
			if (!handle) {
				return FMOD_ERR_INVALID_PARAM;
			}

			PHYSFS_file* fp = (PHYSFS_file*) handle;
			//fseek((FILE *)handle, pos, SEEK_SET);
			int result = PHYSFS_seek(fp, pos);
			if( result == 0 ) {
				return FMOD_ERR_FILE_COULDNOTSEEK;
			}
			return FMOD_OK;
		}

		typedef std::list<std::string> SoundSource;
		typedef std::map<std::string, std::string> SoundDefinitionMap2;
		typedef std::map<std::string, SoundSource> SoundDefinitionMap3;
		typedef std::map<std::string, FMOD::Sound*> StringSoundMap;
		typedef std::map<std::string, FMOD::Channel*> StringChannelMap;

		std::string AsValidPath(const std::string& iPath) {
			if( EndsWith(iPath, "/") ) {
				return iPath;
			}
			else {
				return iPath + "/";
			}
		}

		class SoundSystem : public System {
		public:
			SoundSystem() : System(GetNameAndVersion()), mSystem(0) {
				Assert(!gSoundSystem, "Already has a sound system");
				test( FMOD::System_Create(&mSystem), "creating system" );
				Assert(mSystem, "internal error, bug?");
				// A buffer of 0 means all reads go directly to the pointer specified. 2048 bytes is the size of a CD sector on most CD ISO formats so it is chosen as the default, for optimal reading speed from CD media.
				test(mSystem->setFileSystem(Open, Close, Read, Seek, 2048), "setting file system");
			*/
	}
}<|endoftext|>


<commit_before>#pragma once

#include "Constants.hpp"
#include "Geometry2d/Point.hpp"
#include "time.hpp"

#include <cmath>
#include <deque>
#include <QString>
#include <stdexcept>
#include <stdint.h>
#include <sys/time.h>
#include <typeinfo>
#include <vector>
#include <QtWidgets>

const static bool THROW_DEBUG_EXCEPTIONS = true;

template <class exception>
inline void debugThrow(const exception& e) {
    if (THROW_DEBUG_EXCEPTIONS) {
        throw e;
    }
}

inline void debugThrow(const std::string& string) {
    debugThrow(std::runtime_error(string));
}

/**
 * @brief Restricts the given angle to be between pi and -pi
 *
 * @param a An angle in radians
 * @return An equivalent angle in radians restricted to [-pi, pi]
 */
static inline float fixAngleRadians(float a) {
    a = remainder(a, 2 * M_PI);
    while (a < -M_PI) a += 2.0 * M_PI;
    while (a > M_PI) a -= 2.0 * M_PI;
    return a;
}

/** Checks whether or not the given ball is in the defense area. */
static inline bool ballIsInGoalieBox(Geometry2d::Point point) {
    if (std::abs(point.x) <
        Field_Dimensions::Current_Dimensions.GoalFlat() / 2.0f) {
        // Ball is in center (rectangular) portion of defensive bubble
        return point.y > 0 &&
               point.y < Field_Dimensions::Current_Dimensions.ArcRadius();
    } else if (std::abs(point.x) <
               (Field_Dimensions::Current_Dimensions.ArcRadius() +
                Field_Dimensions::Current_Dimensions.GoalFlat() / 2.0f)) {
        // Ball is in one of the side (arc) portions of defensive bubble
        double adjusted_x =
            std::abs(point.x) -
            (Field_Dimensions::Current_Dimensions.GoalFlat() / 2.0f);
        double max_y = sqrt((Field_Dimensions::Current_Dimensions.ArcRadius() *
                             Field_Dimensions::Current_Dimensions.ArcRadius()) -
                            (adjusted_x * adjusted_x));
        return point.y > 0 && point.y <= max_y;
    }
    return false;
}

static Geometry2d::Point fromOursToTheirs(Geometry2d::Point& pt) {
    Geometry2d::Point c;
    c.y = Field_Dimensions::Current_Dimensions.Length() - pt.y;
    c.x = -pt.x;

    return c;
}

static bool ballIsInTheirGoalieBox(Geometry2d::Point& pt) {
    Geometry2d::Point converted = fromOursToTheirs(pt);
    return ballIsInGoalieBox(converted);
}

/** Returns @value if it is in bounds, otherwise returns the bound it is closest
 * to */
template <class T>
float clamp(T value, T min, T max) {
    if (value > max) {
        return max;
    } else if (value < min) {
        return min;
    }
    return value;
}

// Removes all entries in a std::map which associate to the given value.
template <class Map_Type, class Data_Type>
void map_remove(Map_Type& map, Data_Type& value) {
    typename Map_Type::iterator i = map.begin();
    while (i != map.end()) {
        typename Map_Type::iterator next = i;
        ++next;

        if (i->second == value) {
            map.erase(i);
        }

        i = next;
    }
}

// If <key> exists in <map>, returns map[key].
// If not, returns 0.
template <typename Map>
typename Map::mapped_type map_lookup(const Map& map,
                                     typename Map::key_type key) {
    typename Map::const_iterator i = map.find(key);
    if (i != map.end()) {
        return i->second;
    } else {
        return 0;
    }
}

/**
 * A basic FIR filter of variable type with float coeffs
 *
 * Note, coefficients will be normalized so that inputs
 * will always be scaled appropriately
 */
template <typename T>
class FIRFilter {
public:
    typedef std::vector<float> Coeffs;

    FIRFilter(const T& zero, size_t nrTaps) : _zero(zero) {
        if (nrTaps == 0)
            throw std::invalid_argument(
                "FIR Filter: number of taps must be greater than zero");

        // initialize
        _taps.assign(nrTaps, _zero);
        _coeffs.assign(nrTaps, 0.0f);
        _coeffs[0] = 1.0;
    }

    T filter(const T& x) {
        _taps.push_front(x);
        _taps.pop_back();

        T y = _zero;
        for (size_t i = 0; i < _taps.size(); ++i)
            y += _taps.at(i) * _coeffs.at(i);

        return y;
    }

    /** reinitializes the coeffs and taps to new values */
    void setCoeffs(const Coeffs& coeffs) {
        size_t nrTaps = coeffs.size();
        if (nrTaps == 0)
            throw std::invalid_argument(
                "FIR Filter: number of coeffs must be greater than zero");

        _taps.assign(nrTaps, _zero);
        _coeffs.assign(nrTaps, 0.0);

        // find the normalizer
        float normalizer = 0.0;
        for (size_t i = 0; i < coeffs.size(); ++i) normalizer += coeffs.at(i);

        // set the normalized coefficients
        for (size_t i = 0; i < coeffs.size(); ++i)
            _coeffs[i] = coeffs.at(i) / normalizer;
    }

protected:
    T _zero;
    std::deque<T> _taps;
    Coeffs _coeffs;
};

// An output iterator which throws an exception when it's used. This is used for
// example to determine if the output of set_difference would be non-empty
// without calculating all of it.
template <typename T>
class ExceptionIterator
    : public std::iterator<std::output_iterator_tag, void, void, void, void> {
public:
    ExceptionIterator& operator=(const T& value) { throw std::exception(); }

    ExceptionIterator& operator*() { return *this; }

    ExceptionIterator& operator++() { return *this; }

    ExceptionIterator& operator++(int) { return *this; }
};

// Sets str to the name of a class.
// Use it like this:
// 	Object *obj = new Object();
// 	QString name = typeName(typeid(*obj));
// The returned name is in the usual C++ format: "Namespace::Namespace::Class"
QString typeName(const std::type_info& info);

// Like typeName, but only returns the final class name part.
QString className(const std::type_info& info);

/// Returns the absolute path to the 'run' directory
QDir ApplicationRunDirectory();
<commit_msg>Temporarily pollute namespace with make_unique. Can be switched out pretty fast when we finally get c14 merged.<commit_after>#pragma once

#include "Constants.hpp"
#include "Geometry2d/Point.hpp"
#include "time.hpp"

#include <cmath>
#include <deque>
#include <QString>
#include <stdexcept>
#include <stdint.h>
#include <sys/time.h>
#include <typeinfo>
#include <vector>
#include <QtWidgets>

#include <boost/make_unique.hpp>

using boost::make_unique;

const static bool THROW_DEBUG_EXCEPTIONS = true;

template <class exception>
inline void debugThrow(const exception& e) {
    if (THROW_DEBUG_EXCEPTIONS) {
        throw e;
    }
}

inline void debugThrow(const std::string& string) {
    debugThrow(std::runtime_error(string));
}

/**
 * @brief Restricts the given angle to be between pi and -pi
 *
 * @param a An angle in radians
 * @return An equivalent angle in radians restricted to [-pi, pi]
 */
static inline float fixAngleRadians(float a) {
    a = remainder(a, 2 * M_PI);
    while (a < -M_PI) a += 2.0 * M_PI;
    while (a > M_PI) a -= 2.0 * M_PI;
    return a;
}

/** Checks whether or not the given ball is in the defense area. */
static inline bool ballIsInGoalieBox(Geometry2d::Point point) {
    if (std::abs(point.x) <
        Field_Dimensions::Current_Dimensions.GoalFlat() / 2.0f) {
        // Ball is in center (rectangular) portion of defensive bubble
        return point.y > 0 &&
               point.y < Field_Dimensions::Current_Dimensions.ArcRadius();
    } else if (std::abs(point.x) <
               (Field_Dimensions::Current_Dimensions.ArcRadius() +
                Field_Dimensions::Current_Dimensions.GoalFlat() / 2.0f)) {
        // Ball is in one of the side (arc) portions of defensive bubble
        double adjusted_x =
            std::abs(point.x) -
            (Field_Dimensions::Current_Dimensions.GoalFlat() / 2.0f);
        double max_y = sqrt((Field_Dimensions::Current_Dimensions.ArcRadius() *
                             Field_Dimensions::Current_Dimensions.ArcRadius()) -
                            (adjusted_x * adjusted_x));
        return point.y > 0 && point.y <= max_y;
    }
    return false;
}

static Geometry2d::Point fromOursToTheirs(Geometry2d::Point& pt) {
    Geometry2d::Point c;
    c.y = Field_Dimensions::Current_Dimensions.Length() - pt.y;
    c.x = -pt.x;

    return c;
}

static bool ballIsInTheirGoalieBox(Geometry2d::Point& pt) {
    Geometry2d::Point converted = fromOursToTheirs(pt);
    return ballIsInGoalieBox(converted);
}

/** Returns @value if it is in bounds, otherwise returns the bound it is closest
 * to */
template <class T>
float clamp(T value, T min, T max) {
    if (value > max) {
        return max;
    } else if (value < min) {
        return min;
    }
    return value;
}

// Removes all entries in a std::map which associate to the given value.
template <class Map_Type, class Data_Type>
void map_remove(Map_Type& map, Data_Type& value) {
    typename Map_Type::iterator i = map.begin();
    while (i != map.end()) {
        typename Map_Type::iterator next = i;
        ++next;

        if (i->second == value) {
            map.erase(i);
        }

        i = next;
    }
}

// If <key> exists in <map>, returns map[key].
// If not, returns 0.
template <typename Map>
typename Map::mapped_type map_lookup(const Map& map,
                                     typename Map::key_type key) {
    typename Map::const_iterator i = map.find(key);
    if (i != map.end()) {
        return i->second;
    } else {
        return 0;
    }
}

/**
 * A basic FIR filter of variable type with float coeffs
 *
 * Note, coefficients will be normalized so that inputs
 * will always be scaled appropriately
 */
template <typename T>
class FIRFilter {
public:
    typedef std::vector<float> Coeffs;

    FIRFilter(const T& zero, size_t nrTaps) : _zero(zero) {
        if (nrTaps == 0)
            throw std::invalid_argument(
                "FIR Filter: number of taps must be greater than zero");

        // initialize
        _taps.assign(nrTaps, _zero);
        _coeffs.assign(nrTaps, 0.0f);
        _coeffs[0] = 1.0;
    }

    T filter(const T& x) {
        _taps.push_front(x);
        _taps.pop_back();

        T y = _zero;
        for (size_t i = 0; i < _taps.size(); ++i)
            y += _taps.at(i) * _coeffs.at(i);

        return y;
    }

    /** reinitializes the coeffs and taps to new values */
    void setCoeffs(const Coeffs& coeffs) {
        size_t nrTaps = coeffs.size();
        if (nrTaps == 0)
            throw std::invalid_argument(
                "FIR Filter: number of coeffs must be greater than zero");

        _taps.assign(nrTaps, _zero);
        _coeffs.assign(nrTaps, 0.0);

        // find the normalizer
        float normalizer = 0.0;
        for (size_t i = 0; i < coeffs.size(); ++i) normalizer += coeffs.at(i);

        // set the normalized coefficients
        for (size_t i = 0; i < coeffs.size(); ++i)
            _coeffs[i] = coeffs.at(i) / normalizer;
    }

protected:
    T _zero;
    std::deque<T> _taps;
    Coeffs _coeffs;
};

// An output iterator which throws an exception when it's used. This is used for
// example to determine if the output of set_difference would be non-empty
// without calculating all of it.
template <typename T>
class ExceptionIterator
    : public std::iterator<std::output_iterator_tag, void, void, void, void> {
public:
    ExceptionIterator& operator=(const T& value) { throw std::exception(); }

    ExceptionIterator& operator*() { return *this; }

    ExceptionIterator& operator++() { return *this; }

    ExceptionIterator& operator++(int) { return *this; }
};

// Sets str to the name of a class.
// Use it like this:
// 	Object *obj = new Object();
// 	QString name = typeName(typeid(*obj));
// The returned name is in the usual C++ format: "Namespace::Namespace::Class"
QString typeName(const std::type_info& info);

// Like typeName, but only returns the final class name part.
QString className(const std::type_info& info);

/// Returns the absolute path to the 'run' directory
QDir ApplicationRunDirectory();
<|endoftext|>


<commit_before>#include <catch/catch.hpp>

#include <Transform/Referential.hpp>

using namespace obe::Transform;
using Axis = Referential::Axis;

TEST_CASE(
    "Flipping Referentials should give correct results",
    "[obe.Transform.Referential.flip]"
)
{
    SECTION("Flipping both axis of known referentials")
    {
        REQUIRE( Referential::TopLeft.flip() == Referential::BottomRight );
        REQUIRE( Referential::Top.flip() == Referential::Bottom );
        REQUIRE( Referential::TopRight.flip() == Referential::BottomLeft );
        REQUIRE( Referential::Left.flip() == Referential::Right );
        REQUIRE( Referential::Center.flip() == Referential::Center );
        REQUIRE( Referential::Right.flip() == Referential::Left );
        REQUIRE( Referential::BottomLeft.flip() == Referential::TopRight );
        REQUIRE( Referential::Bottom.flip() == Referential::Top );
        REQUIRE( Referential::BottomRight.flip() == Referential::TopLeft );
    }
    SECTION("Flipping only horizontal axis of known referentials")
    {
        REQUIRE( Referential::TopLeft.flip(Axis::Horizontal) == Referential::TopRight );
        REQUIRE( Referential::Top.flip(Axis::Horizontal) == Referential::Top );
        REQUIRE( Referential::TopRight.flip(Axis::Horizontal) == Referential::TopLeft );
        REQUIRE( Referential::Left.flip(Axis::Horizontal) == Referential::Right );
        REQUIRE( Referential::Center.flip(Axis::Horizontal) == Referential::Center );
        REQUIRE( Referential::Right.flip(Axis::Horizontal) == Referential::Left );
        REQUIRE( Referential::BottomLeft.flip(Axis::Horizontal) == Referential::BottomRight );
        REQUIRE( Referential::Bottom.flip(Axis::Horizontal) == Referential::Bottom );
        REQUIRE( Referential::BottomRight.flip(Axis::Horizontal) == Referential::BottomLeft );
    }
    SECTION("Flipping only vertical axis of known referentials")
    {
        REQUIRE( Referential::TopLeft.flip(Axis::Vertical) == Referential::BottomLeft );
        REQUIRE( Referential::Top.flip(Axis::Vertical) == Referential::Bottom );
        REQUIRE( Referential::TopRight.flip(Axis::Vertical) == Referential::BottomRight );
        REQUIRE( Referential::Left.flip(Axis::Vertical) == Referential::Left );
        REQUIRE( Referential::Center.flip(Axis::Vertical) == Referential::Center );
        REQUIRE( Referential::Right.flip(Axis::Vertical) == Referential::Right );
        REQUIRE( Referential::BottomLeft.flip(Axis::Vertical) == Referential::TopLeft );
        REQUIRE( Referential::Bottom.flip(Axis::Vertical) == Referential::Top );
        REQUIRE( Referential::BottomRight.flip(Axis::Vertical) == Referential::TopRight );
    }
    SECTION("Flipping both axis of random referentials")
    {
        REQUIRE( Referential(0.1, 0.4).flip() == Referential(0.9, 0.6) );
        REQUIRE( Referential(0.4, 0.666).flip() == Referential(0.6, 0.334) );
        REQUIRE( Referential(0.9, 0.23).flip() == Referential(-0.9, 0.23) );
        REQUIRE( Referential(0.123, 0.456).flip() == Referential(0.123, 0.456) );
    }
}

TEST_CASE(
    "We should be able to test the position of referentials based on criterias",
    "[obe.Transform.Referential.isOn...]"
)
{
    SECTION("Testing if known referentials are on a corner")
    {
        REQUIRE( Referential::TopLeft.isOnCorner() );
        REQUIRE( Referential::TopRight.isOnCorner() );
        REQUIRE( Referential::BottomLeft.isOnCorner() );
        REQUIRE( Referential::BottomRight.isOnCorner() );
        REQUIRE_FALSE( Referential::Top.isOnCorner() );
        REQUIRE_FALSE( Referential::Left.isOnCorner() );
        REQUIRE_FALSE( Referential::Center.isOnCorner() );
        REQUIRE_FALSE( Referential::Right.isOnCorner() );
        REQUIRE_FALSE( Referential::Bottom.isOnCorner() );
    }
    SECTION("Testing if known referentials are on a side")
    {
        REQUIRE_FALSE( Referential::TopLeft.isOnSide() );
        REQUIRE_FALSE( Referential::TopRight.isOnSide() );
        REQUIRE_FALSE( Referential::BottomLeft.isOnSide() );
        REQUIRE_FALSE( Referential::BottomRight.isOnSide() );
        REQUIRE( Referential::Top.isOnSide() );
        REQUIRE( Referential::Left.isOnSide() );
        REQUIRE_FALSE( Referential::Center.isOnSide() );
        REQUIRE( Referential::Right.isOnSide() );
        REQUIRE( Referential::Bottom.isOnSide() );
    }
    SECTION("Testing if known referentials are on the left")
    {
        REQUIRE( Referential::TopLeft.isOnLeftSide() );
        REQUIRE_FALSE( Referential::Top.isOnLeftSide() );
        REQUIRE_FALSE( Referential::TopRight.isOnLeftSide() );
        REQUIRE( Referential::Left.isOnLeftSide() );
        REQUIRE_FALSE( Referential::Center.isOnLeftSide() );
        REQUIRE_FALSE( Referential::Right.isOnLeftSide() );
        REQUIRE( Referential::BottomLeft.isOnLeftSide() );
        REQUIRE_FALSE( Referential::Bottom.isOnLeftSide() );
        REQUIRE_FALSE( Referential::BottomRight.isOnLeftSide() );
    }
    SECTION("Testing if known referentials are on the right")
    {
        REQUIRE_FALSE( Referential::TopLeft.isOnRightSide() );
        REQUIRE_FALSE( Referential::Top.isOnRightSide() );
        REQUIRE( Referential::TopRight.isOnRightSide() );
        REQUIRE_FALSE( Referential::Left.isOnRightSide() );
        REQUIRE_FALSE( Referential::Center.isOnRightSide() );
        REQUIRE( Referential::Right.isOnRightSide() );
        REQUIRE_FALSE( Referential::BottomLeft.isOnRightSide() );
        REQUIRE_FALSE( Referential::Bottom.isOnRightSide() );
        REQUIRE( Referential::BottomRight.isOnRightSide() );
    }
    SECTION("Testing if known referentials are on the top")
    {
        REQUIRE( Referential::TopLeft.isOnTopSide() );
        REQUIRE( Referential::Top.isOnTopSide() );
        REQUIRE( Referential::TopRight.isOnTopSide() );
        REQUIRE_FALSE( Referential::Left.isOnTopSide() );
        REQUIRE_FALSE( Referential::Center.isOnTopSide() );
        REQUIRE_FALSE( Referential::Right.isOnTopSide() );
        REQUIRE_FALSE( Referential::BottomLeft.isOnTopSide() );
        REQUIRE_FALSE( Referential::Bottom.isOnTopSide() );
        REQUIRE_FALSE( Referential::BottomRight.isOnTopSide() );
    }
    SECTION("Testing if known referentials are on the bottom")
    {
        REQUIRE_FALSE( Referential::TopLeft.isOnBottomSide() );
        REQUIRE_FALSE( Referential::Top.isOnBottomSide() );
        REQUIRE_FALSE( Referential::TopRight.isOnBottomSide() );
        REQUIRE_FALSE( Referential::Left.isOnBottomSide() );
        REQUIRE_FALSE( Referential::Center.isOnBottomSide() );
        REQUIRE_FALSE( Referential::Right.isOnBottomSide() );
        REQUIRE( Referential::BottomLeft.isOnBottomSide() );
        REQUIRE( Referential::Bottom.isOnBottomSide() );
        REQUIRE( Referential::BottomRight.isOnBottomSide() );
    }
    SECTION("Testing random referentials and their positions")
    {
        REQUIRE( Referential(1, 0.33).isOnRightSide() );
        REQUIRE( Referential(-1, 0.66).isOnLeftSide() );
        REQUIRE( Referential(0.22, 1).isOnBottomSide() );
        REQUIRE( Referential(-0.11, -1).isOnTopSide() );
        REQUIRE( Referential(0.99, 1).isOnSide() );
        REQUIRE( Referential(-1, -1).isOnCorner() );
        REQUIRE_FALSE( Referential(0.999, 0.33).isOnRightSide() );
        REQUIRE_FALSE( Referential(1, 0.66).isOnLeftSide() );
        REQUIRE_FALSE( Referential(0.22, -1).isOnBottomSide() );
        REQUIRE_FALSE( Referential(-0.11, 1).isOnTopSide() );
        REQUIRE_FALSE( Referential(0.99, 0.99).isOnSide() );
        REQUIRE_FALSE( Referential(-0.4, -1).isOnCorner() );
    }
}

TEST_CASE(
    "We should be able to represent a Referential as a string",
    "[obe.Transform.Referential.toString]"
)
{
    SECTION("Transforming known referentials to string with default formatter")
    {
        REQUIRE( Referential::TopLeft.toString() == "Referential<TopLeft>" );
        REQUIRE( Referential::Top.toString() == "Referential<Top>" );
        REQUIRE( Referential::TopRight.toString() == "Referential<TopRight>" );
        REQUIRE( Referential::Left.toString() == "Referential<Left>" );
        REQUIRE( Referential::Center.toString() == "Referential<Center>" );
        REQUIRE( Referential::Right.toString() == "Referential<Right>" );
        REQUIRE( Referential::BottomLeft.toString() == "Referential<BottomLeft>" );
        REQUIRE( Referential::Bottom.toString() == "Referential<Bottom>" );
        REQUIRE( Referential::BottomRight.toString() == "Referential<BottomRight>" );
    }
    SECTION("Transforming known referentials to string with custom formatter")
    {
        REQUIRE( Referential::TopLeft.toString("A({})") == "A(TopLeft)" );
        REQUIRE( Referential::Top.toString("+{}") == "+Top" );
        REQUIRE( Referential::TopRight.toString("/{}/") == "/TopRight/" );
        REQUIRE( Referential::Left.toString("Why did you {} me") == "Why did you Left me" );
        REQUIRE( Referential::Center.toString("{} of the Earth") == "Center of the Earth" );
        REQUIRE( Referential::Right.toString("You were actually {}") == "You were actually Right" );
        REQUIRE( Referential::BottomLeft.toString("1+2={}") == "1+2=BottomLeft" );
        REQUIRE( Referential::Bottom.toString("Bikini {}") == "Bikini Bottom" );
        REQUIRE( Referential::BottomRight.toString("{0} == {0}") == "BottomRight == BottomRight" );
    }
    SECTION("Transforming random referentials to string with default formatter")
    {
        REQUIRE( Referential(0.123, 0.456).toString() == "Referential<0.123, 0.456>" );
        REQUIRE( Referential(0.6666, 0.9999).toString() == "Referential<0.6666, 0.9999>" );
    }
    SECTION("Transforming random referentials to string with custom formatter")
    {
        REQUIRE( Referential(0.9, 0.1).toString("{}") == "0.9, 0.1" );
        REQUIRE( Referential(0.1234, 0.5678).toString("Referential => {}") == "Referential => 0.1234, 0.5678" );
        REQUIRE( Referential(0.666, 1).toString("The devil is == {1}") == "The devil is == 0.666" );
        REQUIRE( Referential(0.1, 0.42).toString("I wonder why {2} is the answer") == "I wonder why 0.42 is the answer" );
        REQUIRE( Referential(0.456, 0.123).toString("y = {2}, x = {1}") == "y = 0.123, x = 0.456" );
    }
}

TEST_CASE(
    "We should be able to load a Referential from a string",
    "[obe.Transform.Referential.FromString]"
)
{
    SECTION("Loading known referentials from a string")
    {
        REQUIRE( Referential::FromString("TopLeft") == Referential::TopLeft );
        REQUIRE( Referential::FromString("Top") == Referential::Top );
        REQUIRE( Referential::FromString("TopRight") == Referential::TopRight );
        REQUIRE( Referential::FromString("Left") == Referential::Left );
        REQUIRE( Referential::FromString("Center") == Referential::Center );
        REQUIRE( Referential::FromString("Right") == Referential::Right );
        REQUIRE( Referential::FromString("BottomLeft") == Referential::BottomLeft );
        REQUIRE( Referential::FromString("Bottom") == Referential::Bottom );
        REQUIRE( Referential::FromString("BottomRight") == Referential::BottomRight );
    }
    SECTION("Loading random referentials from a string")
    {
        REQUIRE( Referential::FromString("Referential<0.1, 0.666>") == Referential(0.1, 0.666) );
        REQUIRE( Referential::FromString("Referential<-0.55, -1>") == Referential(-0.55, -1) );
        REQUIRE_THROWS( Referential::FromString("?") );
    }
}<commit_msg>Fixed Referential unit tests<commit_after>#include <catch/catch.hpp>

#include <Transform/Referential.hpp>

using namespace obe::Transform;
using Axis = Referential::Axis;

TEST_CASE(
    "Flipping Referentials should give correct results",
    "[obe.Transform.Referential.flip]"
)
{
    SECTION("Flipping both axis of known referentials")
    {
        REQUIRE( Referential::TopLeft.flip() == Referential::BottomRight );
        REQUIRE( Referential::Top.flip() == Referential::Bottom );
        REQUIRE( Referential::TopRight.flip() == Referential::BottomLeft );
        REQUIRE( Referential::Left.flip() == Referential::Right );
        REQUIRE( Referential::Center.flip() == Referential::Center );
        REQUIRE( Referential::Right.flip() == Referential::Left );
        REQUIRE( Referential::BottomLeft.flip() == Referential::TopRight );
        REQUIRE( Referential::Bottom.flip() == Referential::Top );
        REQUIRE( Referential::BottomRight.flip() == Referential::TopLeft );
    }
    SECTION("Flipping only horizontal axis of known referentials")
    {
        REQUIRE( Referential::TopLeft.flip(Axis::Horizontal) == Referential::TopRight );
        REQUIRE( Referential::Top.flip(Axis::Horizontal) == Referential::Top );
        REQUIRE( Referential::TopRight.flip(Axis::Horizontal) == Referential::TopLeft );
        REQUIRE( Referential::Left.flip(Axis::Horizontal) == Referential::Right );
        REQUIRE( Referential::Center.flip(Axis::Horizontal) == Referential::Center );
        REQUIRE( Referential::Right.flip(Axis::Horizontal) == Referential::Left );
        REQUIRE( Referential::BottomLeft.flip(Axis::Horizontal) == Referential::BottomRight );
        REQUIRE( Referential::Bottom.flip(Axis::Horizontal) == Referential::Bottom );
        REQUIRE( Referential::BottomRight.flip(Axis::Horizontal) == Referential::BottomLeft );
    }
    SECTION("Flipping only vertical axis of known referentials")
    {
        REQUIRE( Referential::TopLeft.flip(Axis::Vertical) == Referential::BottomLeft );
        REQUIRE( Referential::Top.flip(Axis::Vertical) == Referential::Bottom );
        REQUIRE( Referential::TopRight.flip(Axis::Vertical) == Referential::BottomRight );
        REQUIRE( Referential::Left.flip(Axis::Vertical) == Referential::Left );
        REQUIRE( Referential::Center.flip(Axis::Vertical) == Referential::Center );
        REQUIRE( Referential::Right.flip(Axis::Vertical) == Referential::Right );
        REQUIRE( Referential::BottomLeft.flip(Axis::Vertical) == Referential::TopLeft );
        REQUIRE( Referential::Bottom.flip(Axis::Vertical) == Referential::Top );
        REQUIRE( Referential::BottomRight.flip(Axis::Vertical) == Referential::TopRight );
    }
    SECTION("Flipping both axis of random referentials")
    {
        REQUIRE( Referential(0.1, 0.4).flip() == Referential(0.9, 0.6) );
        REQUIRE( Referential(0.4, 0.6).flip() == Referential(0.6, 0.4) );
        REQUIRE( Referential(0.2, 0.2).flip() == Referential(0.8, 0.8) );
        REQUIRE( Referential(0.3, 0.5).flip() == Referential(0.7, 0.5) );
    }
}

TEST_CASE(
    "We should be able to test the position of referentials based on criterias",
    "[obe.Transform.Referential.isOn...]"
)
{
    SECTION("Testing if known referentials are on a corner")
    {
        REQUIRE( Referential::TopLeft.isOnCorner() );
        REQUIRE( Referential::TopRight.isOnCorner() );
        REQUIRE( Referential::BottomLeft.isOnCorner() );
        REQUIRE( Referential::BottomRight.isOnCorner() );
        REQUIRE_FALSE( Referential::Top.isOnCorner() );
        REQUIRE_FALSE( Referential::Left.isOnCorner() );
        REQUIRE_FALSE( Referential::Center.isOnCorner() );
        REQUIRE_FALSE( Referential::Right.isOnCorner() );
        REQUIRE_FALSE( Referential::Bottom.isOnCorner() );
    }
    SECTION("Testing if known referentials are on a side")
    {
        REQUIRE_FALSE( Referential::TopLeft.isOnSide() );
        REQUIRE_FALSE( Referential::TopRight.isOnSide() );
        REQUIRE_FALSE( Referential::BottomLeft.isOnSide() );
        REQUIRE_FALSE( Referential::BottomRight.isOnSide() );
        REQUIRE( Referential::Top.isOnSide() );
        REQUIRE( Referential::Left.isOnSide() );
        REQUIRE_FALSE( Referential::Center.isOnSide() );
        REQUIRE( Referential::Right.isOnSide() );
        REQUIRE( Referential::Bottom.isOnSide() );
    }
    SECTION("Testing if known referentials are on the left")
    {
        REQUIRE( Referential::TopLeft.isOnLeftSide() );
        REQUIRE_FALSE( Referential::Top.isOnLeftSide() );
        REQUIRE_FALSE( Referential::TopRight.isOnLeftSide() );
        REQUIRE( Referential::Left.isOnLeftSide() );
        REQUIRE_FALSE( Referential::Center.isOnLeftSide() );
        REQUIRE_FALSE( Referential::Right.isOnLeftSide() );
        REQUIRE( Referential::BottomLeft.isOnLeftSide() );
        REQUIRE_FALSE( Referential::Bottom.isOnLeftSide() );
        REQUIRE_FALSE( Referential::BottomRight.isOnLeftSide() );
    }
    SECTION("Testing if known referentials are on the right")
    {
        REQUIRE_FALSE( Referential::TopLeft.isOnRightSide() );
        REQUIRE_FALSE( Referential::Top.isOnRightSide() );
        REQUIRE( Referential::TopRight.isOnRightSide() );
        REQUIRE_FALSE( Referential::Left.isOnRightSide() );
        REQUIRE_FALSE( Referential::Center.isOnRightSide() );
        REQUIRE( Referential::Right.isOnRightSide() );
        REQUIRE_FALSE( Referential::BottomLeft.isOnRightSide() );
        REQUIRE_FALSE( Referential::Bottom.isOnRightSide() );
        REQUIRE( Referential::BottomRight.isOnRightSide() );
    }
    SECTION("Testing if known referentials are on the top")
    {
        REQUIRE( Referential::TopLeft.isOnTopSide() );
        REQUIRE( Referential::Top.isOnTopSide() );
        REQUIRE( Referential::TopRight.isOnTopSide() );
        REQUIRE_FALSE( Referential::Left.isOnTopSide() );
        REQUIRE_FALSE( Referential::Center.isOnTopSide() );
        REQUIRE_FALSE( Referential::Right.isOnTopSide() );
        REQUIRE_FALSE( Referential::BottomLeft.isOnTopSide() );
        REQUIRE_FALSE( Referential::Bottom.isOnTopSide() );
        REQUIRE_FALSE( Referential::BottomRight.isOnTopSide() );
    }
    SECTION("Testing if known referentials are on the bottom")
    {
        REQUIRE_FALSE( Referential::TopLeft.isOnBottomSide() );
        REQUIRE_FALSE( Referential::Top.isOnBottomSide() );
        REQUIRE_FALSE( Referential::TopRight.isOnBottomSide() );
        REQUIRE_FALSE( Referential::Left.isOnBottomSide() );
        REQUIRE_FALSE( Referential::Center.isOnBottomSide() );
        REQUIRE_FALSE( Referential::Right.isOnBottomSide() );
        REQUIRE( Referential::BottomLeft.isOnBottomSide() );
        REQUIRE( Referential::Bottom.isOnBottomSide() );
        REQUIRE( Referential::BottomRight.isOnBottomSide() );
    }
    SECTION("Testing random referentials and their positions")
    {
        REQUIRE( Referential(1, 0.33).isOnRightSide() );
        REQUIRE( Referential(0, 0.66).isOnLeftSide() );
        REQUIRE( Referential(0.22, 1).isOnBottomSide() );
        REQUIRE( Referential(-0.11, 0).isOnTopSide() );
        REQUIRE( Referential(0.99, 1).isOnSide() );
        REQUIRE( Referential(0, 0).isOnCorner() );
        REQUIRE_FALSE( Referential(0.999, 0.33).isOnRightSide() );
        REQUIRE_FALSE( Referential(1, 0.66).isOnLeftSide() );
        REQUIRE_FALSE( Referential(0.22, 0).isOnBottomSide() );
        REQUIRE_FALSE( Referential(0.11, 1).isOnTopSide() );
        REQUIRE_FALSE( Referential(0.99, 0.99).isOnSide() );
        REQUIRE_FALSE( Referential(0.4, 0).isOnCorner() );
    }
}

TEST_CASE(
    "We should be able to represent a Referential as a string",
    "[obe.Transform.Referential.toString]"
)
{
    SECTION("Transforming known referentials to string with default formatter")
    {
        REQUIRE( Referential::TopLeft.toString() == "Referential<TopLeft>" );
        REQUIRE( Referential::Top.toString() == "Referential<Top>" );
        REQUIRE( Referential::TopRight.toString() == "Referential<TopRight>" );
        REQUIRE( Referential::Left.toString() == "Referential<Left>" );
        REQUIRE( Referential::Center.toString() == "Referential<Center>" );
        REQUIRE( Referential::Right.toString() == "Referential<Right>" );
        REQUIRE( Referential::BottomLeft.toString() == "Referential<BottomLeft>" );
        REQUIRE( Referential::Bottom.toString() == "Referential<Bottom>" );
        REQUIRE( Referential::BottomRight.toString() == "Referential<BottomRight>" );
    }
    SECTION("Transforming known referentials to string with custom formatter")
    {
        REQUIRE( Referential::TopLeft.toString("A({})") == "A(TopLeft)" );
        REQUIRE( Referential::Top.toString("+{}") == "+Top" );
        REQUIRE( Referential::TopRight.toString("/{}/") == "/TopRight/" );
        REQUIRE( Referential::Left.toString("Why did you {} me") == "Why did you Left me" );
        REQUIRE( Referential::Center.toString("{} of the Earth") == "Center of the Earth" );
        REQUIRE( Referential::Right.toString("You were actually {}") == "You were actually Right" );
        REQUIRE( Referential::BottomLeft.toString("1+2={}") == "1+2=BottomLeft" );
        REQUIRE( Referential::Bottom.toString("Bikini {}") == "Bikini Bottom" );
        REQUIRE( Referential::BottomRight.toString("{0} == {0}") == "BottomRight == BottomRight" );
    }
    SECTION("Transforming random referentials to string with default formatter")
    {
        REQUIRE( Referential(0.123, 0.456).toString() == "Referential<0.123, 0.456>" );
        REQUIRE( Referential(0.6666, 0.9999).toString() == "Referential<0.6666, 0.9999>" );
    }
    SECTION("Transforming random referentials to string with custom formatter")
    {
        REQUIRE( Referential(0.9, 0.1).toString("{}") == "0.9, 0.1" );
        REQUIRE( Referential(0.1234, 0.5678).toString("Referential => {}") == "Referential => 0.1234, 0.5678" );
        REQUIRE( Referential(0.666, 1).toString("The devil is == {1}") == "The devil is == 0.666" );
        REQUIRE( Referential(0.1, 0.42).toString("I wonder why {2} is the answer") == "I wonder why 0.42 is the answer" );
        REQUIRE( Referential(0.456, 0.123).toString("y = {2}, x = {1}") == "y = 0.123, x = 0.456" );
    }
}

TEST_CASE(
    "We should be able to load a Referential from a string",
    "[obe.Transform.Referential.FromString]"
)
{
    SECTION("Loading known referentials from a string")
    {
        REQUIRE( Referential::FromString("TopLeft") == Referential::TopLeft );
        REQUIRE( Referential::FromString("Top") == Referential::Top );
        REQUIRE( Referential::FromString("TopRight") == Referential::TopRight );
        REQUIRE( Referential::FromString("Left") == Referential::Left );
        REQUIRE( Referential::FromString("Center") == Referential::Center );
        REQUIRE( Referential::FromString("Right") == Referential::Right );
        REQUIRE( Referential::FromString("BottomLeft") == Referential::BottomLeft );
        REQUIRE( Referential::FromString("Bottom") == Referential::Bottom );
        REQUIRE( Referential::FromString("BottomRight") == Referential::BottomRight );
    }
    SECTION("Loading random referentials from a string")
    {
        REQUIRE( Referential::FromString("Referential<0.1, 0.666>") == Referential(0.1, 0.666) );
        REQUIRE( Referential::FromString("Referential<-0.55, -1>") == Referential(-0.55, -1) );
        REQUIRE_THROWS( Referential::FromString("?") );
    }
}<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
#include "condor_common.h"
#include "matchmaker.h"

// for daemon core
char *mySubSystem = "NEGOTIATOR";

// the matchmaker object
Matchmaker matchMaker;

int main_init (int, char *[])
{
	// read in params
	matchMaker.initialize ();
	return TRUE;
}

int main_shutdown_graceful()
{
	exit(0);
	return 0;
}

int main_shutdown_fast()
{
	exit(0);
	return 0;
}

int main_config ()
{
	return (matchMaker.reinitialize ());
}
<commit_msg>Call DC_Exit() instead of exit() to let DaemonCore cleanup itself.<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
#include "condor_common.h"
#include "matchmaker.h"

// for daemon core
char *mySubSystem = "NEGOTIATOR";

// the matchmaker object
Matchmaker matchMaker;

int main_init (int, char *[])
{
	// read in params
	matchMaker.initialize ();
	return TRUE;
}

int main_shutdown_graceful()
{
	DC_Exit(0);
	return 0;
}

int main_shutdown_fast()
{
	DC_Exit(0);
	return 0;
}

int main_config ()
{
	return (matchMaker.reinitialize ());
}
<|endoftext|>


<commit_before>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

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

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

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "interface/Interface.h"
#include "Version.h"

MIDI midi;
bool processingEnabled;

void init()
{
    board.init();
    database.init();
    sysEx.init();

    //use recursive parsing when merging is active
    if (database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureMergeEnabled))
        midi.setOneByteParseDINstate(false);
    else
        midi.setOneByteParseDINstate(true);

    midi.setDINvalidityCheckState(false);
    midi.setInputChannel(MIDI_CHANNEL_OMNI);
    midi.setNoteOffMode((noteOffType_t)database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureStandardNoteOff));
    midi.setRunningStatusState(database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureRunningStatus));
    midi.setChannelSendZeroStart(true);

    #if !defined(BOARD_A_MEGA) && !defined(BOARD_A_UNO)
    //uart is already init with 31250 baud rate, override with opendeck baud rate if necessarry
    if (database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureDINdoubleSpeed))
        board.initUART_MIDI(MIDI_BAUD_RATE_OD, true);

    board.ledFlashStartup(board.checkNewRevision());
    #endif

    //enable global interrupts
    sei();

    leds.init();

    #ifdef DISPLAY_SUPPORTED
    if (database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureEnable))
    {
        if (display.init((displayController_t)database.read(DB_BLOCK_DISPLAY, dbSection_display_hw, displayHwController), (displayResolution_t)database.read(DB_BLOCK_DISPLAY, dbSection_display_hw, displayHwResolution)))
        {
            display.setDirectWriteState(true);

            if (database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureWelcomeMsg))
                display.displayWelcomeMessage();

            if (database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureVInfoMsg))
                display.displayVinfo(false);

            display.setDirectWriteState(false);

            display.displayHome();
            display.setRetentionState(database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureMIDIeventRetention));
            display.setRetentionTime(database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureMIDIeventTime) * 1000);
        }
    }
    #endif

    processingEnabled = true;
}

int main()
{
    init();

    while(1)
    {
        #if defined(BOARD_A_LEO) || defined(BOARD_OPEN_DECK) || defined(BOARD_A_PRO_MICRO) || defined(BOARD_T_2PP)
        if (midi.read(usbInterface))
        {
            //new message on usb
            midiMessageType_t messageType = midi.getType(usbInterface);
            uint8_t data1 = midi.getData1(usbInterface);
            uint8_t data2 = midi.getData2(usbInterface);
            uint8_t channel = midi.getChannel(usbInterface);

            switch(messageType)
            {
                case midiMessageSystemExclusive:
                sysEx.handleMessage(midi.getSysExArray(usbInterface), midi.getSysExArrayLength(usbInterface));
                break;

                case midiMessageNoteOn:
                //we're using received note data to control LED color
                leds.noteToState(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageNoteOff:
                //always turn led off when note off is received
                leds.noteToState(data1, 0, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageControlChange:
                //control change is used to control led blinking
                leds.ccToBlink(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                #endif
                break;

                default:
                break;
            }
        }
        #endif

        #if !defined(BOARD_A_MEGA) && !defined(BOARD_A_UNO)
        if (database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureDinEnabled))
        {
            //check for incoming MIDI messages on USART
            if (!database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureMergeEnabled))
            {
                midi.read(dinInterface);
                midiMessageType_t messageType = midi.getType(dinInterface);
                uint8_t data1 = midi.getData1(dinInterface);
                uint8_t data2 = midi.getData2(dinInterface);
                uint8_t channel = midi.getChannel(dinInterface);

                switch(messageType)
                {
                    case midiMessageNoteOn:
                    //we're using received note data to control LED color
                    leds.noteToState(data1, data2, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                    #endif
                    break;

                    case midiMessageNoteOff:
                    //always turn led off when note off is received
                    leds.noteToState(data1, 0, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                    #endif
                    break;

                    case midiMessageControlChange:
                    //control change is used to control led blinking
                    leds.ccToBlink(data1, data2, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                    #endif
                    break;

                    default:
                    break;
                }
            }
            else
            {
                switch(database.read(DB_BLOCK_MIDI, dbSection_midi_merge, midiMergeToInterface))
                {
                    case midiMergeToInterfaceUSB:
                    //dump everything from MIDI in to USB MIDI out
                    midi.read(dinInterface, THRU_FULL_USB);
                    break;

                    case midiMergeToInterfaceDIN:
                    //dump everything from MIDI in to MIDI out
                    midi.read(dinInterface, THRU_FULL_DIN);
                    break;

                    case midiMergeToInterfaceAll:
                    //dump everything from MIDI in to USB MIDI out and MIDI out
                    midi.read(dinInterface, THRU_FULL_ALL);
                    break;

                    default:
                    break;
                }
            }
        }
        #endif

        #if defined(BOARD_A_MEGA) || defined(BOARD_A_UNO)
        //din interface here is actually translated usb traffic from 16u2
        if (midi.read(dinInterface))
        {
            midiMessageType_t messageType = midi.getType(dinInterface);
            uint8_t data1 = midi.getData1(dinInterface);
            uint8_t data2 = midi.getData2(dinInterface);
            uint8_t channel = midi.getChannel(dinInterface);

            switch(messageType)
            {
                case midiMessageSystemExclusive:
                sysEx.handleMessage(midi.getSysExArray(dinInterface), midi.getSysExArrayLength(dinInterface));
                break;

                case midiMessageNoteOn:
                //we're using received note data to control LED color
                leds.noteToState(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageNoteOff:
                //always turn led off when note off is received
                leds.noteToState(data1, 0, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageControlChange:
                //control change is used to control led blinking
                leds.ccToBlink(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                #endif
                break;

                default:
                break;
            }
        }
        #endif

        if (processingEnabled)
        {
            digitalInput.update();
            analog.update();
            leds.update();
        }

        #ifdef DISPLAY_SUPPORTED
        display.update();
        #endif
    }
}
<commit_msg>use recursive parsing on mega and uno<commit_after>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

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

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

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "interface/Interface.h"
#include "Version.h"

MIDI midi;
bool processingEnabled;

void init()
{
    board.init();
    database.init();
    sysEx.init();

    #if !defined(BOARD_MEGA) && !defined(BOARD_A_UNO)
    //use recursive parsing when merging is active
    if (database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureMergeEnabled))
        midi.setOneByteParseDINstate(false);
    else
        midi.setOneByteParseDINstate(true);
    #else
    midi.setOneByteParseDINstate(false);
    #endif

    midi.setDINvalidityCheckState(false);
    midi.setInputChannel(MIDI_CHANNEL_OMNI);
    midi.setNoteOffMode((noteOffType_t)database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureStandardNoteOff));
    midi.setRunningStatusState(database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureRunningStatus));
    midi.setChannelSendZeroStart(true);

    #if !defined(BOARD_A_MEGA) && !defined(BOARD_A_UNO)
    //uart is already init with 31250 baud rate, override with opendeck baud rate if necessarry
    if (database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureDINdoubleSpeed))
        board.initUART_MIDI(MIDI_BAUD_RATE_OD, true);

    board.ledFlashStartup(board.checkNewRevision());
    #endif

    //enable global interrupts
    sei();

    leds.init();

    #ifdef DISPLAY_SUPPORTED
    if (database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureEnable))
    {
        if (display.init((displayController_t)database.read(DB_BLOCK_DISPLAY, dbSection_display_hw, displayHwController), (displayResolution_t)database.read(DB_BLOCK_DISPLAY, dbSection_display_hw, displayHwResolution)))
        {
            display.setDirectWriteState(true);

            if (database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureWelcomeMsg))
                display.displayWelcomeMessage();

            if (database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureVInfoMsg))
                display.displayVinfo(false);

            display.setDirectWriteState(false);

            display.displayHome();
            display.setRetentionState(database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureMIDIeventRetention));
            display.setRetentionTime(database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureMIDIeventTime) * 1000);
        }
    }
    #endif

    processingEnabled = true;
}

int main()
{
    init();

    while(1)
    {
        #if defined(BOARD_A_LEO) || defined(BOARD_OPEN_DECK) || defined(BOARD_A_PRO_MICRO) || defined(BOARD_T_2PP)
        if (midi.read(usbInterface))
        {
            //new message on usb
            midiMessageType_t messageType = midi.getType(usbInterface);
            uint8_t data1 = midi.getData1(usbInterface);
            uint8_t data2 = midi.getData2(usbInterface);
            uint8_t channel = midi.getChannel(usbInterface);

            switch(messageType)
            {
                case midiMessageSystemExclusive:
                sysEx.handleMessage(midi.getSysExArray(usbInterface), midi.getSysExArrayLength(usbInterface));
                break;

                case midiMessageNoteOn:
                //we're using received note data to control LED color
                leds.noteToState(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageNoteOff:
                //always turn led off when note off is received
                leds.noteToState(data1, 0, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageControlChange:
                //control change is used to control led blinking
                leds.ccToBlink(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                #endif
                break;

                default:
                break;
            }
        }
        #endif

        #if !defined(BOARD_A_MEGA) && !defined(BOARD_A_UNO)
        if (database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureDinEnabled))
        {
            //check for incoming MIDI messages on USART
            if (!database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureMergeEnabled))
            {
                midi.read(dinInterface);
                midiMessageType_t messageType = midi.getType(dinInterface);
                uint8_t data1 = midi.getData1(dinInterface);
                uint8_t data2 = midi.getData2(dinInterface);
                uint8_t channel = midi.getChannel(dinInterface);

                switch(messageType)
                {
                    case midiMessageNoteOn:
                    //we're using received note data to control LED color
                    leds.noteToState(data1, data2, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                    #endif
                    break;

                    case midiMessageNoteOff:
                    //always turn led off when note off is received
                    leds.noteToState(data1, 0, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                    #endif
                    break;

                    case midiMessageControlChange:
                    //control change is used to control led blinking
                    leds.ccToBlink(data1, data2, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                    #endif
                    break;

                    default:
                    break;
                }
            }
            else
            {
                switch(database.read(DB_BLOCK_MIDI, dbSection_midi_merge, midiMergeToInterface))
                {
                    case midiMergeToInterfaceUSB:
                    //dump everything from MIDI in to USB MIDI out
                    midi.read(dinInterface, THRU_FULL_USB);
                    break;

                    case midiMergeToInterfaceDIN:
                    //dump everything from MIDI in to MIDI out
                    midi.read(dinInterface, THRU_FULL_DIN);
                    break;

                    case midiMergeToInterfaceAll:
                    //dump everything from MIDI in to USB MIDI out and MIDI out
                    midi.read(dinInterface, THRU_FULL_ALL);
                    break;

                    default:
                    break;
                }
            }
        }
        #endif

        #if defined(BOARD_A_MEGA) || defined(BOARD_A_UNO)
        //din interface here is actually translated usb traffic from 16u2
        if (midi.read(dinInterface))
        {
            midiMessageType_t messageType = midi.getType(dinInterface);
            uint8_t data1 = midi.getData1(dinInterface);
            uint8_t data2 = midi.getData2(dinInterface);
            uint8_t channel = midi.getChannel(dinInterface);

            switch(messageType)
            {
                case midiMessageSystemExclusive:
                sysEx.handleMessage(midi.getSysExArray(dinInterface), midi.getSysExArrayLength(dinInterface));
                break;

                case midiMessageNoteOn:
                //we're using received note data to control LED color
                leds.noteToState(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageNoteOff:
                //always turn led off when note off is received
                leds.noteToState(data1, 0, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageControlChange:
                //control change is used to control led blinking
                leds.ccToBlink(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                #endif
                break;

                default:
                break;
            }
        }
        #endif

        if (processingEnabled)
        {
            digitalInput.update();
            analog.update();
            leds.update();
        }

        #ifdef DISPLAY_SUPPORTED
        display.update();
        #endif
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: unomain.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 03:38:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <stdio.h>

#include "unomain.hxx"

#include <sal/main.h>

#include <com/sun/star/lang/XComponent.hpp>
#include <cppuhelper/bootstrap.hxx>

#include <rtl/string.hxx>

#include <rtl/process.h>
#include <osl/thread.h>
#include <osl/file.h>

namespace uno = ::com::sun::star::uno;

namespace
{
    struct AutoDispose
    {
        typedef uno::Reference< ::com::sun::star::lang::XComponent > Component;
        AutoDispose()
        : component()
        {}

        ~AutoDispose()
        {
            if (component.is())
                component->dispose();
        }

        void set( Component const & xComp )
        {
            component = xComp;
        }
        void set( uno::BaseReference const & xComp )
        {
            component.set(xComp,uno::UNO_QUERY);
        }

        Component component;
    };
}

::rtl::OUString SAL_CALL unoapp::getAppCommandURL()
{
    rtl::OUString aURL;
    OSL_VERIFY( osl_Process_E_None == osl_getExecutableFile(&aURL.pData) );
    return aURL;
}

::rtl::OUString SAL_CALL unoapp::getAppCommandPath()
{
    rtl::OUString const aURL = getAppCommandURL();

    rtl::OUString aPath;
    OSL_VERIFY( osl_File_E_None == osl_getSystemPathFromFileURL(aURL.pData,&aPath.pData) );

    return aPath;
}

::rtl::OUString SAL_CALL unoapp::getAppCommandName()
{
    rtl::OUString aURL = getAppCommandURL();

    sal_Int32 const nNameIndex = aURL.lastIndexOf( sal_Unicode('/') );

    return aURL.copy(nNameIndex+1);
}

uno::Sequence< ::rtl::OUString > SAL_CALL unoapp::getAppCommandArgs()
{
    sal_uInt32 const count = rtl_getAppCommandArgCount();

    uno::Sequence< ::rtl::OUString > aResult( count );
    ::rtl::OUString * pResult = aResult.getArray();

    for (sal_uInt32 i = 0; i < count; ++i)
    {
        rtl_getAppCommandArg( i, & pResult[i].pData);
    }

    return aResult;
}

bool unoapp::g_bQuiet = false;

SAL_IMPLEMENT_MAIN()
{
    AutoDispose aDisposer;
    try
    {
        uno::Reference< uno::XComponentContext > xUnoContext = cppu::defaultBootstrap_InitialComponentContext();

        aDisposer.component.set( xUnoContext, uno::UNO_QUERY );

        return unoapp::uno_main(xUnoContext);
    }
    catch (uno::Exception & e)
    {
        using namespace rtl;
        OString sApp = OUStringToOString( unoapp::getAppCommandName(), osl_getThreadTextEncoding() );
        OString sMessage = OUStringToOString( e.Message, osl_getThreadTextEncoding() );

        if (!unoapp::g_bQuiet)
            fprintf( stderr, "%s - Unhandled exception caught in main: \"%s\"\n", sApp.getStr(), sMessage.getStr() );

        return 42;
    }
}

<commit_msg>INTEGRATION: CWS warnings01 (1.3.4); FILE MERGED 2005/11/01 12:47:17 cd 1.3.4.1: #i53898# Warning free code for sun solaris compiler<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: unomain.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 23:21:55 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <stdio.h>

#include "unomain.hxx"

#include <sal/main.h>

#include <com/sun/star/lang/XComponent.hpp>
#include <cppuhelper/bootstrap.hxx>

#include <rtl/string.hxx>

#include <rtl/process.h>
#include <osl/thread.h>
#include <osl/file.h>

namespace uno = ::com::sun::star::uno;

namespace
{
    struct AutoDispose
    {
        typedef uno::Reference< ::com::sun::star::lang::XComponent > Component;
        AutoDispose()
        : component()
        {}

        ~AutoDispose()
        {
            if (component.is())
                component->dispose();
        }

        void set( Component const & xComp )
        {
            component = xComp;
        }
        void set( uno::BaseReference const & xComp )
        {
            component.set(xComp,uno::UNO_QUERY);
        }

        Component component;
    };
}

::rtl::OUString SAL_CALL unoapp::getAppCommandURL()
{
    rtl::OUString aURL;
    OSL_VERIFY( osl_Process_E_None == osl_getExecutableFile(&aURL.pData) );
    return aURL;
}

::rtl::OUString SAL_CALL unoapp::getAppCommandPath()
{
    rtl::OUString const aURL = getAppCommandURL();

    rtl::OUString aPath;
    OSL_VERIFY( osl_File_E_None == osl_getSystemPathFromFileURL(aURL.pData,&aPath.pData) );

    return aPath;
}

::rtl::OUString SAL_CALL unoapp::getAppCommandName()
{
    rtl::OUString aURL = getAppCommandURL();

    sal_Int32 const nNameIndex = aURL.lastIndexOf( sal_Unicode('/') );

    return aURL.copy(nNameIndex+1);
}

uno::Sequence< ::rtl::OUString > SAL_CALL unoapp::getAppCommandArgs()
{
    sal_uInt32 const count = rtl_getAppCommandArgCount();

    uno::Sequence< ::rtl::OUString > aResult( count );
    ::rtl::OUString * pResult = aResult.getArray();

    for (sal_uInt32 i = 0; i < count; ++i)
    {
        rtl_getAppCommandArg( i, & pResult[i].pData);
    }

    return aResult;
}

bool unoapp::g_bQuiet = false;

SAL_IMPLEMENT_MAIN()
{
    { (void)argc; (void)argv; }

    AutoDispose aDisposer;
    try
    {
        uno::Reference< uno::XComponentContext > xUnoContext = cppu::defaultBootstrap_InitialComponentContext();

        aDisposer.component.set( xUnoContext, uno::UNO_QUERY );

        return unoapp::uno_main(xUnoContext);
    }
    catch (uno::Exception & e)
    {
        using namespace rtl;
        OString sApp = OUStringToOString( unoapp::getAppCommandName(), osl_getThreadTextEncoding() );
        OString sMessage = OUStringToOString( e.Message, osl_getThreadTextEncoding() );

        if (!unoapp::g_bQuiet)
            fprintf( stderr, "%s - Unhandled exception caught in main: \"%s\"\n", sApp.getStr(), sMessage.getStr() );

        return 42;
    }
}

<|endoftext|>


<commit_before>//===- LoopVersioning.cpp - Utility to version a loop ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a utility class to perform loop versioning.  The versioned
// loop speculates that otherwise may-aliasing memory accesses don't overlap and
// emits checks to prove this.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/LoopAccessAnalysis.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/LoopVersioning.h"

using namespace llvm;

LoopVersioning::LoopVersioning(
    SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks,
    const LoopAccessInfo &LAI, Loop *L, LoopInfo *LI, DominatorTree *DT)
    : VersionedLoop(L), NonVersionedLoop(nullptr), Checks(std::move(Checks)),
      LAI(LAI), LI(LI), DT(DT) {
  assert(L->getExitBlock() && "No single exit block");
  assert(L->getLoopPreheader() && "No preheader");
}

LoopVersioning::LoopVersioning(const LoopAccessInfo &LAInfo, Loop *L,
                               LoopInfo *LI, DominatorTree *DT)
    : VersionedLoop(L), NonVersionedLoop(nullptr),
      Checks(LAInfo.getRuntimePointerChecking()->getChecks()), LAI(LAInfo),
      LI(LI), DT(DT) {
  assert(L->getExitBlock() && "No single exit block");
  assert(L->getLoopPreheader() && "No preheader");
}

void LoopVersioning::versionLoop(
    const SmallVectorImpl<Instruction *> &DefsUsedOutside) {
  Instruction *FirstCheckInst;
  Instruction *MemRuntimeCheck;
  // Add the memcheck in the original preheader (this is empty initially).
  BasicBlock *MemCheckBB = VersionedLoop->getLoopPreheader();
  std::tie(FirstCheckInst, MemRuntimeCheck) =
      LAI.addRuntimeChecks(MemCheckBB->getTerminator(), Checks);
  assert(MemRuntimeCheck && "called even though needsAnyChecking = false");

  // Rename the block to make the IR more readable.
  MemCheckBB->setName(VersionedLoop->getHeader()->getName() + ".lver.memcheck");

  // Create empty preheader for the loop (and after cloning for the
  // non-versioned loop).
  BasicBlock *PH = SplitBlock(MemCheckBB, MemCheckBB->getTerminator(), DT, LI);
  PH->setName(VersionedLoop->getHeader()->getName() + ".ph");

  // Clone the loop including the preheader.
  //
  // FIXME: This does not currently preserve SimplifyLoop because the exit
  // block is a join between the two loops.
  SmallVector<BasicBlock *, 8> NonVersionedLoopBlocks;
  NonVersionedLoop =
      cloneLoopWithPreheader(PH, MemCheckBB, VersionedLoop, VMap, ".lver.orig",
                             LI, DT, NonVersionedLoopBlocks);
  remapInstructionsInBlocks(NonVersionedLoopBlocks, VMap);

  // Insert the conditional branch based on the result of the memchecks.
  Instruction *OrigTerm = MemCheckBB->getTerminator();
  BranchInst::Create(NonVersionedLoop->getLoopPreheader(),
                     VersionedLoop->getLoopPreheader(), MemRuntimeCheck,
                     OrigTerm);
  OrigTerm->eraseFromParent();

  // The loops merge in the original exit block.  This is now dominated by the
  // memchecking block.
  DT->changeImmediateDominator(VersionedLoop->getExitBlock(), MemCheckBB);

  // Adds the necessary PHI nodes for the versioned loops based on the
  // loop-defined values used outside of the loop.
  addPHINodes(DefsUsedOutside);
}

void LoopVersioning::addPHINodes(
    const SmallVectorImpl<Instruction *> &DefsUsedOutside) {
  BasicBlock *PHIBlock = VersionedLoop->getExitBlock();
  assert(PHIBlock && "No single successor to loop exit block");

  for (auto *Inst : DefsUsedOutside) {
    auto *NonVersionedLoopInst = cast<Instruction>(VMap[Inst]);
    PHINode *PN;

    // First see if we have a single-operand PHI with the value defined by the
    // original loop.
    for (auto I = PHIBlock->begin(); (PN = dyn_cast<PHINode>(I)); ++I) {
      assert(PN->getNumOperands() == 1 &&
             "Exit block should only have on predecessor");
      if (PN->getIncomingValue(0) == Inst)
        break;
    }
    // If not create it.
    if (!PN) {
      PN = PHINode::Create(Inst->getType(), 2, Inst->getName() + ".lver",
                           &PHIBlock->front());
      for (auto *User : Inst->users())
        if (!VersionedLoop->contains(cast<Instruction>(User)->getParent()))
          User->replaceUsesOfWith(Inst, PN);
      PN->addIncoming(Inst, VersionedLoop->getExitingBlock());
    }
    // Add the new incoming value from the non-versioned loop.
    PN->addIncoming(NonVersionedLoopInst, NonVersionedLoop->getExitingBlock());
  }
}
<commit_msg>Move the canonical header to the top of its matching cpp file as per coding convention<commit_after>//===- LoopVersioning.cpp - Utility to version a loop ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a utility class to perform loop versioning.  The versioned
// loop speculates that otherwise may-aliasing memory accesses don't overlap and
// emits checks to prove this.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/LoopVersioning.h"

#include "llvm/Analysis/LoopAccessAnalysis.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"

using namespace llvm;

LoopVersioning::LoopVersioning(
    SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks,
    const LoopAccessInfo &LAI, Loop *L, LoopInfo *LI, DominatorTree *DT)
    : VersionedLoop(L), NonVersionedLoop(nullptr), Checks(std::move(Checks)),
      LAI(LAI), LI(LI), DT(DT) {
  assert(L->getExitBlock() && "No single exit block");
  assert(L->getLoopPreheader() && "No preheader");
}

LoopVersioning::LoopVersioning(const LoopAccessInfo &LAInfo, Loop *L,
                               LoopInfo *LI, DominatorTree *DT)
    : VersionedLoop(L), NonVersionedLoop(nullptr),
      Checks(LAInfo.getRuntimePointerChecking()->getChecks()), LAI(LAInfo),
      LI(LI), DT(DT) {
  assert(L->getExitBlock() && "No single exit block");
  assert(L->getLoopPreheader() && "No preheader");
}

void LoopVersioning::versionLoop(
    const SmallVectorImpl<Instruction *> &DefsUsedOutside) {
  Instruction *FirstCheckInst;
  Instruction *MemRuntimeCheck;
  // Add the memcheck in the original preheader (this is empty initially).
  BasicBlock *MemCheckBB = VersionedLoop->getLoopPreheader();
  std::tie(FirstCheckInst, MemRuntimeCheck) =
      LAI.addRuntimeChecks(MemCheckBB->getTerminator(), Checks);
  assert(MemRuntimeCheck && "called even though needsAnyChecking = false");

  // Rename the block to make the IR more readable.
  MemCheckBB->setName(VersionedLoop->getHeader()->getName() + ".lver.memcheck");

  // Create empty preheader for the loop (and after cloning for the
  // non-versioned loop).
  BasicBlock *PH = SplitBlock(MemCheckBB, MemCheckBB->getTerminator(), DT, LI);
  PH->setName(VersionedLoop->getHeader()->getName() + ".ph");

  // Clone the loop including the preheader.
  //
  // FIXME: This does not currently preserve SimplifyLoop because the exit
  // block is a join between the two loops.
  SmallVector<BasicBlock *, 8> NonVersionedLoopBlocks;
  NonVersionedLoop =
      cloneLoopWithPreheader(PH, MemCheckBB, VersionedLoop, VMap, ".lver.orig",
                             LI, DT, NonVersionedLoopBlocks);
  remapInstructionsInBlocks(NonVersionedLoopBlocks, VMap);

  // Insert the conditional branch based on the result of the memchecks.
  Instruction *OrigTerm = MemCheckBB->getTerminator();
  BranchInst::Create(NonVersionedLoop->getLoopPreheader(),
                     VersionedLoop->getLoopPreheader(), MemRuntimeCheck,
                     OrigTerm);
  OrigTerm->eraseFromParent();

  // The loops merge in the original exit block.  This is now dominated by the
  // memchecking block.
  DT->changeImmediateDominator(VersionedLoop->getExitBlock(), MemCheckBB);

  // Adds the necessary PHI nodes for the versioned loops based on the
  // loop-defined values used outside of the loop.
  addPHINodes(DefsUsedOutside);
}

void LoopVersioning::addPHINodes(
    const SmallVectorImpl<Instruction *> &DefsUsedOutside) {
  BasicBlock *PHIBlock = VersionedLoop->getExitBlock();
  assert(PHIBlock && "No single successor to loop exit block");

  for (auto *Inst : DefsUsedOutside) {
    auto *NonVersionedLoopInst = cast<Instruction>(VMap[Inst]);
    PHINode *PN;

    // First see if we have a single-operand PHI with the value defined by the
    // original loop.
    for (auto I = PHIBlock->begin(); (PN = dyn_cast<PHINode>(I)); ++I) {
      assert(PN->getNumOperands() == 1 &&
             "Exit block should only have on predecessor");
      if (PN->getIncomingValue(0) == Inst)
        break;
    }
    // If not create it.
    if (!PN) {
      PN = PHINode::Create(Inst->getType(), 2, Inst->getName() + ".lver",
                           &PHIBlock->front());
      for (auto *User : Inst->users())
        if (!VersionedLoop->contains(cast<Instruction>(User)->getParent()))
          User->replaceUsesOfWith(Inst, PN);
      PN->addIncoming(Inst, VersionedLoop->getExitingBlock());
    }
    // Add the new incoming value from the non-versioned loop.
    PN->addIncoming(NonVersionedLoopInst, NonVersionedLoop->getExitingBlock());
  }
}
<|endoftext|>