/*!
 *  \brief Get the value of the first argument.
 *  \param outResult Value of the first argument.
 *  \param ioContext Evolutionary context.
 *  \throw Beagle::AssertException If there is no argument to the primitive.
 *  \throw Beagle::GP::MaxNodesExecutionException If number of nodes execution is more than allowed.
 *  \throw Beagle::GP::MaxTimeExecutionException If elapsed execution time is more than allowed.
 */
inline void Beagle::GP::Primitive::get1stArgument(Beagle::GP::Datum& outResult,
        Beagle::GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	using namespace Beagle;
	Beagle_AssertM(getNumberArguments() >= 1);
	unsigned int lNodeIndex = ioContext.getCallStackTop() + 1;
	ioContext.incrementNodesExecuted();
	ioContext.checkExecutionTime();
	ioContext.pushCallStack(lNodeIndex);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "primitive", "Beagle::GP::Primitive",
	    std::string("Executing the primitive '")+
	    ioContext.getGenotype()[lNodeIndex].mPrimitive->getName()+std::string("' of the ")+
	    uint2ordinal(lNodeIndex+1)+std::string(" node of the ")+
	    uint2ordinal(ioContext.getGenotypeIndex()+1)+" tree"
	);
	ioContext.getGenotype()[lNodeIndex].mPrimitive->execute(outResult, ioContext);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "primitive", "Beagle::GP::Primitive",
	    std::string("Result of executing '")+
	    ioContext.getGenotype()[lNodeIndex].mPrimitive->getName()+std::string("': ")+
	    outResult.serialize()
	);
	ioContext.popCallStack();
	Beagle_StackTraceEndM("void GP::Primitive::get1stArgument(GP::Datum& outResult, GP::Context& ioContext)");
}
/*!
 *  \brief Get the value of the arguments.
 *  \param outResults Value of the arguments. Array of the good size must be allocated.
 *  \param inSizeTDatum Size (in byte) of each datum of the array.
 *  \param ioContext Evolutionary context.
 *  \throw Beagle::AssertException If the size of the bag doesn't match the nb. of arguments.
 *  \throw Beagle::GP::MaxNodesExecutionException If number of nodes execution is more than allowed.
 *  \throw Beagle::GP::MaxTimeExecutionException If elapsed execution time is more than allowed.
 */
inline void Beagle::GP::Primitive::getArguments(Beagle::GP::Datum outResults[],
        size_t inSizeTDatum,
        Beagle::GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	using namespace Beagle;
	char* lCharResults = reinterpret_cast<char*>(outResults);
	GP::Tree& lActualTree = ioContext.getGenotype();
	unsigned int lNodeIndex = ioContext.getCallStackTop() + 1;
	ioContext.incrementNodesExecuted();
	ioContext.checkExecutionTime();
	ioContext.pushCallStack(lNodeIndex);
	lActualTree[lNodeIndex].mPrimitive->execute(*outResults, ioContext);
	ioContext.popCallStack();
	for(unsigned int i=1; i<mNumberArguments; i++) {
		lNodeIndex += lActualTree[lNodeIndex].mSubTreeSize;
		ioContext.incrementNodesExecuted();
		ioContext.checkExecutionTime();
		ioContext.pushCallStack(lNodeIndex);
		GP::Datum* lResultsI = reinterpret_cast<GP::Datum*>(lCharResults + (i*inSizeTDatum));
		Beagle_LogDebugM(
		    ioContext.getSystem().getLogger(),
		    "primitive", "Beagle::GP::Primitive",
		    std::string("Executing the primitive '")+
		    lActualTree[lNodeIndex].mPrimitive->getName()+std::string("' of the ")+
		    uint2ordinal(lNodeIndex+1)+std::string(" node of the ")+
		    uint2ordinal(ioContext.getGenotypeIndex()+1)+" tree"
		);
		lActualTree[lNodeIndex].mPrimitive->execute(*lResultsI, ioContext);
		ioContext.popCallStack();
	}
	Beagle_StackTraceEndM("void GP::Primitive::getArguments(GP::Datum outResults[], size_t inSizeTDatum, GP::Context& ioContext)");
}
/*!
 *  \brief Get the value of the nth argument.
 *  \param inN Index of the argument to get.
 *  \param outResult Value of the nth argument.
 *  \param ioContext Evolutionary context.
 *  \throw Beagle::AssertException If the argument index is invalid.
 *  \throw Beagle::GP::MaxNodesExecutionException If number of nodes execution is more than allowed.
 *  \throw Beagle::GP::MaxTimeExecutionException If elapsed execution time is more than allowed.
 */
inline void Beagle::GP::Primitive::getArgument(unsigned int inN,
        Beagle::GP::Datum& outResult,
        Beagle::GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	using namespace Beagle;
	Beagle_UpperBoundCheckAssertM(inN,mNumberArguments-1);
	GP::Tree& lActualTree = ioContext.getGenotype();
	unsigned int lNodeIndex = getArgumentIndex(inN, ioContext);
	ioContext.incrementNodesExecuted();
	ioContext.checkExecutionTime();
	ioContext.pushCallStack(lNodeIndex);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "primitive", "Beagle::GP::Primitive",
	    std::string("Executing the primitive '")+
	    lActualTree[lNodeIndex].mPrimitive->getName()+std::string("' of the ")+uint2ordinal(lNodeIndex+1)+
	    std::string(" node of the ")+uint2ordinal(ioContext.getGenotypeIndex()+1)+" tree"
	);
	lActualTree[lNodeIndex].mPrimitive->execute(outResult, ioContext);
	ioContext.popCallStack();
	Beagle_StackTraceEndM("void GP::Primitive::getArgument(unsigned int inN, GP::Datum& outResult, GP::Context& ioContext)");
}