/****************************************************
    FactorialCPE.hpp

    This program computes the factorial of a number either
    recursively or in a loop (thus avoiding function call 
    overhead) and compares the results.

****************************************************/


#ifndef FACTORIALCPE_HEADER
#define FACTORIALCPE_HEADER

#include "CPE.hpp"

//everything stuck in header for convenience, NOT considered 'good practice'!

class FactorialCPE : CCPE{
    class Args{
    public:
        double val;
        bool doLoop;
    };

    static double factRecursive(double val){
        if (val > 1)
            return (val *= factRecursive(val-1));
        else
            return 1.0;
    };

    static double factLoop(double val){
        double tmp = val;
        while (val > 1){
            val -= 1;
            tmp *= val;
        }
        return tmp;
    };

    //    function to run the tests on MUST ALWAYS RETURN A VOID *
    //    AND MUST ALWAYS TAKE A VOID * AS AN ARG
    static void * dummy(void *args){
        static double tmp;
        Args *myArgs = (Args *) args;
        if (myArgs->doLoop)
            tmp = factLoop(myArgs->val);
        else
            tmp = factRecursive(myArgs->val);
        return (void*)&tmp;
    };
public:
    FactorialCPE(unsigned char val){//no point in more than 170 as it is INF
        void *retVal;
        Args args;

        args.val = val;
        args.doLoop = true;
        retVal = test_it(dummy, (void *)&args, 3);
        std::cout << "Factorial loop results: " << *((double*)retVal) << std::endl;
        std::cout << "Overhead for factorial loop: " << GetMinOverhead() << std::endl;
        std::cout << "CPE for factorial loop: " << GetMinExecution() << std::endl;

        args.doLoop = false;
        retVal = test_it(dummy, (void *)&args, 3);
        std::cout << "\nFactorial recursive results: " << *((double*)retVal) << std::endl;
        std::cout << "Overhead for factorial recursive: " << GetMinOverhead() << std::endl;
        std::cout << "CPE for factorial recursive: " << GetMinExecution() << std::endl;
    };
};

#endif //FACTORIALCPE_HEADER
