blob: 0f04ba49294487c2cf75b88d8f44705d4e37e609 [file]
#include "THCTensorMath.h"
#include "THCGeneral.h"
#include "THCBlas.h"
#include "THCTensorCopy.h"
#include "THCTensorRandom.h"
#include "THCApply.cuh"
#include "THCReduce.cuh"
#include <thrust/device_ptr.h>
#include <thrust/fill.h>
#include <thrust/functional.h>
#include <thrust/reduce.h>
#include <thrust/inner_product.h>
#ifndef DIVUP
#define DIVUP(x, y) (((x) + (y) - 1) / (y))
#endif
struct TensorFillOp {
TensorFillOp(float v) : val(v) {}
__device__ __forceinline__ void operator()(float* v) { *v = val; }
const float val;
};
void THCudaTensor_fill(THCState* state, THCudaTensor *self_, float value)
{
THAssert(THCudaTensor_checkGPU(state, 1, self_));
if (!THCudaTensor_pointwiseApply1(state, self_, TensorFillOp(value))) {
THArgCheck(false, 1, CUTORCH_DIM_WARNING);
}
THCudaCheck(cudaGetLastError());
}
void THCudaTensor_zero(THCState *state, THCudaTensor *self_)
{
THAssert(THCudaTensor_checkGPU(state, 1, self_));
if (THCudaTensor_isContiguous(state, self_)) {
THCudaCheck(cudaMemsetAsync(THCudaTensor_data(state, self_),
0,
sizeof(float) * THCudaTensor_nElement(state, self_),
THCState_getCurrentStream(state)));
} else {
if (!THCudaTensor_pointwiseApply1(state, self_, TensorFillOp(0))) {
THArgCheck(false, 1, CUTORCH_DIM_WARNING);
}
}
THCudaCheck(cudaGetLastError());
}
void THCudaTensor_zeros(THCState *state, THCudaTensor *r_, THLongStorage *size)
{
THAssert(THCudaTensor_checkGPU(state, 1, r_));
THCudaTensor_resize(state, r_, size, NULL);
THCudaTensor_zero(state, r_);
}
void THCudaTensor_ones(THCState *state, THCudaTensor *r_, THLongStorage *size)
{
THAssert(THCudaTensor_checkGPU(state, 1, r_));
THCudaTensor_resize(state, r_, size, NULL);
THCudaTensor_fill(state, r_, 1);
}
void THCudaTensor_reshape(THCState *state, THCudaTensor *r_, THCudaTensor *t, THLongStorage *size)
{
THAssert(THCudaTensor_checkGPU(state, 2, r_, t));
THCudaTensor_resize(state, r_, size, NULL);
THCudaTensor_copy(state, r_, t);
}
long THCudaTensor_numel(THCState *state, THCudaTensor *t)
{
return THCudaTensor_nElement(state, t);
}
struct TensorCPowOp {
__device__ __forceinline__ void operator()(float* out, float* in) {
*out = powf(*out, *in);
}
__device__ __forceinline__ void operator()(float* out, float* in1, float* in2) {
*out = powf(*in1, *in2);
}
};
void THCudaTensor_cpow(THCState *state, THCudaTensor *self_, THCudaTensor *src1, THCudaTensor *src2)
{
THAssert(THCudaTensor_checkGPU(state, 3, self_, src1, src2));
THArgCheck(THCudaTensor_nElement(state, src1) ==
THCudaTensor_nElement(state, src2), 3, "sizes do not match");
if (self_ == src1) {
// self = pow(self, src2)
if (!THCudaTensor_pointwiseApply2(state, self_, src2, TensorCPowOp())) {
THArgCheck(false, 2, CUTORCH_DIM_WARNING);
}
} else {
THCudaTensor_resizeAs(state, self_, src1);
// self = pow(src1, src2)
if (!THCudaTensor_pointwiseApply3(state, self_, src1, src2, TensorCPowOp())) {
THArgCheck(false, 2, CUTORCH_DIM_WARNING);
}
}
THCudaCheck(cudaGetLastError());
}
struct TensorDivOp {
__device__ __forceinline__ void
operator()(float* out, float* in) {
*out /= *in;
}
__device__ __forceinline__ void
operator()(float* out, float* in1, float* in2) {
*out = *in1 / *in2;
}
};
void THCudaTensor_cdiv(THCState* state, THCudaTensor *self_, THCudaTensor *src1, THCudaTensor *src2)
{
THAssert(THCudaTensor_checkGPU(state, 3, self_, src1, src2));
THArgCheck(THCudaTensor_nElement(state, src1) ==
THCudaTensor_nElement(state, src2), 3, "sizes do not match");
if (self_ == src1) {
// self *= src2
if (!THCudaTensor_pointwiseApply2(state, self_, src2, TensorDivOp())) {
THArgCheck(false, 2, CUTORCH_DIM_WARNING);
}
} else {
THCudaTensor_resizeAs(state, self_, src1);
// self = src1 * src2
if (!THCudaTensor_pointwiseApply3(state, self_, src1, src2, TensorDivOp())) {
THArgCheck(false, 2, CUTORCH_DIM_WARNING);
}
}
THCudaCheck(cudaGetLastError());
}
struct TensorAddCMulOp {
TensorAddCMulOp(float v) : val(v) {}
__device__ __forceinline__ void
operator()(float* out, float* in1, float* in2) {
*out += val * *in1 * *in2;
}
float val;
};
void THCudaTensor_addcmul(THCState *state, THCudaTensor *self_, THCudaTensor *t, float value, THCudaTensor *src1, THCudaTensor *src2)
{
THAssert(THCudaTensor_checkGPU(state, 4, self_, t, src1, src2));
if(self_ != t)
{
THCudaTensor_resizeAs(state, self_, t);
THCudaTensor_copy(state, self_, t);
}
THCudaTensor_resizeAs(state, self_, src1);
THArgCheck(THCudaTensor_nElement(state, src1) ==
THCudaTensor_nElement(state, src2), 3, "sizes do not match");
if (!THCudaTensor_pointwiseApply3(state, self_, src1, src2, TensorAddCMulOp(value))) {
THArgCheck(false, 2, CUTORCH_DIM_WARNING);
}
THCudaCheck(cudaGetLastError());
}
struct TensorAddCDivOp {
TensorAddCDivOp(float v) : val(v) {}
__device__ __forceinline__ void
operator()(float* out, float* in1, float* in2) {
*out += val * *in1 / *in2;
}
float val;
};
void THCudaTensor_addcdiv(THCState *state, THCudaTensor *self_, THCudaTensor *t, float value, THCudaTensor *src1, THCudaTensor *src2)
{
THAssert(THCudaTensor_checkGPU(state, 4, self_, t, src1, src2));
if(self_ != t)
{
THCudaTensor_resizeAs(state, self_, t);
THCudaTensor_copy(state, self_, t);
}
THCudaTensor_resizeAs(state, self_, src1);
THArgCheck(THCudaTensor_nElement(state, src1) == THCudaTensor_nElement(state, src2), 3, "sizes do not match");
if (!THCudaTensor_pointwiseApply3(state, self_, src1, src2, TensorAddCDivOp(value))) {
THArgCheck(false, 2, CUTORCH_DIM_WARNING);
}
THCudaCheck(cudaGetLastError());
}
float THCudaTensor_minall(THCState *state, THCudaTensor *self)
{
THAssert(THCudaTensor_checkGPU(state, 1, self));
self = THCudaTensor_newContiguous(state, self);
thrust::device_ptr<float> self_data(THCudaTensor_data(state, self));
float result = thrust::reduce(self_data, self_data+THCudaTensor_nElement(state, self), (float)(THInf), thrust::minimum<float>());
THCudaTensor_free(state, self);
return result;
}
float THCudaTensor_maxall(THCState *state, THCudaTensor *self)
{
THAssert(THCudaTensor_checkGPU(state, 1, self));
self = THCudaTensor_newContiguous(state, self);
thrust::device_ptr<float> self_data(THCudaTensor_data(state, self));
float result = thrust::reduce(self_data, self_data+THCudaTensor_nElement(state, self), (float)(-THInf), thrust::maximum<float>());
THCudaTensor_free(state, self);
return result;
}
float THCudaTensor_sumall(THCState *state, THCudaTensor *self)
{
THAssert(THCudaTensor_checkGPU(state, 1, self));
self = THCudaTensor_newContiguous(state, self);
thrust::device_ptr<float> self_data(THCudaTensor_data(state, self));
float result = thrust::reduce(self_data, self_data+THCudaTensor_nElement(state, self), (float)(0), thrust::plus<float>());
THCudaTensor_free(state, self);
return result;
}
float THCudaTensor_prodall(THCState *state, THCudaTensor *self)
{
THAssert(THCudaTensor_checkGPU(state, 1, self));
self = THCudaTensor_newContiguous(state, self);
thrust::device_ptr<float> self_data(THCudaTensor_data(state, self));
float result = thrust::reduce(self_data, self_data+THCudaTensor_nElement(state, self), (float)(1), thrust::multiplies<float>());
THCudaTensor_free(state, self);
return result;
}
struct dim4 {
unsigned arr[4];
__host__ dim4(unsigned init=0) {
for(unsigned i=0; i<4; i++) { arr[i] = init; }
}
__host__ __device__ unsigned& operator[](const unsigned& idx) { return arr[idx]; }
};
void THCudaTensor_sum(THCState* state, THCudaTensor *self, THCudaTensor *src, long dimension)
{
THAssert(THCudaTensor_checkGPU(state, 2, self, src));
THCudaTensor_reduceDim(
state, self, src,
thrust::identity<float>(), thrust::plus<float>(), 0.0f, dimension);
THCudaCheck(cudaGetLastError());
}
void THCudaTensor_prod(THCState* state, THCudaTensor *self, THCudaTensor *src, long dimension)
{
THAssert(THCudaTensor_checkGPU(state, 2, self, src));
THCudaTensor_reduceDim(
state, self, src,
thrust::identity<float>(), thrust::multiplies<float>(), 1.0f, dimension);
THCudaCheck(cudaGetLastError());
}
struct logicalall_functor
{
__host__ __device__ float operator()(const float& x, const float& y) const
{
return x && y;
}
};
struct logicalany_functor
{
__host__ __device__ float operator()(const float& x, const float& y) const
{
return x || y;
}
};
int THCudaTensor_logicalall(THCState *state, THCudaTensor *self) {
THAssert(THCudaTensor_checkGPU(state, 1, self));
self = THCudaTensor_newContiguous(state, self);
thrust::device_ptr<float> self_data(THCudaTensor_data(state, self));
int result = thrust::reduce(self_data, self_data+THCudaTensor_nElement(state, self), (float)(1), logicalall_functor());
THCudaTensor_free(state, self);
return result;
}
int THCudaTensor_logicalany(THCState *state, THCudaTensor *self) {
THAssert(THCudaTensor_checkGPU(state, 1, self));
self = THCudaTensor_newContiguous(state, self);
thrust::device_ptr<float> self_data(THCudaTensor_data(state, self));
int result = thrust::reduce(self_data, self_data+THCudaTensor_nElement(state, self), (float)(0), logicalany_functor());
THCudaTensor_free(state, self);
return result;
}