text:
//               Copyright Ross MacGregor 2013
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#pragma once

#include <vector>
#include <set>
#include <limits>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

#include "AsioExpressError/Check.hpp"
#include "AsioExpressError/CallStack.hpp"
#include "AsioExpress/CompletionHandler.hpp"
#include "AsioExpress/ErrorCodes.hpp"
#include "AsioExpress/Timer/Timer.hpp"

#undef max

namespace AsioExpress {

///
/// This is a basic event synchronization primitive for ASIO applications.
/// The EventQueue allows you to decouple the event processor from the async
/// processes generating the events. The queue accepts a maximum size parameter
/// that will block the completion of AsyncAdd to prevent the event queue from
/// getting unreasonably large and providing feedback to the rest of the
/// system.
///

template<typename E>
class EventQueue
{
public:
  typedef E Event;
  typedef boost::shared_ptr<Event> EventPointer;
  typedef size_t SizeType;

  EventQueue() :
    m_isShutDown(false),
    m_maxSize(std::numeric_limits<SizeType>::max())
  {
  }

  EventQueue(SizeType size) :
    m_isShutDown(false),
    m_maxSize(size)
  {
      CHECK(size > 0);
  }

  ~EventQueue()
  {
  }

  ///
  /// Get the next event from the event queue. If no events are queued the
  /// async call waits for a new event to be added to the queue.
  ///
  /// @param event              The event data that will be received by the
  ///                           caller.
  /// @param waitTimer          A timer to indicate how long to wait to receive
  ///                           the event.
  /// @param completionHandler  The completion hander is called when the event
  ///                           is received, the wait time expires, or an error
  ///                           occurs.
  void AsyncWait(
      EventPointer const & event,
      TimerPointer const & waitTimer,
      CompletionHandler completionHandler);

  ///
  /// This method adds an event to the event queue.
  ///
  /// @param event              The event data that will be received by the
  ///                           caller.
  /// @param completionHandler  The completion hander is called when the event
  ///                           is queued or the queue has been canceled.
  ///
  void AsyncAdd(
      Event const & event,
      CompletionHandler completionHandler);

  ///
  /// This method cancels all pending operations on the event queue.
  ///
  void Cancel();

  ///
  /// This method cancels all pending operations on the event queue. If
  /// AsyncWait or AsyncAdd is called on a queue that has been shut down,
  /// an operation-aborted error is returned immediately.
  ///
  void ShutDown();

private:
  void Timeout(
      Error error,
      TimerPointer timer);

  struct EventHandler
  {
    EventHandler(
        EventPointer const & event,
        CompletionHandler const & completionHandler,
        TimerPointer const & waitTimer) :
      event(event),
      completionHandler(completionHandler),
      timer(waitTimer)
    {
    }
    EventPointer        event;
    CompletionHandler   completionHandler;
    TimerPointer        timer;
  };

  struct WaitingEvent
  {
    WaitingEvent(
        Event const & event,
        CompletionHandler const & completionHandler) :
      waitingEvent(event),
      completionHandler(completionHandler)
    {
    }
    Event               waitingEvent;
    CompletionHandler   completionHandler;
  };

  typedef std::vector<EventHandler> EventHandlerList;
  typedef std::vector<Event> RegisteredEvents;
  typedef std::vector<WaitingEvent> WaitingEvents;

  EventHandlerList      m_waitingEventHandlers;
  RegisteredEvents      m_registeredEvents;
  WaitingEvents         m_waitingEvents;
  bool                  m_isShutDown;
  SizeType              m_maxSize;
};

template<typename Event>
void EventQueue<Event>::AsyncWait(
      EventPointer const & event,
      TimerPointer const & waitTimer,
      CompletionHandler completionHandler)
{
  // If the queue has been canceled return operation aborted immediately.
  if ( m_isShutDown )
  {
    completionHandler(Error(boost::asio::error::operation_aborted));
    return;
  }

  // Verify that we have a unique event and timer pointer.
  {
    typename EventHandlerList::iterator  it = m_waitingEventHandlers.begin();
    typename EventHandlerList::iterator end = m_waitingEventHandlers.end();
    for (; it != end; ++it)
    {
      CHECK_MSG(it->event != event, "Outstanding wait for this event pointer in call to EventQueue::AsyncWait.");
      CHECK_MSG(it->timer != waitTimer, "Outstanding wait for this timer in call to EventQueue::AsyncWait.");
    }
  }

  // Look up waiting event.
  if (! m_registeredEvents.empty())
  {
    typename RegisteredEvents::iterator  it = m_registeredEvents.begin();
    *event = *it;
    m_registeredEvents.erase(it);
    completionHandler(Error());

    // move waiting event to registered event
    if (! m_waitingEvents.empty())
    {
      typename WaitingEvents::iterator it = m_waitingEvents.begin();
      m_registeredEvents.push_back(it->waitingEvent);
      CompletionHandler handler(it->completionHandler);
      m_waitingEvents.erase(it);
      handler(Error());
    }
    return;
  }

  // Queue this event to be handled.
  //
  waitTimer->AsyncWait(boost::bind(&EventQueue::Timeout, this, _1, waitTimer));

  m_waitingEventHandlers.push_back(
    EventHandler(event, completionHandler, waitTimer));
}

template<typename Event>
void EventQueue<Event>::AsyncAdd(
      Event const & event,
      CompletionHandler completionHandler)
{
  // If the queue has been canceled return operation aborted immediately.
  if ( m_isShutDown )
  {
    completionHandler(Error(boost::asio::error::operation_aborted));
    return;
  }

  if(! m_waitingEventHandlers.empty())
  {
    // Look up waiting handler.
    typename EventHandlerList::iterator  it = m_waitingEventHandlers.begin();
    *(it->event) = event;
    TimerPointer timer = it->timer;
    CompletionHandler handler(it->completionHandler);
    m_waitingEventHandlers.erase(it);
    timer->Stop();
    handler(Error());
    completionHandler(Error());
    return;
  }

  if (m_registeredEvents.size() >= m_maxSize)
  {
      // Add event and this completion hander to the following queue.
      m_waitingEvents.push_back(WaitingEvent(event,completionHandler));
      return;
  }

  // No handler found so we put it in the event queue.
  m_registeredEvents.push_back(event);
  completionHandler(Error());
}

template<typename Event>
void EventQueue<Event>::Cancel()
{
  // Look up waiting handler.
  typename EventHandlerList::iterator  it = m_waitingEventHandlers.begin();
  typename EventHandlerList::iterator end = m_waitingEventHandlers.end();
  for (; it != end; ++it)
  {
    it->timer->Stop();
  }
}

template<typename Event>
void EventQueue<Event>::ShutDown()
{
  // Indicate that this queue is canceled.
  m_isShutDown = true;

  Cancel();
}

template<typename Event>
void EventQueue<Event>::Timeout(
    Error error,
    TimerPointer timer)
{
  // Convert to timeout error if timer has expired.
  if (!error)
    error = Error(ErrorCode::EventQueueTimeout);

  typename EventHandlerList::iterator  it = m_waitingEventHandlers.begin();
  typename EventHandlerList::iterator end = m_waitingEventHandlers.end();
  for (; it != end; ++it)
  {
    if (it->timer == timer)
    {
      CompletionHandler handler(it->completionHandler);
      m_waitingEventHandlers.erase(it);
      handler(error);
      break;
    }
  }
}

} // namespace AsioExpress

max_stars_repo_name: suhao/asioexpress

max_issues_repo_name: suhao/asioexpress

max_forks_repo_name: suhao/asioexpress


text:
/*
 * Copyright 1993-2009 NVIDIA Corporation.  All rights reserved.
 *
 * NVIDIA Corporation and its licensors retain all intellectual property and
 * proprietary rights in and to this software and related documentation.
 * Any use, reproduction, disclosure, or distribution of this software
 * and related documentation without an express license agreement from
 * NVIDIA Corporation is strictly prohibited.
 *
 * Please refer to the applicable NVIDIA end user license agreement (EULA)
 * associated with this source code for terms and conditions that govern
 * your use of this NVIDIA software.
 *
 */

// *********************************************************************
// oclVectorAdd Notes:
//
// A simple OpenCL API demo application that implements
// element by element vector addition between 2 float arrays.
//
// Runs computations with OpenCL on the GPU device and then checks results
// against basic host CPU/C++ computation.
//
// Uses some 'shr' and 'ocl' functions from oclUtils and shrUtils libraries for
// compactness, but these are NOT required libs for OpenCL developement in general.
// *********************************************************************

#include "NEAT.h"

#include <boost/filesystem.hpp>
#include <boost/progress.hpp>
#include <boost/thread/xtime.hpp>

#ifdef __APPLE__
// common SDK header for standard utilities and system libs
#include <OpenCL/cl.h>
#else
// common SDK header for standard utilities and system libs
#include <CL/cl.h>
#include <CL/clext.h>
#endif

// Round Up Division function
size_t shrRoundUp(int group_size, int global_size)
{
    int r = global_size % group_size;
    if(r == 0)
    {
        return global_size;
    }
	else
    {
        return global_size + group_size - r;
    }
}

// Helper function to init data arrays
// *********************************************************************
void shrFillArray(float* pfData, int iSize)
{
    int i;
    const float fScale = 1.0f / (float)(RAND_MAX+1);
    for (i = 0; i < iSize; ++i)
    {
        pfData[i] = fScale * rand();
    }
}

// Helper function to check diffs between 2 same-sized result arrays and count/report the errors
// *********************************************************************
int shrDiffArray(const float* pfResult1, const float* pfResult2, int iNumElements)
{
    // sweep through arrays and count differences between test array and golden
    int iErrorCount = 0, i;
    for (i = 0; i < iNumElements; i++)
    {
        if (fabsf(pfResult2[i] - pfResult1[i]) > 1e-2)
        {
			cout << "Index (" << i << "): CPU: " << pfResult1[i] << " GPU: " << pfResult2[i] << endl;
            iErrorCount++;
        }
    }
    return iErrorCount;
}

