#include <CudaMatrixPrivate.cuh>
#include <math.h>
#include <thrust/transform.h>
#include <thrust/functional.h>
#include <thrust/execution_policy.h>
using namespace thrust::placeholders;

struct PowOperator{
    float exponent;
    PowOperator(float v):exponent(v) {}
    void setExponent(float v){
        exponent = v;
    }
    __host__ __device__
    float operator()(const float& x)  {
        return powf(x, exponent);
    }
};

void unaryAdd(float* in1, float* in2, float* out, unsigned long  length)
{
    thrust::plus<float> op;
    thrust::transform(thrust::device,in1,in1+length,in2,out,op);
}

void unaryAdd(float* in1, const float& in2, float* out, unsigned long  length)
{
    thrust::transform(thrust::device,in1,in1+length,out,in2*_1);
}

void unaryMul(float* in1, float* in2, float* out, unsigned long  length)
{
    thrust::multiplies<float> op;
    thrust::transform(thrust::device,in1,in1+length,in2,out,op);
}

void unaryNeg(float* in1, float* out, unsigned long length){
    thrust::negate<float> op;
    thrust::transform(thrust::device,in1,in1+length,out,op);
}

void unarySub(float* in1, float* in2, float* out, unsigned long length){
    thrust::minus<float> op;
    thrust::transform(thrust::device,in1,in1+length,in2,out,op);
}

void unaryDiv(float* in1, float* in2, float* out, unsigned long length){
    thrust::divides<float> op;
    thrust::transform(thrust::device,in1,in1+length,in2,out,op);
}

void unaryPow(float* in1, float N,float* out, unsigned long length){
    if (N == 0.0f)
    {
            thrust::fill(out,out+length,0);
            return;
    }
    if (N == 1.0f)
    {
        thrust::copy(in1,in1+length,out);
        return;
    }
    if (N == 2.0f){
        thrust::square<float> op;
        thrust::transform(thrust::device,in1,in1+length,out,op);
        return;
    }
    thrust::transform(thrust::device,in1,in1+length,out,powf(_1,N));
    
}