//////////////////////////////////////////////////////////////////////////////
//! Loads a Program file and prepends the cPreamble to the code.
//!
//! @return the source string if succeeded, 0 otherwise
//! @param cFilename        program filename
//! @param cPreamble        code that is prepended to the loaded file, typically a set of #defines or a header
//! @param szFinalLength    returned length of the code string
//////////////////////////////////////////////////////////////////////////////
char* oclLoadProgSource(const char* cFilename, const char* cPreamble, size_t* szFinalLength)
{
    // locals
    FILE* pFileStream = NULL;
    size_t szSourceLength;

    // open the OpenCL source code file
    #ifdef _WIN32   // Windows version
        if(fopen_s(&pFileStream, cFilename, "rb") != 0)
        {
            return NULL;
        }
    #else           // Linux version
        pFileStream = fopen(cFilename, "rb");
        if(pFileStream == 0)
        {
            return NULL;
        }
    #endif

    size_t szPreambleLength = strlen(cPreamble);

    // get the length of the source code
    fseek(pFileStream, 0, SEEK_END);
    szSourceLength = ftell(pFileStream);
    fseek(pFileStream, 0, SEEK_SET);

    // allocate a buffer for the source code string and read it in
    char* cSourceString = (char *)malloc(szSourceLength + szPreambleLength + 1);
    memcpy(cSourceString, cPreamble, szPreambleLength);
    if (fread((cSourceString) + szPreambleLength, szSourceLength, 1, pFileStream) != 1)
    {
        fclose(pFileStream);
        free(cSourceString);
        return 0;
    }

    // close the file and return the total length of the combined (preamble + source) string
    fclose(pFileStream);
    if(szFinalLength != 0)
    {
        *szFinalLength = szSourceLength + szPreambleLength;
    }
    cSourceString[szSourceLength + szPreambleLength] = '\0';

    return cSourceString;
}

// Host buffers for demo
// *********************************************************************

// OpenCL Vars
cl_context cxGPUContext;        // OpenCL context
cl_command_queue cqCommandQue;  // OpenCL command que
cl_device_id* cdDevices;        // OpenCL device list
cl_program cpProgram;           // OpenCL program
cl_kernel ckKernel;             // OpenCL kernel
cl_mem cmNodeReverseAdjacencyList;               // OpenCL device source buffer A
cl_mem cmLinkWeightAdjacencyList;               // OpenCL device source buffer B
cl_mem cmCurrentNodeValues;                // OpenCL device destination buffer
cl_mem cmNewNodeValues;                // OpenCL device destination buffer
size_t szGlobalWorkSize;        // 1D var for Total # of work items
size_t szLocalWorkSize;		    // 1D var for # of work items in the work group
size_t szParmDataBytes;			// Byte size of context information
size_t szKernelLength;			// Byte size of kernel code
cl_int ciErr1, ciErr2;			// Error code var
string cPathAndName;      // var for full paths to data, src, etc.
char* cSourceCL = NULL;         // Buffer to hold source for compilation

// Forward Declarations
// *********************************************************************
void ANN(
		 cl_int** nodeReverseAdjacencyList,
		 cl_float** linkWeightAdjacencyList,
		 cl_float* currentNodeValues,
		 cl_float* newNodeValues,
		 int numNodes
		 );
void Cleanup (int iExitCode);

boost::filesystem::path BASE_EXE_DIRECTORY;

// Main function
// *********************************************************************
int main(int argc,char** argv)
{
	BASE_EXE_DIRECTORY = boost::filesystem::path(argv[0]).parent_path().parent_path();
#ifdef __APPLE__
	BASE_EXE_DIRECTORY = BASE_EXE_DIRECTORY.parent_path().parent_path().parent_path();
#endif

	int numNodes = 4096;

    // start logs
    //printf( "%s Starting...\n\n# of elements per Array \t= %i\n", argv[0], iNumElements);

    // set and log Global and Local work size dimensions
    szLocalWorkSize = 128;
    szGlobalWorkSize = 2048;
	int workGroupCount = (szGlobalWorkSize + (szLocalWorkSize-1))/szLocalWorkSize;

    //szGlobalWorkSize = shrRoundUp((int)szLocalWorkSize, numNodes);  // rounded up to the nearest multiple of the LocalWorkSize

    printf( "Global Work Size \t\t= %u\nLocal Work Size \t\t= %u\n# of Work Groups \t\t= %u\n\n",
           szGlobalWorkSize, szLocalWorkSize, (szGlobalWorkSize % szLocalWorkSize + szGlobalWorkSize/szLocalWorkSize));

    // Allocate and initialize host arrays
    printf(  "Allocate and Init Host Mem...\n");
	cl_int** nodeReverseAdjacencyList = (cl_int**)malloc(sizeof(cl_int*)*128);
	cl_int* nodeReverseAdjacencyListData = (cl_int*)malloc(sizeof(cl_int)*128*numNodes);
	for(int a=0;a<128;a++)
	{
		nodeReverseAdjacencyList[a] = &(nodeReverseAdjacencyListData[a*numNodes]);
	}
	for(int a=0;a<128;a++)
	{
		for(int b=0;b<numNodes;b++)
		{
			nodeReverseAdjacencyList[a][b]=-1;
		}
	}
	for(int a=0;a<64;a++)
	{
		for(int b=0;b<numNodes;b++)
		{
			//if(a>b)
			{
				nodeReverseAdjacencyList[a][b]=a;
			}
		}
	}

	cl_float** linkWeightAdjacencyList = (cl_float**)malloc(sizeof(cl_float*)*numNodes);
	cl_float* linkWeightAdjacencyListData = (cl_float*)malloc(sizeof(cl_float)*128*numNodes);
	for(int a=0;a<128;a++)
	{
		linkWeightAdjacencyList[a] = &(linkWeightAdjacencyListData[a*numNodes]);
	}
	for(int a=0;a<128;a++)
	{
		//shrFillArray(linkWeightAdjacencyList[a], numNodes);
		for(int b=0;b<numNodes;b++)
		{
			linkWeightAdjacencyList[a][b]=1.0;
		}
	}

	cl_float* currentNodeValues = (cl_float*)malloc(sizeof(cl_float)*numNodes);
	memset(currentNodeValues,0,sizeof(cl_float) * numNodes);
    //shrFillArray(currentNodeValues, numNodes);
	for(int b=0;b<numNodes;b++)
	{
		currentNodeValues[b]=1.0;
	}

	cl_float* newNodeValues = (cl_float*)malloc(sizeof(cl_float)*numNodes);
	memset(newNodeValues,0,sizeof(cl_float) * numNodes);

	cl_float* newNodeValuesGolden = (cl_float*)malloc(sizeof(cl_float)*numNodes);
	memset(newNodeValuesGolden,0,sizeof(cl_float) * numNodes);

	boost::xtime startTime,curTime;
    const int MILLISECONDS_PER_SECOND = 1000;
    const int NANOSECONDS_PER_SECOND = 1000000000;
    const int NANOSECONDS_PER_MILLISECOND = 1000000;

#if 1
	// Create the OpenCL context on a GPU device
    cxGPUContext = clCreateContextFromType(0, CL_DEVICE_TYPE_GPU, NULL, NULL, &ciErr1);
    printf( "clCreateContextFromType...\n");
    if (ciErr1 != CL_SUCCESS)
    {
        printf( "Error in clCreateContextFromType, Line %u in file %s !!!\n\n", __LINE__, __FILE__);
        Cleanup(EXIT_FAILURE);
    }

    // Get the list of GPU devices associated with context
    ciErr1 = clGetContextInfo(cxGPUContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes);
    cdDevices = (cl_device_id*)malloc(szParmDataBytes);
    ciErr1 |= clGetContextInfo(cxGPUContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL);
    printf( "clGetContextInfo...\n");
    if (ciErr1 != CL_SUCCESS)
    {
        printf( "Error in clGetContextInfo, Line %u in file %s !!!\n\n", __LINE__, __FILE__);
        Cleanup(EXIT_FAILURE);
    }

	for(int a=0;a<(szParmDataBytes/sizeof(cl_device_id));a++)
	{
		cl_uint numComputeUnits;
		clGetDeviceInfo(cdDevices[a],CL_DEVICE_MAX_COMPUTE_UNITS,4,&numComputeUnits,NULL);
		printf("NUM COMPUTE UNITS: %d\n",numComputeUnits);
	}

    // Create a command-queue
    cqCommandQue = clCreateCommandQueue(cxGPUContext, cdDevices[0], CL_QUEUE_PROFILING_ENABLE, &ciErr1);
    printf( "clCreateCommandQueue...\n");
    if (ciErr1 != CL_SUCCESS)
    {
        printf( "Error in clCreateCommandQueue, Line %u in file %s !!!\n\n", __LINE__, __FILE__);
        Cleanup(EXIT_FAILURE);
    }

	cl_uint numImageFormats;
	cl_image_format imageFormats[1024];
	clGetSupportedImageFormats(cxGPUContext,CL_MEM_READ_ONLY,CL_MEM_OBJECT_IMAGE2D,1024,imageFormats,&numImageFormats);

	for(int a=0;a<(int)numImageFormats;a++)
	{
		cout << imageFormats[a].image_channel_data_type << ", " << imageFormats[a].image_channel_order << endl;
	}

	/*
    // Allocate the OpenCL buffer memory objects for source and result on the device GMEM
	{
		cl_image_format format;
		format.image_channel_order = CL_RGBA;
		format.image_channel_data_type = CL_SIGNED_INT32;
		cmNodeReverseAdjacencyList = clCreateImage2D(cxGPUContext, CL_MEM_READ_ONLY, &format ,128/4,numNodes,0,NULL,&ciErr1);
	}
	{
		cl_image_format format;
		format.image_channel_order = CL_RGBA;
		format.image_channel_data_type = CL_FLOAT;
		cmLinkWeightAdjacencyList = clCreateImage2D(cxGPUContext, CL_MEM_READ_ONLY, &format ,128/4,numNodes,0,NULL, &ciErr2);
	}
    ciErr1 |= ciErr2;
	*/

    cmNodeReverseAdjacencyList = clCreateBuffer(cxGPUContext, CL_MEM_READ_ONLY, sizeof(cl_int) * numNodes * 128, NULL, &ciErr2);
    ciErr1 |= ciErr2;
    cmLinkWeightAdjacencyList = clCreateBuffer(cxGPUContext, CL_MEM_READ_ONLY, sizeof(cl_float) * numNodes * 128, NULL, &ciErr2);
    ciErr1 |= ciErr2;
    cmCurrentNodeValues = clCreateBuffer(cxGPUContext, CL_MEM_READ_ONLY, sizeof(cl_float) * numNodes, NULL, &ciErr2);
    ciErr1 |= ciErr2;
    cmNewNodeValues = clCreateBuffer(cxGPUContext, CL_MEM_WRITE_ONLY, sizeof(cl_float) * numNodes, NULL, &ciErr2);
    ciErr1 |= ciErr2;

    printf( "clCreateBuffer...\n");
    if (ciErr1 != CL_SUCCESS)
    {
        printf( "Error in clCreateBuffer, Line %u in file %s !!!\n\n", __LINE__, __FILE__);
        Cleanup(EXIT_FAILURE);
    }

    // Read the OpenCL kernel in from source file
    printf( "oclLoadProgSource (%s)...\n", (BASE_EXE_DIRECTORY / string("../out/OpenCL/ANN.cl")).string().c_str());
    cPathAndName = (BASE_EXE_DIRECTORY / string("../out/OpenCL/ANN.cl")).string();
    cSourceCL = oclLoadProgSource(cPathAndName.c_str(), "", &szKernelLength);

    // Create the program
    cpProgram = clCreateProgramWithSource(cxGPUContext, 1, (const char **)&cSourceCL, &szKernelLength, &ciErr1);
    printf( "clCreateProgramWithSource...\n");
    if (ciErr1 != CL_SUCCESS)
    {
        printf( "Error in clCreateProgramWithSource, Line %u in file %s !!!\n\n", __LINE__, __FILE__);
        Cleanup(EXIT_FAILURE);
    }

    // Build the program
    ciErr1 = clBuildProgram(cpProgram, 0, NULL, NULL, NULL, NULL);
    printf( "clBuildProgram...\n");
    if (ciErr1 != CL_SUCCESS)
    {
        printf( "Error in clBuildProgram, Line %u in file %s !!!\n\n", __LINE__, __FILE__);
		printf( "Error: %d\n",int(ciErr1));
        Cleanup(EXIT_FAILURE);
    }

    // Create the kernel
    ckKernel = clCreateKernel(cpProgram, "ANN", &ciErr1);
    printf( "clCreateKernel (ANN)...\n");
    if (ciErr1 != CL_SUCCESS)
    {
        printf( "Error in clCreateKernel, Line %u in file %s !!!\n\n", __LINE__, __FILE__);
        Cleanup(EXIT_FAILURE);
    }

    // --------------------------------------------------------
    // Start Core sequence... copy input data to GPU, compute, copy results back

    // Asynchronous write of data to GPU device
    //ciErr1 = clEnqueueWriteBuffer(cqCommandQue, cmDevSrcA, CL_TRUE, 0, sizeof(cl_float) * iNumElements, srcA, 0, NULL, NULL);
	size_t usedOrigin[3] = {0,0,0};
	size_t usedRegion[3] = {128/4,numNodes,1};
	ciErr1 = 0;
    //ciErr1 |= clEnqueueWriteImage(cqCommandQue, cmNodeReverseAdjacencyList, CL_TRUE, usedOrigin, usedRegion, 0, 0, nodeReverseAdjacencyListData, 0, NULL, NULL);
    //ciErr1 |= clEnqueueWriteImage(cqCommandQue, cmLinkWeightAdjacencyList, CL_TRUE, usedOrigin, usedRegion, 0, 0, linkWeightAdjacencyListData, 0, NULL, NULL);
    ciErr1 |= clEnqueueWriteBuffer(cqCommandQue, cmNodeReverseAdjacencyList, CL_TRUE, 0, sizeof(cl_int) * numNodes * 128, nodeReverseAdjacencyListData, 0, NULL, NULL);
    ciErr1 |= clEnqueueWriteBuffer(cqCommandQue, cmLinkWeightAdjacencyList, CL_TRUE, 0, sizeof(cl_float) * numNodes * 128, linkWeightAdjacencyListData, 0, NULL, NULL);
    ciErr1 |= clEnqueueWriteBuffer(cqCommandQue, cmCurrentNodeValues, CL_TRUE, 0, sizeof(cl_float) * numNodes, currentNodeValues, 0, NULL, NULL);
    printf( "clEnqueueWriteBuffer (SrcA and SrcB)...\n");
    if (ciErr1 != CL_SUCCESS)
    {
        printf( "Error in clEnqueueWriteBuffer, Line %u in file %s error %d !!!\n\n", __LINE__, __FILE__,ciErr1);
        Cleanup(EXIT_FAILURE);
    }

	clFinish(cqCommandQue);

	// Set the Argument values
	ciErr1 = clSetKernelArg(ckKernel, 0, sizeof(cl_mem), (void*)&cmNodeReverseAdjacencyList);
	ciErr1 |= clSetKernelArg(ckKernel, 1, sizeof(cl_mem), (void*)&cmLinkWeightAdjacencyList);
	ciErr1 |= clSetKernelArg(ckKernel, 2, sizeof(cl_mem), (void*)&cmCurrentNodeValues);
	ciErr1 |= clSetKernelArg(ckKernel, 3, sizeof(cl_mem), (void*)&cmNewNodeValues);
	ciErr1 |= clSetKernelArg(ckKernel, 4, sizeof(cl_int), (void*)&numNodes);
	ciErr1 |= clSetKernelArg(ckKernel, 5, sizeof(cl_float)*1, (void*)NULL);
	//printf( "clSetKernelArg 0 - 3...\n\n");
	if (ciErr1 != CL_SUCCESS)
	{
		printf( "Error in clSetKernelArg, Line %u in file %s !!!\n\n", __LINE__, __FILE__);
		Cleanup(EXIT_FAILURE);
	}

	clFinish(cqCommandQue);

	boost::xtime_get(&startTime, boost::TIME_UTC);
	{
		printf("LAUNCHING KERNEL\n");
		cl_ulong nanoSecondsSpentProcessing=0;
		cl_ulong start, end;
		cl_event execEvent;
		for(int a=0;a<500;a++)
		{
			// Launch kernel
			ciErr1 = clEnqueueNDRangeKernel(cqCommandQue, ckKernel, 1, NULL, &szGlobalWorkSize, &szLocalWorkSize, 0, NULL, &execEvent);

			//printf( "clEnqueueNDRangeKernel (ANN)...\n");
			if (ciErr1 != CL_SUCCESS)
			{
				printf( "Error in clEnqueueNDRangeKernel, Line %u in file %s (Error %d)!!!\n\n", __LINE__, __FILE__, ciErr1);
				Cleanup(EXIT_FAILURE);
			}

			clFinish(cqCommandQue);

			clGetEventProfilingInfo(execEvent, CL_PROFILING_COMMAND_END,
				sizeof(cl_ulong), &end, NULL);
			clGetEventProfilingInfo(execEvent, CL_PROFILING_COMMAND_START,
				sizeof(cl_ulong), &start, NULL);
			nanoSecondsSpentProcessing += (end - start);
		}
		boost::xtime_get(&curTime, boost::TIME_UTC);
		int msTimeDiff = int(nanoSecondsSpentProcessing / NANOSECONDS_PER_MILLISECOND);
			//(curTime.sec-startTime.sec)*MILLISECONDS_PER_SECOND +
			//(curTime.nsec-startTime.nsec)/NANOSECONDS_PER_MILLISECOND;
		cout << "Seconds to run: " << float(msTimeDiff)/1000.0 << endl;
	}

	// Synchronous/blocking read of results, and check accumulated errors
	ciErr1 = clEnqueueReadBuffer(cqCommandQue, cmNewNodeValues, CL_TRUE, 0, sizeof(cl_float) * numNodes, newNodeValues, 0, NULL, NULL);
	printf( "clEnqueueReadBuffer (Dst)...\n\n");
	if (ciErr1 != CL_SUCCESS)
	{
		printf("ERROR: %d\n",ciErr1);
		printf( "Error in clEnqueueReadBuffer, Line %u in file %s !!!\n\n", __LINE__, __FILE__);
		Cleanup(EXIT_FAILURE);
	}
#endif

    //--------------------------------------------------------

    // Compute and compare results for golden-host and report errors and pass/fail
    printf( "Comparing against Host/C++ computation...\n\n");
	boost::xtime_get(&startTime, boost::TIME_UTC);
	{
		ANN(nodeReverseAdjacencyList,linkWeightAdjacencyList,currentNodeValues,newNodeValuesGolden,numNodes);
		boost::xtime_get(&curTime, boost::TIME_UTC);
		int msTimeDiff =
			(curTime.sec-startTime.sec)*MILLISECONDS_PER_SECOND +
			(curTime.nsec-startTime.nsec)/NANOSECONDS_PER_MILLISECOND;
		cout << "Seconds to run: " << float(msTimeDiff)/1000.0 << endl;
	}
    int iNumErrors = shrDiffArray(newNodeValuesGolden, newNodeValues, numNodes);
    printf( "TEST %s\t (Error Count = %i)\n\n ", (iNumErrors == 0) ? "PASSED" : "FAILED !!!", iNumErrors);

    // Cleanup and leave
    Cleanup (EXIT_SUCCESS);
}

void Cleanup (int iExitCode)
{
    // Cleanup allocated objects
    printf( "Starting Cleanup...\n\n");
    if(cdDevices)free(cdDevices);
    if(cSourceCL)free(cSourceCL);
	if(ckKernel)clReleaseKernel(ckKernel);
    if(cpProgram)clReleaseProgram(cpProgram);
    if(cqCommandQue)clReleaseCommandQueue(cqCommandQue);
    if(cxGPUContext)clReleaseContext(cxGPUContext);
    if(cmNodeReverseAdjacencyList)clReleaseMemObject(cmNodeReverseAdjacencyList);
    if(cmLinkWeightAdjacencyList)clReleaseMemObject(cmLinkWeightAdjacencyList);
    if(cmCurrentNodeValues)clReleaseMemObject(cmCurrentNodeValues);
    if(cmNewNodeValues)clReleaseMemObject(cmNewNodeValues);

    // finalize logs and leave
    printf( "oclVectorAdd.exe Exiting...\nPress <Enter> to Quit\n");
    getchar();
    exit (iExitCode);
}

// "Golden" Host processing vector addition function for comparison purposes
// *********************************************************************
void ANN(
		 cl_int** nodeReverseAdjacencyList,
		 cl_float** linkWeightAdjacencyList,
		 cl_float* currentNodeValues,
		 cl_float* newNodeValues,
		 int numNodes
		 )
{
	for(int runCount=0;runCount<500;runCount++)
	{
		for(int currentToNode = 0; currentToNode < numNodes; currentToNode++)
		{
			// bound check (equivalent to the limit on a 'for' loop for standard/serial C code
			if (currentToNode >= numNodes)
			{
				return;
			}

			int currentFromNode = 0;

			float output = 0;
			for(currentFromNode=0 ; currentFromNode<numNodes ; currentFromNode++)
			{
				if(nodeReverseAdjacencyList[currentFromNode][currentToNode]<0)
					break;
				output += currentNodeValues[nodeReverseAdjacencyList[currentFromNode][currentToNode]] * linkWeightAdjacencyList[currentFromNode][currentToNode];
				//output += nodeReverseAdjacencyList[currentToNode][currentFromNode];
			}
			newNodeValues[currentToNode] = output;
		}
	}
}

ext: cpp

max_stars_repo_name: LMBernardo/HyperNEAT

max_issues_repo_name: LMBernardo/HyperNEAT

max_forks_repo_name: LMBernardo/HyperNEAT


text:
// Copyright (c)       2014 Martin Stumpf
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef MANDELBROT_PNG_WRITER_H_
#define MANDELBROT_PNG_WRITER_H_

#include <cstdlib>
#include <vector>
#include <memory>
#include <boost/shared_array.hpp>

// writes data to png file
void save_png(std::shared_ptr<std::vector<char> > data, size_t width,
              size_t height, const char* filename);

boost::shared_array<char> create_png(std::shared_ptr<std::vector<char> > data,
                                     size_t width, size_t height, size_t* size);

void png_write_to_file(boost::shared_array<char> png, size_t png_size,
                       const char* filename);

void save_pngi_it(std::shared_ptr<std::vector<char> > data, size_t width,
                  size_t height, size_t it);
#endif

ext: hpp

max_stars_repo_name: STEllAR-GROUP/hpxcl

max_issues_repo_name: STEllAR-GROUP/hpxcl

max_forks_repo_name: STEllAR-GROUP/hpxcl


text:
#include <boost/test/unit_test.hpp>

#include <smtrat-mcsat/explanations/vs/ExplanationGenerator.h>
#include <smtrat-common/smtrat-common.h>

using namespace smtrat;
using namespace mcsat::vs::helper;

BOOST_AUTO_TEST_SUITE(Test_ExplanationGenerator);

BOOST_AUTO_TEST_CASE(Test_generateZeros_eliminationVariableNotContained) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");

	ConstraintT c1(Poly(x)+Rational(1), carl::Relation::LEQ);
	bool result = generateZeros(c1, y, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
    	BOOST_CHECK(false);
    });
	BOOST_CHECK(result);
}
BOOST_AUTO_TEST_CASE(Test_generateZeros_degreeTooHigh) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");

	ConstraintT c1(Poly(y)*y*y+Rational(1), carl::Relation::LEQ);
	bool result = generateZeros(c1, y, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
    	BOOST_CHECK(false);
    });
	BOOST_CHECK(result == false);

	int zeros = 0;
	ConstraintT c2(Poly(y)*y*x, carl::Relation::LEQ);
	result = generateZeros(c2, y, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
    	zeros++;
    });
	BOOST_CHECK(result == true);
	BOOST_CHECK(zeros > 0);
}
BOOST_AUTO_TEST_CASE(Test_generateZeros_deg1) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");

	ConstraintT c1(Rational(0)*Poly(y), carl::Relation::LESS);
	bool result = generateZeros(c1, y, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
    	BOOST_CHECK(false);
    });
	BOOST_CHECK(result);

	ConstraintT c2(Poly(y)*x+Rational(1), carl::Relation::EQ);
	result = generateZeros(c2, y, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
    	BOOST_CHECK(sqrtExpression==SqrtEx(Poly(-1), Poly(0), Poly(x), Poly(0)));
		BOOST_CHECK(sideConditions.size() == 1);
		BOOST_CHECK(*sideConditions.begin() == ConstraintT(Poly(x), carl::Relation::NEQ));
    });
	BOOST_CHECK(result);
}
BOOST_AUTO_TEST_CASE(Test_generateZeros_deg2) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");

	ConstraintT c1(Poly(y)*y+Rational(1), carl::Relation::EQ);
	bool result = generateZeros(c1, y, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
    	BOOST_CHECK(false);
    });
	BOOST_CHECK(result);

	ConstraintT c2(Poly(y)*y+y+x, carl::Relation::EQ);
	int resultcount = 0;
	result = generateZeros(c2, y, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
		BOOST_CHECK(sqrtExpression==SqrtEx(Poly(Rational(-1)), Poly(1), Poly(Rational(2)), Poly(Rational(1))-Rational(4)*x) || sqrtExpression==SqrtEx(Poly(Rational(-1)), Poly(-1), Poly(Rational(2)), Poly(Rational(1))-Rational(4)*x));
		BOOST_CHECK(sideConditions.size() == 1);
		BOOST_CHECK(*sideConditions.begin() == ConstraintT(Poly(Rational(1))-Rational(4)*x, carl::Relation::GEQ));
		resultcount++;
    });
	BOOST_CHECK(resultcount == 2);
	BOOST_CHECK(result);
}

BOOST_AUTO_TEST_CASE(Test_generateZeros_VarComp_eliminationVariableNotContained) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");

	VariableComparisonT varcomp(x, MultivariateRootT(Poly(MultivariateRootT::var())+Rational(1), 1), carl::Relation::EQ);
	Model model;

	bool result = generateZeros(varcomp, y, model, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
    	BOOST_CHECK(false);
    });
	BOOST_CHECK(result);
}
BOOST_AUTO_TEST_CASE(Test_generateZeros_VarComp_MVRoot_degreeTooHigh) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
	VariableComparisonT varcomp(y, MultivariateRootT(Poly(MultivariateRootT::var())*MultivariateRootT::var()*MultivariateRootT::var()*x-Rational(1), 2), carl::Relation::EQ);

	Model model;

	bool result = generateZeros(varcomp, y, model, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
    	BOOST_CHECK(false);
    });
	BOOST_CHECK(!result);
}
BOOST_AUTO_TEST_CASE(Test_generateZeros_VarComp_MVRoot_simple) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
	VariableComparisonT varcomp(y, MultivariateRootT(Poly(MultivariateRootT::var())*MultivariateRootT::var()*x-Rational(1), 2), carl::Relation::EQ);

	Model model;
	model.assign(x, Rational(1));
	bool result = generateZeros(varcomp, y, model, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
		// 0+1*sqrt(x)/(x)
    	BOOST_CHECK(sqrtExpression == SqrtEx(Poly(Rational(0)), Poly(Rational(1)), Poly(x), Poly(x)));
		BOOST_CHECK(sideConditions.size() > 0);
    });
	BOOST_CHECK(result);
}
BOOST_AUTO_TEST_CASE(Test_generateZeros_VarComp_MVRoot_multivar) {
	carl::Variable x1 = carl::freshRealVariable("x1");
	carl::Variable x2 = carl::freshRealVariable("x2");
	carl::Variable y = carl::freshRealVariable("y");
	Poly poly = (Poly(MultivariateRootT::var())*x1) + (Poly(MultivariateRootT::var())*MultivariateRootT::var()*x2);
	VariableComparisonT varcomp(y, MultivariateRootT(poly, 2), carl::Relation::EQ);

	Model model;
	model.assign(x1, Rational(-1));
	model.assign(x2, Rational(1));

	bool result = generateZeros(varcomp, y, model, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
		// ((-1)*x1)/(x2)
    	BOOST_CHECK(sqrtExpression == SqrtEx(Poly(Rational(0)), Poly(Rational(-1))*x1, Poly(x2), Poly(Rational(1))));
		BOOST_CHECK(sideConditions.size() > 0);
    });
	BOOST_CHECK(result);
}
BOOST_AUTO_TEST_CASE(Test_generateZeros_VarComp_RAN_simple) {
	carl::Variable r = carl::freshRealVariable("r");
	carl::UnivariatePolynomial<Rational> pol = (Poly(r)*r-Rational(2)).toUnivariatePolynomial();
	carl::Interval<Rational> interval(Rational(1), carl::BoundType::STRICT, Rational(2), carl::BoundType::STRICT);
	carl::RealAlgebraicNumber<Rational> ran(pol, interval, true);

	bool result = generateZeros(ran, [&](const SqrtEx&& sqrtExpression, const ConstraintsT&& sideConditions) {
		// sqrt(2) = 0+1*sqrt(8)/2
    	BOOST_CHECK(sqrtExpression == SqrtEx(Poly(Rational(0)), Poly(Rational(1)), Poly(Rational(2)), Poly(Rational(8))));
    });
	BOOST_CHECK(result);
}

BOOST_AUTO_TEST_CASE(Test_compareSqrtEx) {
	carl::Variable x = carl::freshRealVariable("x");
	SqrtEx sqrtA(Poly(Rational(0)), Poly(Rational(1))*x, Poly(Rational(1)), Poly(Rational(1)));
	SqrtEx sqrtB(Poly(Rational(0)), Poly(Rational(-1))*x, Poly(Rational(1)), Poly(Rational(1)));
	Model model1;
	model1.assign(x, Rational(-1));
	Model model2;
	model2.assign(x, Rational(1));

	BOOST_CHECK(compareSqrtEx(sqrtA, sqrtB, model1).value());
	BOOST_CHECK(!compareSqrtEx(sqrtB, sqrtA, model1).value());
	BOOST_CHECK(!compareSqrtEx(sqrtA, sqrtB, model2).value());
	BOOST_CHECK(compareSqrtEx(sqrtB, sqrtA, model2).value());
}

BOOST_AUTO_TEST_CASE(Test_compareSqrtExWithRational) {
	SqrtEx sqrtB(Poly(Rational(0)), Poly(Rational(-1)), Poly(Rational(10)), Poly(Rational(40)));

	Rational lower = Rational(-16) / Rational(25);
	Rational upper = Rational(-31) / Rational(50);

	Model model;

	BOOST_CHECK(rationalLessThanSqrtEx(lower, sqrtB, model));
	BOOST_CHECK(!rationalLessThanSqrtEx(upper, sqrtB, model));
	BOOST_CHECK(!sqrtExLessThanRational(sqrtB, lower, model));
	BOOST_CHECK(sqrtExLessThanRational(sqrtB, upper, model));
}

BOOST_AUTO_TEST_CASE(Test_compareSqrtExWithRational_fraction) {
	SqrtEx sqrtB(Poly(Rational(2)), Poly(Rational(0)), Poly(Rational(10)), Poly(Rational(0)));

	Rational lower = Rational(1) / Rational(10);
	Rational upper = Rational(3) / Rational(10);

	Model model;

	BOOST_CHECK(rationalLessThanSqrtEx(lower, sqrtB, model));
	BOOST_CHECK(!rationalLessThanSqrtEx(upper, sqrtB, model));
	BOOST_CHECK(!sqrtExLessThanRational(sqrtB, lower, model));
	BOOST_CHECK(sqrtExLessThanRational(sqrtB, upper, model));
}

BOOST_AUTO_TEST_CASE(Test_doccToFormula) {
	carl::Variable x = carl::freshRealVariable("x");
	::vs::DisjunctionOfConstraintConjunctions docc;
	::vs::ConstraintVector conjunction1;
	conjunction1.push_back(ConstraintT(Poly(x), carl::Relation::EQ));
	conjunction1.push_back(ConstraintT(Poly(x)+Rational(1), carl::Relation::EQ));
	::vs::ConstraintVector conjunction2;
	conjunction2.push_back(ConstraintT(Poly(x)+Rational(2), carl::Relation::EQ));
	conjunction2.push_back(ConstraintT(Poly(x)+Rational(3), carl::Relation::EQ));
	docc.push_back(conjunction1);
	docc.push_back(conjunction2);

	FormulaT formula = doccToFormula(docc);
	std::stringstream ss;
	ss << formula;
	BOOST_CHECK(ss.str() == "(or (and (= x 0) (= (+ x 1) 0)) (and (= (+ x 2) 0) (= (+ x 3) 0)))");
}

BOOST_AUTO_TEST_CASE(Test_generateTestCandidates_degreeTooHigh) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
	std::vector<::vs::Substitution> results;

	ConstraintT c1(Poly(y)*y*y+Rational(1), carl::Relation::EQ);
	FormulaSetT constraints1;
	constraints1.emplace(c1);

	bool status = generateTestCandidates(results, y, Model(), constraints1);
	BOOST_CHECK(!status);

	ConstraintT c2(Poly(y)*y+Rational(1), carl::Relation::GEQ);
	FormulaSetT constraints2;
	constraints2.emplace(c2);

	status = generateTestCandidates(results, y, Model(), constraints2);
	BOOST_CHECK(status);
}
BOOST_AUTO_TEST_CASE(Test_generateTestCandidates_variableNotIncluded) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
	std::vector<::vs::Substitution> results;

	ConstraintT c(Poly(x), carl::Relation::EQ);
	FormulaSetT constraints;
	constraints.emplace(c);

	bool status = generateTestCandidates(results, y, Model(), constraints);
	BOOST_CHECK(status);
	BOOST_CHECK(results.size() == 1); // only y -> -infty
}
BOOST_AUTO_TEST_CASE(Test_generateTestCandidates_constraintType) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
	std::vector<::vs::Substitution> results;

	ConstraintT c1(Poly(y), carl::Relation::GEQ);
	ConstraintT c2(Poly(y), carl::Relation::GREATER);
	FormulaSetT constraints;
	constraints.emplace(c1);
	constraints.emplace(c2);

	bool status = generateTestCandidates(results, y, Model(), constraints);
	BOOST_CHECK(status);
	BOOST_CHECK(results.size() == 3);
	BOOST_CHECK(results[1].type() == ::vs::Substitution::Type::NORMAL);
	BOOST_CHECK(results[2].type() == ::vs::Substitution::Type::PLUS_EPSILON);
}
BOOST_AUTO_TEST_CASE(Test_generateTestCandidates_duplicateRemoval) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
	std::vector<::vs::Substitution> results;

	ConstraintT c1(Poly(y) - x, carl::Relation::GEQ);
	ConstraintT c2(Poly(y) - x, carl::Relation::GEQ);
	FormulaSetT constraints;
	constraints.emplace(c1);
	constraints.emplace(c2);

	bool status = generateTestCandidates(results, y, Model(), constraints);
	BOOST_CHECK(status);
	BOOST_CHECK(results.size() == 2); // duplicates removed
}
BOOST_AUTO_TEST_CASE(Test_generateTestCandidates_variableComparison) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
	VariableComparisonT varcomp(y, MultivariateRootT(Poly(MultivariateRootT::var())*MultivariateRootT::var()*x-Rational(1), 2), carl::Relation::EQ);
	Model model;
	model.assign(x, Rational(1));
	FormulaSetT constraints;
	constraints.emplace(varcomp);

	std::vector<::vs::Substitution> results;
	bool result = generateTestCandidates( results, y, model, constraints);
	BOOST_CHECK(result);
	BOOST_CHECK(results.size()==2);

	// 0+1*sqrt(x)/(x)
	// note that results[0] is -infty
    BOOST_CHECK(results[1].term() == SqrtEx(Poly(Rational(0)), Poly(Rational(1)), Poly(x), Poly(x)));
	BOOST_CHECK(results[1].sideCondition().size() > 0);
}

BOOST_AUTO_TEST_CASE(Test_substitute_constraint_varNotContained) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");

	::vs::Substitution substitution(y, SqrtEx(Poly(Rational(1))), ::vs::Substitution::Type::NORMAL, carl::PointerSet<::vs::Condition>(), ConstraintsT());
	ConstraintT constraint(Poly(x), carl::Relation::EQ);

	FormulaT result;
	bool status = substitute(constraint, substitution, result);
	BOOST_CHECK(status);
	BOOST_CHECK(result.constraint() == constraint);
}
BOOST_AUTO_TEST_CASE(Test_substitute_constraint_simple) {
	carl::Variable y = carl::freshRealVariable("y");

	::vs::Substitution substitution(y, SqrtEx(Poly(Rational(1))), ::vs::Substitution::Type::NORMAL, carl::PointerSet<::vs::Condition>(), ConstraintsT());
	ConstraintT constraint(Poly(y), carl::Relation::EQ);

	FormulaT result;
	bool status = substitute(constraint, substitution, result);
	BOOST_CHECK(status);
	BOOST_CHECK(result.getType() == carl::FormulaType::FALSE);
}
BOOST_AUTO_TEST_CASE(Test_substitute_varComp_varNotContained) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");

	carl::Variable r = carl::freshRealVariable("r");
	carl::UnivariatePolynomial<Rational> pol = (Poly(r)*r-Rational(2)).toUnivariatePolynomial();
	carl::Interval<Rational> interval(Rational(1), carl::BoundType::STRICT, Rational(2), carl::BoundType::STRICT);
	carl::RealAlgebraicNumber<Rational> ran(pol, interval, true);

	::vs::Substitution substitution(y, SqrtEx(Poly(Rational(1))), ::vs::Substitution::Type::NORMAL, carl::PointerSet<::vs::Condition>(), ConstraintsT());
	VariableComparisonT varcomp(x, ran, carl::Relation::EQ);

	FormulaT result;
	bool status = substitute(varcomp, substitution, Model(), result);
	BOOST_CHECK(status);
	BOOST_CHECK(result.variableComparison() == varcomp);
}
BOOST_AUTO_TEST_CASE(Test_substitute_varComp_MVRoot) {
}
BOOST_AUTO_TEST_CASE(Test_substitute_varComp_RAN) {
}

BOOST_AUTO_TEST_CASE(Test_getExplanation_degreeTooHigh) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
	std::vector<carl::Variable> ordering;
	ordering.push_back(x);
	ordering.push_back(y);

	ConstraintT c1(Poly(y)*y*y+Rational(1), carl::Relation::EQ);
	FormulaT f1(c1);
	std::vector<FormulaT> constraints;
	constraints.push_back(f1);

	Model varModel;
	varModel.emplace(x, Rational(0));

	mcsat::vs::ExplanationGenerator<mcsat::vs::DefaultSettings> generator(constraints, ordering, y, varModel);
	boost::optional<mcsat::Explanation> result = generator.getExplanation();
	BOOST_CHECK(!result);
}
BOOST_AUTO_TEST_CASE(Test_getExplanation_substitution) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
	std::vector<carl::Variable> ordering;
	ordering.push_back(x);
	ordering.push_back(y);

	std::vector<FormulaT> constraints;
	ConstraintT c1((Poly(x)-Rational(2)).pow(2) + (Poly(y)-Rational(2)).pow(2) - Rational(1), carl::Relation::LESS);
	constraints.push_back(FormulaT(c1));
	ConstraintT c2(Poly(x)-y, carl::Relation::EQ);
	constraints.push_back(FormulaT(c2));

	Model varModel;
	varModel.emplace(x, Rational(0));

	mcsat::vs::ExplanationGenerator<mcsat::vs::DefaultSettings> generator(constraints, ordering, y, varModel);
	boost::optional<mcsat::Explanation> result = generator.getExplanation();
	BOOST_CHECK(result);
	std::stringstream ss;
	ss << result.value();
	BOOST_CHECK(ss.str() == "(or (<= (+ (* (- 1) (* y y)) (* 4 y) (* (- 1) (* x x)) (* 4 x) (- 7)) 0) (!= (+ y (* (- 1) x)) 0) (< (+ (* 2 (* x x)) (* (- 8) x) 7) 0))");
}

BOOST_AUTO_TEST_SUITE_END();

max_stars_repo_name: minemebarsha/smtrat

max_issues_repo_name: minemebarsha/smtrat

max_forks_repo_name: minemebarsha/smtrat


text: #include <boost/mpl/aux_/preprocessed/msvc70/divides.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// test_nvp.cpp

// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// should pass compilation and execution

#include <cstddef> // NULL
#include <cstdio> // remove
#include <fstream>

#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
    using ::remove;
}
#endif

#include <I3Test.h>

#include <serialization/nvp.hpp>

#include "B.hpp"
#include "A.ipp"

template <typename TS /*test settings*/>
void do_test(){
    auto testfile = I3Test::testfile("test_nvp");

    B b, b1;

    {
        typename TS::test_ostream os(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_oarchive oa(os, TS::TEST_ARCHIVE_FLAGS);
        oa << I3_SERIALIZATION_NVP(b);
    }
    {
        typename TS::test_istream is(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_iarchive ia(is, TS::TEST_ARCHIVE_FLAGS);
        ia >> I3_SERIALIZATION_NVP(b1);
    }
    ENSURE(b == b1);

    B* bptr = &b;
    B* bptr1;

    {
        typename TS::test_ostream os(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_oarchive oa(os, TS::TEST_ARCHIVE_FLAGS);
        oa << I3_SERIALIZATION_NVP(bptr);
    }
    {
        typename TS::test_istream is(testfile, TS::TEST_STREAM_FLAGS);
        typename TS::test_iarchive ia(is, TS::TEST_ARCHIVE_FLAGS);
        ia >> I3_SERIALIZATION_NVP(bptr1);
    }
    ENSURE(b == *bptr1);

    std::remove(testfile.c_str());
}

TEST_GROUP(test_nvp)

#define TEST_SET(name) \
TEST(name ## _nvp){ \
    do_test<test_settings>(); \
}

#define I3_ARCHIVE_TEST binary_archive.hpp
#include "select_archive.hpp"
TEST_SET(binary_archive)

#undef I3_ARCHIVE_TEST
#define I3_ARCHIVE_TEST text_archive.hpp
#include "select_archive.hpp"
TEST_SET(text_archive)

#undef I3_ARCHIVE_TEST
#define I3_ARCHIVE_TEST xml_archive.hpp
#include "select_archive.hpp"
TEST_SET(xml_archive)

#undef I3_ARCHIVE_TEST
#define I3_ARCHIVE_TEST portable_binary_archive.hpp
#include "select_archive.hpp"
TEST_SET(portable_binary_archive)

// EOF


text:
/*************************************************************************
 * Copyright (C) 2017-2019 Barcelona Supercomputing Center               *
 *                         Centro Nacional de Supercomputacion           *
 * All rights reserved.                                                  *
 *                                                                       *
 * This file is part of NORNS, a service that allows other programs to   *
 * start, track and manage asynchronous transfers of data resources      *
 * between different storage backends.                                   *
 *                                                                       *
 * See AUTHORS file in the top level directory for information regarding *
 * developers and contributors.                                          *
 *                                                                       *
 * This software was developed as part of the EC H2020 funded project    *
 * NEXTGenIO (Project ID: 671951).                                       *
 *     www.nextgenio.eu                                                  *
 *                                                                       *
 * Permission is hereby granted, free of charge, to any person obtaining *
 * a copy of this software and associated documentation files (the       *
 * "Software"), to deal in the Software without restriction, including   *
 * without limitation the rights to use, copy, modify, merge, publish,   *
 * distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to *
 * the following conditions:                                             *
 *                                                                       *
 * The above copyright notice and this permission notice shall be        *
 * included in all copies or substantial portions of the Software.       *
 *                                                                       *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                 *
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS   *
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN    *
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN     *
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE      *
 * SOFTWARE.                                                             *
 *************************************************************************/

#include <sstream>
#include <boost/algorithm/string/join.hpp>

#include "common.hpp"
#include "messages.pb.h"
#include "backends.hpp"
#include "resources.hpp"
#include "utils.hpp"
#include "request.hpp"

namespace {

norns::iotask_type decode_iotask_type(::google::protobuf::uint32 type) {

    using norns::iotask_type;

    switch(type) {
        case NORNS_IOTASK_COPY:
            return iotask_type::copy;
        case NORNS_IOTASK_MOVE:
            return iotask_type::move;
        case NORNS_IOTASK_REMOVE:
            return iotask_type::remove;
        default:
            return iotask_type::unknown;
    }
}

norns::backend_type decode_backend_type(::google::protobuf::uint32 type) {

    using norns::backend_type;

    switch(type) {
        case NORNS_BACKEND_NVML:
            return backend_type::nvml;
        case NORNS_BACKEND_LUSTRE:
            return backend_type::lustre;
//        //XXX PROCESS_MEMORY should never be received
//        case NORNS_BACKEND_PROCESS_MEMORY: // deprecated
//            return backend_type::process_memory;
        case NORNS_BACKEND_ECHOFS:
            return backend_type::echofs;
        case NORNS_BACKEND_POSIX_FILESYSTEM:
            return backend_type::posix_filesystem;
        default:
            return backend_type::unknown;
    }
}

norns::command_type decode_command(::google::protobuf::uint32 type) {

    using norns::command_type;

    switch(type) {
        case NORNSCTL_CMD_PING:
            return command_type::ping;
        case NORNSCTL_CMD_PAUSE_LISTEN:
            return command_type::pause_listen;
        case NORNSCTL_CMD_RESUME_LISTEN:
            return command_type::resume_listen;
        case NORNSCTL_CMD_SHUTDOWN:
            return command_type::shutdown;
        default:
            return command_type::unknown;
    }
}

bool is_valid(const norns::rpc::Request_Task_Resource& res) {
    if(res.type() & NORNS_NULL_RESOURCE) {
        return true;
    }

    if(res.type() & NORNS_PROCESS_MEMORY) {
        if(!res.has_buffer()) {
            return false;
        }

        return true;
    }

    if(res.type() & NORNS_POSIX_PATH) {
        if(!res.has_path()) {
            return false;
        }

        if(!(res.type() & (R_LOCAL | R_SHARED | R_REMOTE))) {
            return false;
        }

        if((res.type() & R_LOCAL) && res.path().has_hostname()) {
            return false;
        }

        if((res.type() & R_SHARED) && res.path().has_hostname()) {
            return false;
        }

        if((res.type() & R_REMOTE) && !res.path().has_hostname()) {
            return false;
        }

        return true;
    }

    return false;
}

bool
is_valid(const norns::rpc::Request_Task& task) {

    using norns::iotask_type;

    switch(::decode_iotask_type(task.optype())) {
        case iotask_type::copy:
        case iotask_type::move:
        case iotask_type::remove:
            if(!task.has_source() || !::is_valid(task.source())) {
                return false;
            }

            if(!task.has_destination() || !::is_valid(task.destination())) {
                return false;
            }

            return true;

        default:
            return false;
    }
}

std::shared_ptr<norns::data::resource_info>
create_from(const norns::rpc::Request_Task_Resource& res) {

    using norns::data::resource_info;
    using norns::data::memory_buffer;
    using norns::data::local_path_info;
    using norns::data::shared_path_info;
    using norns::data::remote_path_info;
    using norns::data::remote_resource_info;

    assert(is_valid(res));

    if(res.type() & NORNS_PROCESS_MEMORY) {
        return std::make_shared<memory_buffer>(res.buffer().address(),
                                               res.buffer().size());
    }

    if(res.type() & NORNS_POSIX_PATH) {
        if(res.type() & R_LOCAL) {
            return std::make_shared<local_path_info>(res.path().nsid(),
                                                     res.path().datapath());
        }

        if(res.type() & R_SHARED) {
            return std::make_shared<shared_path_info>(res.path().nsid(),
                                                      res.path().datapath());
        }

        // R_REMOTE
        assert(res.type() & R_REMOTE);
        //return std::make_shared<remote_path_info>(res.path().nsid(),
        //                                          res.path().hostname(),
        //                                          res.path().datapath());

        return std::make_shared<remote_resource_info>(res.path().hostname(),
                                                      res.path().nsid(),
                                                      res.path().datapath());
    }

    assert(res.type() & NORNS_NULL_RESOURCE);
    return {};
}

std::string
to_string(const std::vector<std::shared_ptr<norns::storage::backend>>& blist) {

    std::string str;

    for(const auto& b : blist) {
        str += b->to_string() + ", ";
    }

    if(str.length() != 0) {
        str.pop_back();
        str.pop_back();
    }

    return str;
}

}

namespace norns {
namespace api {

using request_ptr = std::unique_ptr<request>;

request_ptr request::create_from_buffer(const std::vector<uint8_t>& buffer, int size) {

    norns::rpc::Request rpc_req;

    if(rpc_req.ParseFromArray(buffer.data(), size)) {
        switch(rpc_req.type()) {
            case norns::rpc::Request::IOTASK_SUBMIT:

                if(rpc_req.has_task()) {

                    auto task = rpc_req.task();
                    iotask_type optype = ::decode_iotask_type(task.optype());

                    if(::is_valid(task)) {
                        const auto src_res = ::create_from(task.source());
                        const auto dst_res = ::create_from(task.destination());

                        if(dst_res) {
                            return std::make_unique<iotask_create_request>(optype, std::move(src_res), dst_res);
                        }

                        return std::make_unique<iotask_create_request>(optype, std::move(src_res), boost::none);
                    }

                    return std::make_unique<bad_request>();
                }
            break;

            case norns::rpc::Request::IOTASK_STATUS:
                if(rpc_req.has_task()) {

                    auto task = rpc_req.task();

                    if(task.has_taskid()) {
                        return std::make_unique<iotask_status_request>(task.taskid());
                    }
                }
            break;

            case norns::rpc::Request::PING:
                return std::make_unique<ping_request>();

            case norns::rpc::Request::GLOBAL_STATUS:
                return std::make_unique<global_status_request>();

            case norns::rpc::Request::CTL_COMMAND:

                if(rpc_req.has_command()) {
                    command_type cmd = ::decode_command(rpc_req.command().id());
                    return std::make_unique<command_request>(cmd);
                }
                break;

            case norns::rpc::Request::JOB_REGISTER:
            case norns::rpc::Request::JOB_UPDATE:

                if(rpc_req.has_jobid() && rpc_req.has_job()) {

                    auto id = rpc_req.jobid();
                    auto job = rpc_req.job();

                    std::vector<std::string> hosts;
                    hosts.reserve(job.hosts().size());

                    for(const auto& h : job.hosts()) {
                        hosts.push_back(h);
                    }

                    std::vector<std::shared_ptr<storage::backend>> backends;
#if 0
                    //XXX deprecated for now, backends are registered elsewhere
                    //here we should only propagate access rights to backends,
                    // i.e. nsids this job can access and usage quotas
                    backends.reserve(job.backends().size());

                    for(const auto& b : job.backends()) {
                        backends.push_back(storage::backend_factory::create_from(b.type(), b.mount(), b.quota()));
                    }
#endif

                    //XXX TODO instantiate job_capabilities
                    //and pass them to make_unique<XXX> below
                    //instead of 'backends'

                    if(rpc_req.type() == norns::rpc::Request::JOB_REGISTER) {
                        return std::make_unique<job_register_request>(id, hosts, backends);
                    }
                    else { // rpc_req.type() == norns::rpc::Request::JOB_UPDATE)
                        return std::make_unique<job_update_request>(id, hosts, backends);
                    }
                }
                break;

            case norns::rpc::Request::JOB_UNREGISTER:
                if(rpc_req.has_jobid()) {
                    return std::make_unique<job_unregister_request>(rpc_req.jobid());
                }
                break;

            case norns::rpc::Request::PROCESS_ADD:
            case norns::rpc::Request::PROCESS_REMOVE:
                if(rpc_req.has_jobid() && rpc_req.has_process()) {

                    auto process = rpc_req.process();

                    if(rpc_req.type() == norns::rpc::Request::PROCESS_ADD) {
                        return std::make_unique<process_register_request>(
                                rpc_req.jobid(),
                                process.uid(),
                                process.gid(),
                                process.pid());
                    }
                    else { // rpc_req.type() == norns::rpc::Request::PROCESS_REMOVE
                        return std::make_unique<process_unregister_request>(
                                rpc_req.jobid(),
                                process.uid(),
                                process.gid(),
                                process.pid());
                    }
                }
                break;

            case norns::rpc::Request::NAMESPACE_REGISTER:
            case norns::rpc::Request::NAMESPACE_UPDATE:
            case norns::rpc::Request::NAMESPACE_UNREGISTER:
                if(rpc_req.has_nspace()) {

                    auto nspace = rpc_req.nspace();

                    if(nspace.has_backend()) {

                        const auto& b = nspace.backend();
                        backend_type type = ::decode_backend_type(b.type());

                        if(type == backend_type::unknown) {
                            break;
                        }

                        if(rpc_req.type() == norns::rpc::Request::NAMESPACE_REGISTER) {
                            return std::make_unique<backend_register_request>(nspace.nsid(),
                                                                              type,
                                                                              b.track(),
                                                                              b.mount(),
                                                                              b.capacity());
                        }
                        else { // rpc_req.type() == norns::rpc::Request::NAMESPACE_UPDATE
                            return std::make_unique<backend_update_request>(nspace.nsid(),
                                                                            type,
                                                                            b.track(),
                                                                            b.mount(),
                                                                            b.capacity());
                        }
                    }
                    else { // norns::rpc::Request::NAMESPACE_UNREGISTER
                        return std::make_unique<backend_unregister_request>(nspace.nsid());
                    }
                }
                break;
        }
    }

    return std::make_unique<bad_request>();
}

void request::cleanup() {
    google::protobuf::ShutdownProtobufLibrary();
}

namespace detail {

template<>
std::string iotask_create_request::to_string() const {

    const auto op = this->get<0>();
    const auto src = this->get<1>();
    const auto dst = this->get<2>();

    auto str = utils::to_string(op);

    if(src) {
        str += std::string(", ") + src->to_string();
    }

    if(dst) {
        str += std::string(" => ") + (*dst)->to_string();
    }

    return str;
}

template<>
std::string iotask_status_request::to_string() const {

    const auto tid = this->get<0>();

    return std::to_string(tid);
}

template<>
std::string global_status_request::to_string() const {
    return "GLOBAL_STATUS";
}

template<>
std::string command_request::to_string() const {
    switch(this->get<0>()) {
        case command_type::ping:
            return "PING";
        case command_type::pause_listen:
            return "PAUSE_LISTEN";
        case command_type::resume_listen:
            return "RESUME_LISTEN";
        case command_type::shutdown:
            return "SHUTDOWN";
        default:
            return "UNKNOWN";
    }
}

template<>
std::string ping_request::to_string() const {
    return "PING";
}

template<>
std::string job_register_request::to_string() const {

    using boost::algorithm::join;
    std::stringstream ss;

    const auto& jobid = this->get<0>();
    const auto& hosts = this->get<1>();
    const auto& backends = this->get<2>();

    ss << "jobid: " << jobid << ", "
       << "hosts: {" << join(hosts, ", ") << "}; "
       << "backends: {" << ::to_string(backends) << "}";

    return ss.str();
}

template<>
std::string job_update_request::to_string() const {

    using boost::algorithm::join;
    std::stringstream ss;

    const auto& jobid = this->get<0>();
    const auto& hosts = this->get<1>();
    const auto& backends = this->get<2>();

    ss << "jobid: " << jobid << ", "
       << "hosts: {" << join(hosts, ", ") << "}; "
       << "backends: {" << ::to_string(backends) << "}";

    return ss.str();
}

template<>
std::string job_unregister_request::to_string() const {

    const auto& jobid = this->get<0>();

    return "jobid: " + std::to_string(jobid);
}

template<>
std::string process_register_request::to_string() const {

    const auto& jobid = this->get<0>();
    const auto& uid = this->get<1>();
    const auto& gid = this->get<2>();
    const auto& pid = this->get<3>();

    return "jobid: " + std::to_string(jobid) + ", "
           "uid:" + std::to_string(uid) + ", "
           "gid:" + std::to_string(gid) + ", "
           "pid:" + std::to_string(pid);
}

template<>
std::string process_unregister_request::to_string() const {

    const auto& jobid = this->get<0>();
    const auto& uid = this->get<1>();
    const auto& gid = this->get<2>();
    const auto& pid = this->get<3>();

    return "jobid: " + std::to_string(jobid) + ", "
           "uid:" + std::to_string(uid) + ", "
           "gid:" + std::to_string(gid) + ", "
           "pid:" + std::to_string(pid);
}

template<>
std::string backend_register_request::to_string() const {

    const auto& nsid = this->get<0>();
    const auto& type = this->get<1>();
    const auto& track = this->get<2>();
    const auto& mount = this->get<3>();
    const auto& quota = this->get<4>();

#if 0 // verbose
    return "nsid: \"" + nsid + "\", "
           "type:" + utils::to_string(type) + ", "
           (mount != "" ?  "mount: \"" + mount + "\", " : "") +
           (quota != 0 ? "quota: " + std::to_string(quota) : "unlimited");
#else
    return "\"" + nsid + "\", " +
           utils::to_string(type) + ", " +
           (track ? "tracked" : "untracked") + ", " +
           (mount != "" ?  "\"" + mount + "\", " : "") +
           (quota != 0 ? std::to_string(quota) : "unlimited");
#endif
}

template<>
std::string backend_update_request::to_string() const {

    const auto& nsid = this->get<0>();
    const auto& type = this->get<1>();
    const auto& track = this->get<2>();
    const auto& mount = this->get<3>();
    const auto& quota = this->get<4>();

#if 0 // verbose
    return "nsid: \"" + nsid + "\", "
           "type:" + utils::to_string(type) + ", "
           (mount != "" ?  "mount: \"" + mount + "\", " : "") +
           (quota != 0 ? "quota: " + std::to_string(quota) : "unlimited");
#else
    return "\"" + nsid + "\", " +
           utils::to_string(type) + ", " +
           (track ? "tracked" : "untracked") + ", " +
           (mount != "" ?  "\"" + mount + "\", " : "") +
           (quota != 0 ? std::to_string(quota) : "unlimited");
#endif
}

template<>
std::string backend_unregister_request::to_string() const {

    const auto& nsid = this->get<0>();

    return "\"" + nsid + "\"";
}

template<>
std::string bad_request::to_string() const {
    return "BAD_REQUEST";
}

} // namespace detail

} // namespace api
} // namespace norns

max_stars_repo_name: bsc-ssrg/NORNS

max_issues_repo_name: bsc-ssrg/NORNS

max_forks_repo_name: bsc-ssrg/NORNS


text:
/*=============================================================================
    Copyright (c) 2001-2007 Joel de Guzman

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#if !defined(BOOST_SPIRIT_RULE_FEB_12_2007_1020AM)
#define BOOST_SPIRIT_RULE_FEB_12_2007_1020AM

#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/qi/nonterminal/nonterminal.hpp>
#include <boost/spirit/home/qi/nonterminal/grammar_fwd.hpp>
#include <boost/spirit/home/qi/nonterminal/detail/rule.hpp>
#include <boost/spirit/home/qi/nonterminal/detail/error_handler.hpp>
#include <boost/spirit/home/qi/domain.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_convertible.hpp>

#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
#endif

namespace boost { namespace spirit { namespace qi
{
    namespace detail { struct rule_decorator; }

    template <
        typename Iterator
      , typename T0 = unused_type
      , typename T1 = unused_type
      , typename T2 = unused_type
    >
    struct rule
      : make_nonterminal<rule<Iterator, T0, T1, T2>, T0, T1, T2>::type
    {
        typedef
            make_nonterminal<rule<Iterator, T0, T1, T2>, T0, T1, T2>
        make_nonterminal_;

        typedef typename make_nonterminal_::skipper_type skipper_type;
        typedef typename make_nonterminal_::type base_type;
        typedef Iterator iterator_type;
        typedef rule<Iterator, T0, T1, T2> self_type;

        typedef
            virtual_component_base<
                Iterator
              , typename base_type::context_type
              , skipper_type
            >
        virtual_component;

        typedef intrusive_ptr<virtual_component> pointer_type;

        rule(std::string const& name_ = std::string())
          : name_(name_) {}

        ~rule() {}

        rule(rule const& rhs)
          : ptr(rhs.ptr)
          , name_(rhs.name_)
        {
        }

        rule& operator=(rule const& rhs)
        {
            ptr = rhs.ptr;
            name_ = rhs.name_;
            return *this;
        }

        template <typename Expr>
        rule& operator=(Expr const& xpr)
        {
            typedef spirit::traits::is_component<qi::domain, Expr> is_component;

            // report invalid expression error as early as possible
//             BOOST_MPL_ASSERT_MSG(
//                 is_component::value,
//                 xpr_is_not_convertible_to_a_parser, ());

            // temp workaround for mpl problem
            BOOST_STATIC_ASSERT(is_component::value);

            define(xpr, mpl::false_());
            return *this;
        }

        template <typename Expr>
        friend rule& operator%=(rule& r, Expr const& xpr)
        {
            typedef spirit::traits::is_component<qi::domain, Expr> is_component;

            // report invalid expression error as early as possible
            //~ BOOST_MPL_ASSERT_MSG(
                //~ is_component::value,
                //~ xpr_is_not_convertible_to_a_parser, ());

            // temp workaround for mpl problem
            BOOST_STATIC_ASSERT(is_component::value);

            r.define(xpr, mpl::true_());
            return r;
        }

        self_type alias() const
        {
            self_type result;
            result.define(*this, mpl::false_());
            return result;
        }

        typename
            make_nonterminal_holder<
                nonterminal_object<self_type>
              , self_type
            >::type
        copy() const
        {
            typename
                make_nonterminal_holder<
                    nonterminal_object<self_type>
                  , self_type
                >::type
            result = {{*this}};
            return result;
        }

        std::string const& name() const
        {
            return name_;
        }

        void name(std::string const& str)
        {
            name_ = str;
        }

    private:

        template <typename Iterator_, typename T0_, typename T1_, typename T2_>
        friend struct grammar;

        friend struct detail::rule_decorator;

        template <typename Expr, typename Auto>
        void define(Expr const& xpr, Auto)
        {
            typedef typename
                result_of::as_component<qi::domain, Expr>::type
            component;
            typedef
                detail::virtual_component<
                    Iterator
                  , component
                  , typename base_type::context_type
                  , skipper_type
                  , Auto
                >
            virtual_component;
            ptr = new virtual_component(spirit::as_component(qi::domain(), xpr));
        }

        template <typename Iterator_, typename Context, typename Skipper>
        bool parse(
            Iterator_& first, Iterator_ const& last
          , Context& context, Skipper const& skipper) const
        {
            // If the following line produces a compilation error stating the
            // 4th parameter is not convertible to the expected type, then you
            // are probably trying to use this rule instance with a skipper
            // which is not compatible with the skipper type used while
            // defining the type of this rule instance.
            return ptr->parse(first, last, context, skipper);
        }

        std::string what() const
        {
            if (name_.empty())
            {
                if (ptr)
                {
                    return "unnamed-rule";
                }
                else
                {
                    return "empty-rule";
                }
            }
            else
            {
                return name_;
            }
        }

        friend struct nonterminal_director;
        pointer_type ptr;
        std::string name_;
    };

    // Decoration support: create a new virtual component and link it as
    // first element in the chain of virtual components associated with this
    // rule. Returns the previous topmost virtual component in the chain.
    // We provide support from 1 to 5 arguments.

    namespace detail
    {
        struct rule_decorator
        {
            template <typename Decorator, typename Rule, typename A1>
            typename Rule::pointer_type
            static call(Rule& r, A1 const& a1)
            {
                typename Rule::pointer_type old (r.ptr);
                r.ptr.reset(new Decorator(r.ptr, a1));
                return old;
            }

            template <typename Decorator, typename Rule, typename A1, typename A2>
            typename Rule::pointer_type
            static call(Rule& r, A1 const& a1, A2 const& a2)
            {
                typename Rule::pointer_type old (r.ptr);
                r.ptr.reset(new Decorator(r.ptr, a1, a2));
                return old;
            }

            template <typename Decorator, typename Rule
              , typename A1, typename A2, typename A3
            >
            typename Rule::pointer_type
            static call(Rule& r
              , A1 const& a1, A2 const& a2, A3 const& a3)
            {
                typename Rule::pointer_type old (r.ptr);
                r.ptr.reset(new Decorator(r.ptr, a1, a2, a3));
                return old;
            }

            template <typename Decorator, typename Rule
              , typename A1, typename A2, typename A3, typename A4
            >
            typename Rule::pointer_type
            static call(Rule& r
              , A1 const& a1, A2 const& a2
              , A3 const& a3, A4 const& a4)
            {
                typename Rule::pointer_type old (r.ptr);
                r.ptr.reset(new Decorator(r.ptr, a1, a2, a3, a4));
                return old;
            }

            template <typename Decorator, typename Rule
              , typename A1, typename A2, typename A3, typename A4, typename A5
            >
            typename Rule::pointer_type
            static call(Rule& r
              , A1 const& a1, A2 const& a2
              , A3 const& a3, A4 const& a4, A5 const& a5)
            {
                typename Rule::pointer_type old (r.ptr);
                r.ptr.reset(new Decorator(r.ptr, a1, a2, a3, a4, a5));
                return old;
            }
        };
    }

    template <typename Decorator
      , typename Iterator, typename T0, typename T1, typename T2
      , typename A1>
    typename rule<Iterator, T0, T1, T2>::pointer_type
    decorate(rule<Iterator, T0, T1, T2>& r
      , A1 const& a1)
    {
        return detail::rule_decorator::
            template call<Decorator>(r, a1);
    }

    template <typename Decorator
      , typename Iterator, typename T0, typename T1, typename T2
      , typename A1, typename A2
    >
    typename rule<Iterator, T0, T1, T2>::pointer_type
    decorate(rule<Iterator, T0, T1, T2>& r
      , A1 const& a1, A2 const& a2)
    {
        return detail::rule_decorator::
            template call<Decorator>(r, a1, a2);
    }

    template <typename Decorator
      , typename Iterator, typename T0, typename T1, typename T2
      , typename A1, typename A2, typename A3
    >
    typename rule<Iterator, T0, T1, T2>::pointer_type
    decorate(rule<Iterator, T0, T1, T2>& r
      , A1 const& a1, A2 const& a2, A3 const& a3)
    {
        return detail::rule_decorator::
            template call<Decorator>(r, a1, a2, a3);
    }

    template <typename Decorator
      , typename Iterator, typename T0, typename T1, typename T2
      , typename A1, typename A2, typename A3, typename A4
    >
    typename rule<Iterator, T0, T1, T2>::pointer_type
    decorate(rule<Iterator, T0, T1, T2>& r
      , A1 const& a1, A2 const& a2
      , A3 const& a3, A4 const& a4)
    {
        return detail::rule_decorator::
            template call<Decorator>(r, a1, a2, a3, a4);
    }

    template <typename Decorator
      , typename Iterator, typename T0, typename T1, typename T2
      , typename A1, typename A2, typename A3, typename A4, typename A5
    >
    typename rule<Iterator, T0, T1, T2>::pointer_type
    decorate(rule<Iterator, T0, T1, T2>& r
      , A1 const& a1, A2 const& a2
      , A3 const& a3, A4 const& a4, A5 const& a5)
    {
        return detail::rule_decorator::
            template call<Decorator>(r, a1, a2, a3, a4, a5);
    }

    // Error handling support
    template <
        error_handler_result action
      , typename Iterator, typename T0, typename T1, typename T2
      , typename F>
    void on_error(rule<Iterator, T0, T1, T2>& r, F f)
    {
        typedef
            rule<Iterator, T0, T1, T2>
        rule_type;

        typedef
            detail::error_handler<
                Iterator
              , typename rule_type::base_type::context_type
              , typename rule_type::skipper_type
              , F
              , action>
        error_handler;
        decorate<error_handler>(r, f);
    }

    // Error handling support when <action> is not
    // specified. We will default to <fail>.
    template <typename Iterator, typename T0, typename T1
      , typename T2, typename F>
    void on_error(rule<Iterator, T0, T1, T2>& r, F f)
    {
        on_error<fail>(r, f);
    }

}}}

#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif

#endif