Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/torch/nn.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonan Collobert <ronan@collobert.com>2012-01-25 17:55:20 +0400
committerRonan Collobert <ronan@collobert.com>2012-01-25 17:55:20 +0400
commit4df3893abd1b9f840f1d9a8c1859799ccbf941de (patch)
treee8a1e1cc1b6ea6e47855347b157eaf419fdb357b /generic
initial revamp of torch7 tree
Diffstat (limited to 'generic')
-rw-r--r--generic/Abs.c43
-rw-r--r--generic/AbsCriterion.c54
-rw-r--r--generic/Exp.c43
-rw-r--r--generic/HardShrink.c50
-rw-r--r--generic/HardTanh.c50
-rw-r--r--generic/LogSigmoid.c49
-rw-r--r--generic/LogSoftMax.c111
-rw-r--r--generic/MSECriterion.c54
-rw-r--r--generic/Max.c100
-rw-r--r--generic/Min.c100
-rw-r--r--generic/MultiLabelMarginCriterion.c185
-rw-r--r--generic/MultiMarginCriterion.c162
-rw-r--r--generic/Sigmoid.c44
-rw-r--r--generic/SoftMax.c114
-rw-r--r--generic/SoftPlus.c44
-rw-r--r--generic/SoftShrink.c50
-rw-r--r--generic/SparseLinear.c130
-rw-r--r--generic/SpatialConvolution.c201
-rw-r--r--generic/SpatialConvolutionMap.c229
-rw-r--r--generic/SpatialMaxPooling.c163
-rw-r--r--generic/SpatialSubSampling.c278
-rw-r--r--generic/Sqrt.c46
-rw-r--r--generic/Square.c45
-rw-r--r--generic/Tanh.c45
-rw-r--r--generic/TemporalConvolution.c194
-rw-r--r--generic/TemporalSubSampling.c139
-rw-r--r--generic/Threshold.c47
-rw-r--r--generic/VolumetricConvolution.c118
28 files changed, 2888 insertions, 0 deletions
diff --git a/generic/Abs.c b/generic/Abs.c
new file mode 100644
index 0000000..8c65813
--- /dev/null
+++ b/generic/Abs.c
@@ -0,0 +1,43 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/Abs.c"
+#else
+
+static int nn_(Abs_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ *output_data = fabs(*input_data);)
+ return 1;
+}
+
+static int nn_(Abs_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, input);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \
+ real z = *input_data; \
+ *gradInput_data = *gradOutput_data * (z >= 0 ? 1 : -1);)
+ return 1;
+}
+
+static const struct luaL_Reg nn_(Abs__) [] = {
+ {"Abs_updateOutput", nn_(Abs_updateOutput)},
+ {"Abs_updateGradInput", nn_(Abs_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(Abs_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(Abs__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/AbsCriterion.c b/generic/AbsCriterion.c
new file mode 100644
index 0000000..b9b948d
--- /dev/null
+++ b/generic/AbsCriterion.c
@@ -0,0 +1,54 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/AbsCriterion.c"
+#else
+
+static int nn_(AbsCriterion_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage");
+ real sum;
+
+ sum = 0;
+ TH_TENSOR_APPLY2(real, input, real, target,
+ sum += fabs(*input_data - *target_data);)
+
+ if(sizeAverage)
+ sum /= THTensor_(nElement)(input);
+
+ lua_pushnumber(L, sum);
+ lua_setfield(L, 1, "output");
+
+ lua_pushnumber(L, sum);
+ return 1;
+}
+
+static int nn_(AbsCriterion_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage");
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+ real norm = (sizeAverage ? 1./((real)THTensor_(nElement)(input)) : 1.);
+
+ THTensor_(resizeAs)(gradInput, input);
+ TH_TENSOR_APPLY3(real, gradInput, real, input, real, target,
+ *gradInput_data = ( (*input_data - *target_data) >= 0 ? norm : -norm);)
+
+ return 1;
+}
+
+static const struct luaL_Reg nn_(AbsCriterion__) [] = {
+ {"AbsCriterion_updateOutput", nn_(AbsCriterion_updateOutput)},
+ {"AbsCriterion_updateGradInput", nn_(AbsCriterion_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(AbsCriterion_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(AbsCriterion__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/Exp.c b/generic/Exp.c
new file mode 100644
index 0000000..b56f379
--- /dev/null
+++ b/generic/Exp.c
@@ -0,0 +1,43 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/Exp.c"
+#else
+
+static int nn_(Exp_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ *output_data = exp(*input_data);)
+
+ return 1;
+}
+
+static int nn_(Exp_updateGradInput)(lua_State *L)
+{
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, output);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \
+ *gradInput_data = *gradOutput_data * *output_data;);
+ return 1;
+}
+
+static const struct luaL_Reg nn_(Exp__) [] = {
+ {"Exp_updateOutput", nn_(Exp_updateOutput)},
+ {"Exp_updateGradInput", nn_(Exp_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(Exp_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(Exp__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/HardShrink.c b/generic/HardShrink.c
new file mode 100644
index 0000000..be98ddc
--- /dev/null
+++ b/generic/HardShrink.c
@@ -0,0 +1,50 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/HardShrink.c"
+#else
+
+static int nn_(HardShrink_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ real lambda = luaT_getfieldchecknumber(L, 1, "lambda");
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ if ((*input_data) > lambda) *output_data = *input_data; \
+ else if ((*input_data) < -lambda) *output_data = *input_data; \
+ else *output_data = 0;);
+ return 1;
+}
+
+static int nn_(HardShrink_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ real lambda = luaT_getfieldchecknumber(L, 1, "lambda");
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, input);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \
+ if ((*input_data) > lambda || (*input_data) < -lambda) \
+ *gradInput_data = (*gradOutput_data); \
+ else \
+ *gradInput_data = 0; \
+ );
+ return 1;
+}
+
+static const struct luaL_Reg nn_(HardShrink__) [] = {
+ {"HardShrink_updateOutput", nn_(HardShrink_updateOutput)},
+ {"HardShrink_updateGradInput", nn_(HardShrink_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(HardShrink_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(HardShrink__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/HardTanh.c b/generic/HardTanh.c
new file mode 100644
index 0000000..3764095
--- /dev/null
+++ b/generic/HardTanh.c
@@ -0,0 +1,50 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/HardTanh.c"
+#else
+
+static int nn_(HardTanh_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ if(*input_data < -1) \
+ *output_data = -1; \
+ else if(*input_data <= 1) \
+ *output_data = *input_data; \
+ else \
+ *output_data = 1;)
+ return 1;
+}
+
+static int nn_(HardTanh_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, input);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \
+ if(*input_data < -1 || *input_data > 1) \
+ *gradInput_data = 0; \
+ else \
+ *gradInput_data = *gradOutput_data;);
+ return 1;
+}
+
+static const struct luaL_Reg nn_(HardTanh__) [] = {
+ {"HardTanh_updateOutput", nn_(HardTanh_updateOutput)},
+ {"HardTanh_updateGradInput", nn_(HardTanh_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(HardTanh_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(HardTanh__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/LogSigmoid.c b/generic/LogSigmoid.c
new file mode 100644
index 0000000..b5bdae4
--- /dev/null
+++ b/generic/LogSigmoid.c
@@ -0,0 +1,49 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/LogSigmoid.c"
+#else
+
+static int nn_(LogSigmoid_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *buffer = luaT_getfieldcheckudata(L, 1, "buffer", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+ THTensor_(resizeAs)(buffer, input);
+
+ TH_TENSOR_APPLY3(real, output, real, input, real, buffer, \
+ real z = exp(-*input_data); \
+ *buffer_data = z; \
+ *output_data = -log(1. + z);)
+
+ return 1;
+}
+
+static int nn_(LogSigmoid_updateGradInput)(lua_State *L)
+{
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *buffer = luaT_getfieldcheckudata(L, 1, "buffer", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, buffer);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, buffer, \
+ real z = *buffer_data; \
+ *gradInput_data = *gradOutput_data * z / (1. + z);)
+
+ return 1;
+}
+
+static const struct luaL_Reg nn_(LogSigmoid__) [] = {
+ {"LogSigmoid_updateOutput", nn_(LogSigmoid_updateOutput)},
+ {"LogSigmoid_updateGradInput", nn_(LogSigmoid_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(LogSigmoid_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(LogSigmoid__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/LogSoftMax.c b/generic/LogSoftMax.c
new file mode 100644
index 0000000..5d4dbfc
--- /dev/null
+++ b/generic/LogSoftMax.c
@@ -0,0 +1,111 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/LogSoftMax.c"
+#else
+
+static int nn_(LogSoftMax_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ real *input_data, *output_data;
+ long nframe = 0, dim = 0;
+ long t, d;
+
+ if(input->nDimension == 1)
+ {
+ nframe = 1;
+ dim = input->size[0];
+ }
+ else if(input->nDimension == 2)
+ {
+ nframe = input->size[0];
+ dim = input->size[1];
+ }
+ else
+ THArgCheck(0, 2, "vector or matrix expected");
+
+ input = THTensor_(newContiguous)(input);
+ THTensor_(resizeAs)(output, input);
+
+ input_data = THTensor_(data)(input);
+ output_data = THTensor_(data)(output);
+ for(t = 0; t < nframe; t++)
+ {
+ accreal logsum = 0;
+ real maxInput = -THInf;
+
+ for(d = 0; d < dim; d++)
+ maxInput = THMax(maxInput, input_data[d]);
+
+ for(d = 0; d < dim; d++)
+ logsum += THExpMinusApprox(maxInput-input_data[d]);
+ logsum = maxInput + log(logsum);
+
+ for(d = 0; d < dim; d++)
+ output_data[d] = input_data[d] - logsum;
+
+ input_data += dim;
+ output_data += dim;
+ }
+
+ THTensor_(free)(input);
+
+ return 1;
+}
+
+static int nn_(LogSoftMax_updateGradInput)(lua_State *L)
+{
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+ real *gradInput_data, *gradOutput_data, *output_data;
+ long nframe = 0, dim = 0;
+ long t, d;
+
+ if(output->nDimension == 1)
+ {
+ nframe = 1;
+ dim = output->size[0];
+ }
+ else if(output->nDimension == 2)
+ {
+ nframe = output->size[0];
+ dim = output->size[1];
+ }
+ else
+ THError("vector or matrix expected");
+
+ THTensor_(resizeAs)(gradInput, output);
+ gradInput_data = THTensor_(data)(gradInput);
+ output_data = THTensor_(data)(output);
+ gradOutput_data = THTensor_(data)(gradOutput);
+ for(t = 0; t < nframe; t++)
+ {
+ accreal sum = 0;
+ for(d = 0; d < dim; d++)
+ sum += gradOutput_data[d];
+
+ for(d = 0; d < dim; d++)
+ gradInput_data[d] = gradOutput_data[d] - exp(output_data[d])*sum;
+
+ gradInput_data += dim;
+ output_data += dim;
+ gradOutput_data += dim;
+ }
+
+ return 1;
+}
+
+static const struct luaL_Reg nn_(LogSoftMax__) [] = {
+ {"LogSoftMax_updateOutput", nn_(LogSoftMax_updateOutput)},
+ {"LogSoftMax_updateGradInput", nn_(LogSoftMax_updateGradInput)},
+ {NULL, NULL}
+};
+
+void nn_(LogSoftMax_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(LogSoftMax__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/MSECriterion.c b/generic/MSECriterion.c
new file mode 100644
index 0000000..c53735c
--- /dev/null
+++ b/generic/MSECriterion.c
@@ -0,0 +1,54 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/MSECriterion.c"
+#else
+
+static int nn_(MSECriterion_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage");
+ real sum;
+
+ sum = 0;
+ TH_TENSOR_APPLY2(real, input, real, target,
+ real z = (*input_data - *target_data);
+ sum += z*z;)
+
+ if(sizeAverage)
+ sum /= THTensor_(nElement)(input);
+
+ lua_pushnumber(L, sum);
+ lua_setfield(L, 1, "output");
+
+ lua_pushnumber(L, sum);
+ return 1;
+}
+
+static int nn_(MSECriterion_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage");
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+ real norm = (sizeAverage ? 2./((real)THTensor_(nElement)(input)) : 2.);
+
+ THTensor_(resizeAs)(gradInput, input);
+ TH_TENSOR_APPLY3(real, gradInput, real, input, real, target,
+ *gradInput_data = norm * (*input_data - *target_data);)
+ return 1;
+}
+
+static const struct luaL_Reg nn_(MSECriterion__) [] = {
+ {"MSECriterion_updateOutput", nn_(MSECriterion_updateOutput)},
+ {"MSECriterion_updateGradInput", nn_(MSECriterion_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(MSECriterion_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(MSECriterion__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/Max.c b/generic/Max.c
new file mode 100644
index 0000000..87f52f1
--- /dev/null
+++ b/generic/Max.c
@@ -0,0 +1,100 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/Max.c"
+#else
+
+static int nn_(Max_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int dimension = luaT_getfieldcheckint(L, 1, "dimension")-1;
+ THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THLongStorage *dim;
+ long i;
+
+ luaL_argcheck(L, dimension >= 0 && dimension < input->nDimension, 2, "dimension out of range");
+
+ dim = THLongStorage_newWithSize(input->nDimension);
+ for(i = 0; i < input->nDimension; i++)
+ dim->data[i] = input->size[i];
+ dim->data[dimension] = 1;
+ THTensor_(resize)(output, dim, NULL);
+ THTensor_(resize)(indices, dim, NULL);
+ THLongStorage_free(dim);
+
+ TH_TENSOR_DIM_APPLY3(real, output, real, input, real, indices, dimension,
+ long theIndex = 0;
+ real theMax = input_data[0];
+ for(i = 1; i < input_size; i++)
+ {
+ if(input_data[i*input_stride] > theMax)
+ {
+ theIndex = i;
+ theMax = input_data[i*input_stride];
+ }
+ }
+ *indices_data = theIndex+1;
+ *output_data = theMax;)
+
+ THTensor_(select)(output, NULL, dimension, 0);
+
+ return 1;
+}
+
+static int nn_(Max_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id));
+ int dimension = luaT_getfieldcheckint(L, 1, "dimension")-1;
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor *gradOutputPlusOneDim;
+ THLongStorage *dim, *str;
+ int i, j;
+
+ THTensor_(resizeAs)(gradInput, input);
+ THTensor_(zero)(gradInput);
+
+ dim = THLongStorage_newWithSize(gradOutput->nDimension+1);
+ str = THLongStorage_newWithSize(gradOutput->nDimension+1);
+ for(i = 0, j = 0; j < gradOutput->nDimension+1; j++)
+ {
+ if(j == dimension)
+ {
+ dim->data[j] = input->size[dimension];
+ str->data[j] = 0;
+ continue;
+ }
+
+ dim->data[j] = gradOutput->size[i];
+ str->data[j] = gradOutput->stride[i];
+ i++;
+ }
+
+ gradOutputPlusOneDim = THTensor_(newWithStorage)(gradOutput->storage, gradOutput->storageOffset, dim, str);
+ THLongStorage_free(dim);
+ THLongStorage_free(str);
+
+ TH_TENSOR_DIM_APPLY3(real, gradInput, real, gradOutputPlusOneDim, real, indices, dimension,
+ gradInput_data[ ((long)(*indices_data)-1)*gradInput_stride ] = *gradOutputPlusOneDim_data;)
+
+ THTensor_(free)(gradOutputPlusOneDim);
+
+ return 1;
+}
+
+static const struct luaL_Reg nn_(Max__) [] = {
+ {"Max_updateOutput", nn_(Max_updateOutput)},
+ {"Max_updateGradInput", nn_(Max_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(Max_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(Max__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/Min.c b/generic/Min.c
new file mode 100644
index 0000000..d3309df
--- /dev/null
+++ b/generic/Min.c
@@ -0,0 +1,100 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/Min.c"
+#else
+
+static int nn_(Min_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int dimension = luaT_getfieldcheckint(L, 1, "dimension")-1;
+ THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THLongStorage *dim;
+ long i;
+
+ luaL_argcheck(L, dimension >= 0 && dimension < input->nDimension, 2, "dimension out of range");
+
+ dim = THLongStorage_newWithSize(input->nDimension);
+ for(i = 0; i < input->nDimension; i++)
+ dim->data[i] = input->size[i];
+ dim->data[dimension] = 1;
+ THTensor_(resize)(output, dim, NULL);
+ THTensor_(resize)(indices, dim, NULL);
+ THLongStorage_free(dim);
+
+ TH_TENSOR_DIM_APPLY3(real, output, real, input, real, indices, dimension,
+ long theIndex = 0;
+ real theMin = input_data[0];
+ for(i = 1; i < input_size; i++)
+ {
+ if(input_data[i*input_stride] < theMin)
+ {
+ theIndex = i;
+ theMin = input_data[i*input_stride];
+ }
+ }
+ *indices_data = theIndex+1;
+ *output_data = theMin;)
+
+ THTensor_(select)(output, NULL, dimension, 0);
+
+ return 1;
+}
+
+static int nn_(Min_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id));
+ int dimension = luaT_getfieldcheckint(L, 1, "dimension")-1;
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor *gradOutputPlusOneDim;
+ THLongStorage *dim, *str;
+ int i, j;
+
+ THTensor_(resizeAs)(gradInput, input);
+ THTensor_(zero)(gradInput);
+
+ dim = THLongStorage_newWithSize(gradOutput->nDimension+1);
+ str = THLongStorage_newWithSize(gradOutput->nDimension+1);
+ for(i = 0, j = 0; j < gradOutput->nDimension+1; j++)
+ {
+ if(j == dimension)
+ {
+ dim->data[j] = input->size[dimension];
+ str->data[j] = 0;
+ continue;
+ }
+
+ dim->data[j] = gradOutput->size[i];
+ str->data[j] = gradOutput->stride[i];
+ i++;
+ }
+
+ gradOutputPlusOneDim = THTensor_(newWithStorage)(gradOutput->storage, gradOutput->storageOffset, dim, str);
+ THLongStorage_free(dim);
+ THLongStorage_free(str);
+
+ TH_TENSOR_DIM_APPLY3(real, gradInput, real, gradOutputPlusOneDim, real, indices, dimension,
+ gradInput_data[ ((long)(*indices_data)-1)*gradInput_stride ] = *gradOutputPlusOneDim_data;)
+
+ THTensor_(free)(gradOutputPlusOneDim);
+
+ return 1;
+}
+
+static const struct luaL_Reg nn_(Min__) [] = {
+ {"Min_updateOutput", nn_(Min_updateOutput)},
+ {"Min_updateGradInput", nn_(Min_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(Min_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(Min__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/MultiLabelMarginCriterion.c b/generic/MultiLabelMarginCriterion.c
new file mode 100644
index 0000000..f4c3914
--- /dev/null
+++ b/generic/MultiLabelMarginCriterion.c
@@ -0,0 +1,185 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/MultiLabelMarginCriterion.c"
+#else
+
+static int nn_(MultiLabelMarginCriterion_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage");
+ real *input_data, *target_data;
+ long nframe, dim;
+ long t, d, dt, ddt;
+ THTensor *target;
+ real sum;
+
+ THArgCheck((input->nDimension == 1) || (input->nDimension == 2), 2, "vector or matrix expected");
+
+ if(input->nDimension == 1)
+ {
+ nframe = 1;
+ dim = input->size[0];
+ target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THArgCheck((target->nDimension == 1) && (target->size[0] == dim), 3, "inconsistent target size");
+ }
+ else
+ {
+ nframe = input->size[0];
+ dim = input->size[1];
+ target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THArgCheck((target->nDimension == 2) && (target->size[0] == nframe) && (target->size[1] == dim), 3, "inconsistent target size");
+ }
+
+ THArgCheck(THTensor_(minall)(target) >= 0, 3, "target out of range");
+ THArgCheck(THTensor_(maxall)(target) <= dim, 3, "target out of range");
+
+ target = THTensor_(newContiguous)(target);
+ input = THTensor_(newContiguous)(input);
+ input_data = THTensor_(data)(input);
+ target_data = THTensor_(data)(target);
+
+ sum = 0;
+ for(t = 0; t < nframe; t++)
+ {
+ for(dt = 0; dt < dim; dt++)
+ {
+ long target_idx = (long)target_data[dt]-1;
+ real input_target;
+ if(target_idx < 0)
+ break;
+
+ input_target = input_data[target_idx];
+ for(d = 0; d < dim; d++)
+ {
+ int istarget = 0;
+ for(ddt = 0; ddt < dim; ddt++)
+ {
+ if(!target_data[ddt])
+ break;
+ if(((long)target_data[ddt])-1 == d)
+ istarget = 1;
+ }
+
+ if(!istarget)
+ {
+ real z = 1 - input_target + input_data[d];
+ if(z > 0)
+ sum += z;
+ }
+ }
+ }
+ input_data += dim;
+ target_data += dim;
+ }
+
+ if(sizeAverage)
+ sum /= dim;
+
+ lua_pushnumber(L, sum);
+ lua_setfield(L, 1, "output");
+
+ THTensor_(free)(input);
+ THTensor_(free)(target);
+ lua_pushnumber(L, sum);
+ return 1;
+}
+
+static int nn_(MultiLabelMarginCriterion_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage");
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+ real *input_data;
+ real *gradInput_data;
+ real *target_data;
+ long nframe, dim;
+ long t, d, dt, ddt;
+ THTensor *target;
+ real g;
+
+ THArgCheck((input->nDimension == 1) || (input->nDimension == 2), 2, "vector or matrix expected");
+
+ if(input->nDimension == 1)
+ {
+ nframe = 1;
+ dim = input->size[0];
+ target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THArgCheck((target->nDimension == 1) && (target->size[0] == dim), 3, "inconsistent target size");
+ }
+ else
+ {
+ nframe = input->size[0];
+ dim = input->size[1];
+ target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THArgCheck((target->nDimension == 2) && (target->size[0] == nframe) && (target->size[1] == dim), 3, "inconsistent target size");
+ }
+
+ THArgCheck(THTensor_(minall)(target) >= 0, 3, "target out of range");
+ THArgCheck(THTensor_(maxall)(target) <= dim, 3, "target out of range");
+
+ target = THTensor_(newContiguous)(target);
+ input = THTensor_(newContiguous)(input);
+ input_data = THTensor_(data)(input);
+ target_data = THTensor_(data)(target);
+
+ g = (sizeAverage ? 1./((real)dim) : 1.);
+
+ THTensor_(resizeAs)(gradInput, input);
+ THTensor_(zero)(gradInput);
+ gradInput_data = THTensor_(data)(gradInput);
+
+ for(t = 0; t < nframe; t++)
+ {
+ for(dt = 0; dt < dim; dt++)
+ {
+ long target_idx = (long)target_data[dt]-1;
+ real input_target;
+ if(target_idx < 0)
+ break;
+
+ input_target = input_data[target_idx];
+ for(d = 0; d < dim; d++)
+ {
+ int istarget = 0;
+ for(ddt = 0; ddt < dim; ddt++)
+ {
+ if(!target_data[ddt])
+ break;
+ if(((long)target_data[ddt])-1 == d)
+ istarget = 1;
+ }
+
+ if(!istarget)
+ {
+ real z = 1 - input_target + input_data[d];
+ if(z > 0)
+ {
+ gradInput_data[target_idx] -= g;
+ gradInput_data[d] += g;
+ }
+ }
+ }
+ }
+ input_data += dim;
+ target_data += dim;
+ gradInput_data += dim;
+ }
+
+ THTensor_(free)(input);
+ THTensor_(free)(target);
+ return 1;
+}
+
+static const struct luaL_Reg nn_(MultiLabelMarginCriterion__) [] = {
+ {"MultiLabelMarginCriterion_updateOutput", nn_(MultiLabelMarginCriterion_updateOutput)},
+ {"MultiLabelMarginCriterion_updateGradInput", nn_(MultiLabelMarginCriterion_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(MultiLabelMarginCriterion_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(MultiLabelMarginCriterion__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/MultiMarginCriterion.c b/generic/MultiMarginCriterion.c
new file mode 100644
index 0000000..ca73bc9
--- /dev/null
+++ b/generic/MultiMarginCriterion.c
@@ -0,0 +1,162 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/MultiMarginCriterion.c"
+#else
+
+static int nn_(MultiMarginCriterion_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage");
+ real *input_data, *target_data;
+ long nframe, dim;
+ long t, d;
+ real target_;
+ THTensor *target;
+ real sum;
+
+ THArgCheck((input->nDimension == 1) || (input->nDimension == 2), 2, "vector or matrix expected");
+
+ if(input->nDimension == 1)
+ {
+ nframe = 1;
+ dim = input->size[0];
+ target_ = luaL_checknumber(L, 3);
+ target = THTensor_(newWithSize1d)(1);
+ THTensor_(fill)(target, target_);
+ }
+ else
+ {
+ nframe = input->size[0];
+ dim = input->size[1];
+ target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THArgCheck((target->nDimension == 1) && (target->size[0] == nframe), 3, "inconsistent target size");
+ target = THTensor_(newContiguous)(target);
+ }
+
+ for(t = 0; t < nframe; t++)
+ {
+ real idx = THTensor_(get1d)(target, t);
+ THArgCheck((idx >= 1) && (idx <= dim), 3, "target out of range");
+ }
+
+ input = THTensor_(newContiguous)(input);
+ input_data = THTensor_(data)(input);
+ target_data = THTensor_(data)(target);
+
+ sum = 0;
+ for(t = 0; t < nframe; t++)
+ {
+ long target_idx = (long)(target_data[t]-1);
+ real input_target = input_data[target_idx];
+ for(d = 0; d < dim; d++)
+ {
+ real z = 1 - input_target + input_data[d];
+ if(d == target_idx)
+ continue;
+
+ if(z > 0)
+ sum += z;
+ }
+ input_data += dim;
+ }
+
+ if(sizeAverage)
+ sum /= dim;
+
+ lua_pushnumber(L, sum);
+ lua_setfield(L, 1, "output");
+
+ THTensor_(free)(input);
+ THTensor_(free)(target);
+ lua_pushnumber(L, sum);
+ return 1;
+}
+
+static int nn_(MultiMarginCriterion_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage");
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+ real *input_data;
+ real *gradInput_data;
+ real *target_data;
+ THTensor *target;
+ long nframe, dim;
+ long t, d;
+ real target_;
+ real g;
+ real sum;
+
+ THArgCheck((input->nDimension == 1) || (input->nDimension == 2), 2, "vector or matrix expected");
+
+ if(input->nDimension == 1)
+ {
+ nframe = 1;
+ dim = input->size[0];
+ target_ = luaL_checknumber(L, 3);
+ target = THTensor_(newWithSize1d)(1);
+ THTensor_(fill)(target, target_);
+ }
+ else
+ {
+ nframe = input->size[0];
+ dim = input->size[1];
+ target = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THArgCheck((target->nDimension == 1) && (target->size[0] == nframe), 3, "inconsistent target size");
+ target = THTensor_(newContiguous)(target);
+ }
+
+ g = (sizeAverage ? 1./((real)dim) : 1.);
+
+ input = THTensor_(newContiguous)(input);
+ input_data = THTensor_(data)(input);
+
+ THTensor_(resizeAs)(gradInput, input);
+ gradInput_data = THTensor_(data)(gradInput);
+
+ target_data = THTensor_(data)(target);
+
+ for(t = 0; t < nframe; t++)
+ {
+ long target_idx = (long)(target_data[t])-1;
+ real input_target = input_data[target_idx];
+ real gradInput_target = 0;
+ for(d = 0; d < dim; d++)
+ {
+ real z = 1 - input_target + input_data[d];
+ if(d == target_idx)
+ continue;
+
+ if(z > 0)
+ {
+ gradInput_target -= g;
+ gradInput_data[d] = g;
+ }
+ else
+ gradInput_data[d] = 0;
+ }
+ gradInput_data[target_idx] = gradInput_target;
+
+ input_data += dim;
+ gradInput_data += dim;
+ }
+
+
+ THTensor_(free)(input);
+ THTensor_(free)(target);
+ return 1;
+}
+
+static const struct luaL_Reg nn_(MultiMarginCriterion__) [] = {
+ {"MultiMarginCriterion_updateOutput", nn_(MultiMarginCriterion_updateOutput)},
+ {"MultiMarginCriterion_updateGradInput", nn_(MultiMarginCriterion_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(MultiMarginCriterion_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(MultiMarginCriterion__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/Sigmoid.c b/generic/Sigmoid.c
new file mode 100644
index 0000000..20348b9
--- /dev/null
+++ b/generic/Sigmoid.c
@@ -0,0 +1,44 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/Sigmoid.c"
+#else
+
+static int nn_(Sigmoid_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ *output_data = 1./(1.+ exp(- *input_data));)
+
+ return 1;
+}
+
+static int nn_(Sigmoid_updateGradInput)(lua_State *L)
+{
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, output);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \
+ real z = *output_data; \
+ *gradInput_data = *gradOutput_data * (1. - z) * z;)
+ return 1;
+}
+
+static const struct luaL_Reg nn_(Sigmoid__) [] = {
+ {"Sigmoid_updateOutput", nn_(Sigmoid_updateOutput)},
+ {"Sigmoid_updateGradInput", nn_(Sigmoid_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(Sigmoid_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(Sigmoid__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/SoftMax.c b/generic/SoftMax.c
new file mode 100644
index 0000000..3aaae65
--- /dev/null
+++ b/generic/SoftMax.c
@@ -0,0 +1,114 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/SoftMax.c"
+#else
+
+static int nn_(SoftMax_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ real *input_data, *output_data;
+ long nframe = 0, dim = 0;
+ long t, d;
+
+ if(input->nDimension == 1)
+ {
+ nframe = 1;
+ dim = input->size[0];
+ }
+ else if(input->nDimension == 2)
+ {
+ nframe = input->size[0];
+ dim = input->size[1];
+ }
+ else
+ THArgCheck(0, 2, "vector or matrix expected");
+
+ input = THTensor_(newContiguous)(input);
+ THTensor_(resizeAs)(output, input);
+
+ input_data = THTensor_(data)(input);
+ output_data = THTensor_(data)(output);
+ for(t = 0; t < nframe; t++)
+ {
+ real inputMax = -THInf;
+ for(d = 0; d < dim; d++) {
+ if (input_data[d] >= inputMax) inputMax = input_data[d];
+ }
+
+ accreal sum = 0;
+ for(d = 0; d < dim; d++) {
+ real z = THExpMinusApprox(inputMax - input_data[d]);
+ output_data[d] = z;
+ sum += z;
+ }
+
+ for(d = 0; d < dim; d++) {
+ output_data[d] *= 1/sum;
+ }
+
+ input_data += dim;
+ output_data += dim;
+ }
+
+ THTensor_(free)(input);
+
+ return 1;
+}
+
+static int nn_(SoftMax_updateGradInput)(lua_State *L)
+{
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+ real *gradInput_data, *gradOutput_data, *output_data;
+ long nframe = 0, dim = 0;
+ long t, d;
+
+ if(output->nDimension == 1)
+ {
+ nframe = 1;
+ dim = output->size[0];
+ }
+ else if(output->nDimension == 2)
+ {
+ nframe = output->size[0];
+ dim = output->size[1];
+ }
+ else
+ THError("vector or matrix expected");
+
+ THTensor_(resizeAs)(gradInput, output);
+ gradInput_data = THTensor_(data)(gradInput);
+ output_data = THTensor_(data)(output);
+ gradOutput_data = THTensor_(data)(gradOutput);
+ for(t = 0; t < nframe; t++)
+ {
+ accreal sum = 0;
+ for(d = 0; d < dim; d++)
+ sum += (accreal)gradOutput_data[d] * output_data[d];
+
+ for(d = 0; d < dim; d++)
+ gradInput_data[d] = output_data[d] * (gradOutput_data[d] - sum);
+
+ gradInput_data += dim;
+ output_data += dim;
+ gradOutput_data += dim;
+ }
+
+ return 1;
+}
+
+static const struct luaL_Reg nn_(SoftMax__) [] = {
+ {"SoftMax_updateOutput", nn_(SoftMax_updateOutput)},
+ {"SoftMax_updateGradInput", nn_(SoftMax_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(SoftMax_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(SoftMax__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/SoftPlus.c b/generic/SoftPlus.c
new file mode 100644
index 0000000..7a097fb
--- /dev/null
+++ b/generic/SoftPlus.c
@@ -0,0 +1,44 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/SoftPlus.c"
+#else
+
+static int nn_(SoftPlus_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ *output_data = log1p(exp(*input_data));)
+
+ return 1;
+}
+
+static int nn_(SoftPlus_updateGradInput)(lua_State *L)
+{
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, output);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \
+ real z = exp(*output_data); \
+ *gradInput_data = *gradOutput_data * (z - 1.)/z;)
+ return 1;
+}
+
+static const struct luaL_Reg nn_(SoftPlus__) [] = {
+ {"SoftPlus_updateOutput", nn_(SoftPlus_updateOutput)},
+ {"SoftPlus_updateGradInput", nn_(SoftPlus_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(SoftPlus_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(SoftPlus__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/SoftShrink.c b/generic/SoftShrink.c
new file mode 100644
index 0000000..0bc4075
--- /dev/null
+++ b/generic/SoftShrink.c
@@ -0,0 +1,50 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/SoftShrink.c"
+#else
+
+static int nn_(SoftShrink_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ real lambda = luaT_getfieldchecknumber(L, 1, "lambda");
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ if ((*input_data) > lambda) *output_data = *input_data - lambda; \
+ else if ((*input_data) < -lambda) *output_data = *input_data + lambda; \
+ else *output_data = 0;);
+ return 1;
+}
+
+static int nn_(SoftShrink_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ real lambda = luaT_getfieldchecknumber(L, 1, "lambda");
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, input);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \
+ if ((*input_data) > lambda || (*input_data) < -lambda) \
+ *gradInput_data = (*gradOutput_data); \
+ else \
+ *gradInput_data = 0; \
+ );
+ return 1;
+}
+
+static const struct luaL_Reg nn_(SoftShrink__) [] = {
+ {"SoftShrink_updateOutput", nn_(SoftShrink_updateOutput)},
+ {"SoftShrink_updateGradInput", nn_(SoftShrink_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(SoftShrink_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(SoftShrink__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/SparseLinear.c b/generic/SparseLinear.c
new file mode 100644
index 0000000..d29a1aa
--- /dev/null
+++ b/generic/SparseLinear.c
@@ -0,0 +1,130 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/SparseLinear.c"
+#else
+
+static int nn_(SparseLinear_updateOutput)(lua_State *L)
+{
+ long i;
+ THTensor * input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor * weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor * bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id));
+ THTensor * output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ long dim = weight->size[0]; /* number of weights.. */
+
+ THTensor_(copy)(output, bias);
+ for(i = 0; i < input->size[1]; i++)
+ {
+ long offset = (long)(THTensor_(get2d)(input, 0, i))-1;
+
+ if(offset >= 0 && offset < dim) /* make sure indices are in bounds.. */
+ {
+ real val = THTensor_(get2d)(input, 1, i);
+ THBlas_(axpy)(output->size[0],
+ val,
+ THTensor_(data)(weight)+offset*weight->stride[0],
+ weight->stride[1],
+ THTensor_(data)(output),
+ output->stride[0]);
+ }
+ else
+ luaL_error(L, "index out of bound");
+ }
+ return 1;
+}
+
+static int nn_(SparseLinear_accGradParameters)(lua_State *L)
+{
+ long i;
+ THTensor * input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor * gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ real scale = luaL_optnumber(L, 4, 1);
+ THTensor * weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor * output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ THTensor * gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id));
+ THTensor * gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id));
+ THTensor * lastInput = luaT_getfieldcheckudata(L, 1, "lastInput", torch_(Tensor_id));
+ real weightDecay = luaT_getfieldchecknumber(L, 1, "weightDecay");
+ long dim = gradWeight->size[0]; /* number of weights.. */
+
+ for(i = 0; i < input->size[1]; i++)
+ {
+ long offset = (long)(THTensor_(get2d)(input, 0, i))-1;
+
+ if(offset >= 0 && offset < dim) /* make sure indices are in bounds.. */
+ {
+ real val = scale*THTensor_(get2d)(input, 1, i);
+ THBlas_(scal)(gradOutput->size[0],
+ 0,
+ THTensor_(data)(gradWeight)+offset*gradWeight->stride[0],
+ gradWeight->stride[1]); /* zero */
+
+ THBlas_(axpy)(gradOutput->size[0],
+ val,
+ THTensor_(data)(gradOutput),
+ gradOutput->stride[0],
+ THTensor_(data)(gradWeight)+offset*gradWeight->stride[0],
+ gradWeight->stride[1]);
+ }
+ else
+ luaL_error(L, "index out of bound");
+ }
+
+ THTensor_(cadd)(gradBias, gradBias, 1, gradOutput);
+
+ if(weightDecay != 0)
+ THTensor_(cadd)(gradWeight, gradWeight, weightDecay, weight);
+
+ THTensor_(resizeAs)(lastInput, input);
+ THTensor_(copy)(lastInput, input);
+
+ return 0;
+}
+
+int nn_(SparseLinear_updateParameters)(lua_State *L)
+{
+ long i;
+ real learningRate = luaL_checknumber(L, 2);
+ THTensor * weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor * output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ THTensor * bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id));
+ THTensor * gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id));
+ THTensor * gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id));
+ THTensor * lastInput = luaT_getfieldcheckudata(L, 1, "lastInput", torch_(Tensor_id));
+ real weightDecay = luaT_getfieldchecknumber(L, 1, "weightDecay");
+
+ long dim = weight->size[0]; /* number of weights.. */
+ THTensor_(cadd)(bias, bias, -learningRate, gradBias);
+
+ for(i = 0; i < lastInput->size[1]; i++)
+ {
+ long offset = (long)(THTensor_(get2d)(lastInput, 0, i))-1;
+
+ if(offset >= 0 && offset < dim) /* make sure indices are in bounds.. */
+ {
+ THBlas_(axpy)(bias->size[0],
+ -learningRate,
+ THTensor_(data)(gradWeight)+offset*gradWeight->stride[0],
+ gradWeight->stride[1],
+ THTensor_(data)(weight)+offset*weight->stride[0],
+ weight->stride[1]);
+ }
+ else
+ luaL_error(L, "index out of bound");
+ }
+ return 0;
+}
+
+static const struct luaL_Reg nn_(SparseLinear__) [] = {
+ {"SparseLinear_updateOutput", nn_(SparseLinear_updateOutput)},
+ {"SparseLinear_updateParameters", nn_(SparseLinear_updateParameters)},
+ {NULL, NULL}
+};
+
+void nn_(SparseLinear_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(SparseLinear__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/SpatialConvolution.c b/generic/SpatialConvolution.c
new file mode 100644
index 0000000..de0de1d
--- /dev/null
+++ b/generic/SpatialConvolution.c
@@ -0,0 +1,201 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/SpatialConvolution.c"
+#else
+
+static void nn_(convolution_updateOutput_)(THTensor *input, THTensor *output, THTensor *weight, THTensor *bias, int dH, int dW)
+{
+ /* add bias */
+ long i;
+ THTensor *outn = THTensor_(new)();
+ for (i=0; i<bias->size[0]; i++) {
+ THTensor_(select)(outn,output,0,i);
+ THTensor_(fill)(outn, THTensor_(get1d)(bias, i));
+ }
+ THTensor_(free)(outn);
+
+ /* do convolutions */
+ THTensor_(conv2Dmv)(output, 1.0, 1.0, input, weight, dH, dW, "V","X");
+}
+
+static int nn_(SpatialConvolution_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ luaL_argcheck(L, input->nDimension == 3 || input->nDimension == 4, 2, "3D or 4D(batch mode) tensor expected");
+
+ int dimw = 2;
+ int dimh = 1;
+ if (input->nDimension == 4) {
+ dimw++;
+ dimh++;
+ }
+
+ long nOutputPlane = weight->size[0];
+ long nInputPlane = weight->size[1];
+ long kW = weight->size[3];
+ long kH = weight->size[2];
+ long inputWidth = input->size[dimw];
+ long inputHeight = input->size[dimh];
+ long outputWidth = (inputWidth - kW) / dW + 1;
+ long outputHeight = (inputHeight - kH) / dH + 1;
+
+ if (input->nDimension == 3)
+ {
+ THTensor_(resize3d)(output, nOutputPlane, outputHeight, outputWidth);
+/* printf("\n*************\nstochastic\n"); */
+/* printf("no=%d\n",output->nDimension); */
+/* printf("no=%ld,%ld,%ld\n",nOutputPlane,outputHeight,outputWidth); */
+/* printf("ni=%d\n",input->nDimension); */
+ nn_(convolution_updateOutput_)(input,output,weight,bias,dH,dW);
+/* printf("stochastic\n");*/
+ }
+ else
+ {
+ THTensor_(resize4d)(output, input->size[0], nOutputPlane, outputHeight, outputWidth);
+ THTensor *outn = THTensor_(new)();
+ THTensor *inpn = THTensor_(new)();
+ long i;
+ for (i=0; i<input->size[0]; i++)
+ {
+ THTensor_(select)(outn,output,0,i);
+ THTensor_(select)(inpn,input,0,i);
+ nn_(convolution_updateOutput_)(inpn,outn,weight,bias,dH,dW);
+ }
+ THTensor_(free)(outn);
+ THTensor_(free)(inpn);
+ }
+
+/* /\* add bias *\/ */
+/* long i; */
+/* THTensor *outn = THTensor_(new)(); */
+/* for (i=0; i<bias->size[0]; i++) { */
+/* THTensor_(select)(outn,output,0,i); */
+/* THTensor_(fill)(outn, THTensor_(get1d)(bias, i)); */
+/* } */
+/* THTensor_(free)(outn); */
+
+/* /\* do convolutions *\/ */
+/* THTensor_(conv2Dmv)(output, 1.0, 1.0, input, weight, dH, dW, "vx"); */
+
+ return 1;
+}
+
+
+static int nn_(SpatialConvolution_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THArgCheck( nOutputPlane == gradOutput->size[input->nDimension == 4 ? 1 : 0], 1, "Number of output features is not equal to nOutputPlane" );
+
+ long k;
+
+ /* gradient to input */
+ THTensor *tweight = THTensor_(newTranspose)(weight,0,1);
+
+ if(input->nDimension == 3)
+ {
+ THTensor_(conv2Dmv)(gradInput, 0.0, 1.0, gradOutput, tweight, dH, dW, "F", "C");
+ }
+ else
+ {
+
+ THTensor_(resizeAs)(gradInput,input);
+ THTensor *outn = THTensor_(new)();
+ THTensor *inpn = THTensor_(new)();
+ long i;
+ for (i=0; i<input->size[0]; i++)
+ {
+ THTensor_(select)(outn,gradOutput,0,i);
+ THTensor_(select)(inpn,gradInput,0,i);
+ THTensor_(conv2Dmv)(inpn, 0.0, 1.0, outn, tweight, dH, dW, "F", "C");
+ }
+ THTensor_(free)(outn);
+ THTensor_(free)(inpn);
+ }
+ THTensor_(free)(tweight);
+
+ return 1;
+}
+
+static void nn_(convolution_accGradParameters_)(THTensor *input, THTensor *gradOutput, THTensor *gradWeight, THTensor *gradBias, real scale, int dH, int dW)
+{
+ long k;
+
+ /* gradient to bias */
+ real *gradBias_data = THTensor_(data)(gradBias);
+ THTensor* gradOutSlice = THTensor_(new)();
+ for(k = 0; k < gradOutput->size[0]; k++)
+ {
+ THTensor_(select)(gradOutSlice, gradOutput, 0, k);
+ gradBias_data[k] += scale*THTensor_(sumall)(gradOutSlice);
+ }
+ THTensor_(free)(gradOutSlice);
+
+ /* gradient to kernels */
+ THTensor_(conv2DRevger)(gradWeight, 1.0, scale, input, gradOutput, dH, dW);
+}
+
+static int nn_(SpatialConvolution_accGradParameters)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ real scale = luaL_optnumber(L, 4, 1);
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane");
+
+ THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id));
+ THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id));
+
+ THArgCheck( nOutputPlane == gradOutput->size[input->nDimension == 4 ? 1 : 0], 1, "Number of output features is not equal to nOutputPlane" );
+
+ if(input->nDimension == 3)
+ {
+ nn_(convolution_accGradParameters_)(input,gradOutput,gradWeight,gradBias,scale,dH,dW);
+ }
+ else
+ {
+ THTensor *outn = THTensor_(new)();
+ THTensor *inpn = THTensor_(new)();
+ long i;
+ for (i=0; i<input->size[0]; i++)
+ {
+ THTensor_(select)(outn,gradOutput,0,i);
+ THTensor_(select)(inpn,input,0,i);
+ nn_(convolution_accGradParameters_)(inpn,outn,gradWeight,gradBias,scale,dH,dW);
+ }
+ THTensor_(free)(outn);
+ THTensor_(free)(inpn);
+ }
+
+ return 0;
+}
+
+static const struct luaL_Reg nn_(SpatialConvolution__) [] = {
+ {"SpatialConvolution_updateOutput", nn_(SpatialConvolution_updateOutput)},
+ {"SpatialConvolution_updateGradInput", nn_(SpatialConvolution_updateGradInput)},
+ {"SpatialConvolution_accGradParameters", nn_(SpatialConvolution_accGradParameters)},
+ {NULL, NULL}
+};
+
+static void nn_(SpatialConvolution_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(SpatialConvolution__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/SpatialConvolutionMap.c b/generic/SpatialConvolutionMap.c
new file mode 100644
index 0000000..ff7d8ca
--- /dev/null
+++ b/generic/SpatialConvolutionMap.c
@@ -0,0 +1,229 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/SpatialConvolutionMap.c"
+#else
+
+static int nn_(SpatialConvolutionMap_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int kH = luaT_getfieldcheckint(L, 1, "kH");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane");
+ int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane");
+
+ THTensor *connTable = luaT_getfieldcheckudata(L, 1, "connTable", torch_(Tensor_id));
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ luaL_argcheck(L, input->nDimension == 3, 2, "3D tensor expected");
+ luaL_argcheck(L, input->size[0] == nInputPlane, 2, "invalid number of input planes");
+ luaL_argcheck(L, input->size[2] >= kW && input->size[1] >= kH, 2, "input image smaller than kernel size");
+
+ THTensor_(resize3d)(output, nOutputPlane,
+ (input->size[1] - kH) / dH + 1,
+ (input->size[2] - kW) / dW + 1);
+
+ // contiguous
+ input = THTensor_(newContiguous)(input);
+ output = THTensor_(newContiguous)(output);
+
+ // get raw pointers
+ real *input_data = THTensor_(data)(input);
+ real *output_data = THTensor_(data)(output);
+ real *weight_data = THTensor_(data)(weight);
+
+ // and dims
+ long input_n = input->size[0];
+ long input_h = input->size[1];
+ long input_w = input->size[2];
+ long output_n = output->size[0];
+ long output_h = output->size[1];
+ long output_w = output->size[2];
+ long weight_n = weight->size[0];
+ long weight_h = weight->size[1];
+ long weight_w = weight->size[2];
+
+ // add bias
+ THTensor *outputPlane = THTensor_(new)();
+ int k;
+ for (k = 0; k < nOutputPlane; k++) {
+ THTensor_(select)(outputPlane,output,0,k);
+ THTensor_(fill)(outputPlane, THTensor_(get1d)(bias, k));
+ }
+ THTensor_(free)(outputPlane);
+
+ // convolve all maps
+ int i,o;
+ int nweight = connTable->size[0];
+ for (k = 0; k < nweight; k++) {
+ // get offsets for input/output
+ o = (int)THTensor_(get2d)(connTable,k,1)-1;
+ i = (int)THTensor_(get2d)(connTable,k,0)-1;
+
+ // convolve each map
+ THTensor_(validXCorr2Dptr)(output_data + o*output_w*output_h,
+ 1.0,
+ input_data + i*input_w*input_h, input_h, input_w,
+ weight_data + k*weight_w*weight_h, weight_h, weight_w,
+ dH, dW);
+ }
+
+ // clean up
+ THTensor_(free)(input);
+ THTensor_(free)(output);
+
+ return 1;
+}
+
+static int nn_(SpatialConvolutionMap_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int kH = luaT_getfieldcheckint(L, 1, "kH");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane");
+ int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane");
+
+ THTensor *connTable = luaT_getfieldcheckudata(L, 1, "connTable", torch_(Tensor_id));
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id));
+ THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ // contiguous
+ gradInput = THTensor_(newContiguous)(gradInput);
+ gradOutput = THTensor_(newContiguous)(gradOutput);
+
+ // Resize/Zero
+ THTensor_(resizeAs)(gradInput, input);
+ THTensor_(zero)(gradInput);
+
+ // get raw pointers
+ real *gradInput_data = THTensor_(data)(gradInput);
+ real *gradOutput_data = THTensor_(data)(gradOutput);
+ real *weight_data = THTensor_(data)(weight);
+ real *gradWeight_data = THTensor_(data)(gradWeight);
+
+ // and dims
+ long input_n = input->size[0];
+ long input_h = input->size[1];
+ long input_w = input->size[2];
+ long output_n = gradOutput->size[0];
+ long output_h = gradOutput->size[1];
+ long output_w = gradOutput->size[2];
+ long weight_n = weight->size[0];
+ long weight_h = weight->size[1];
+ long weight_w = weight->size[2];
+
+ // updateGradInput all
+ int k;
+ int nkernel = connTable->size[0];
+ for(k = 0; k < nkernel; k++)
+ {
+ int o = (int)THTensor_(get2d)(connTable,k,1)-1;
+ int i = (int)THTensor_(get2d)(connTable,k,0)-1;
+
+ // gradient to input
+ THTensor_(fullConv2Dptr)(gradInput_data + i*input_w*input_h,
+ 1.0,
+ gradOutput_data + o*output_w*output_h, output_h, output_w,
+ weight_data + k*weight_w*weight_h, weight_h, weight_w,
+ dH, dW);
+ }
+
+ // clean up
+ THTensor_(free)(gradInput);
+ THTensor_(free)(gradOutput);
+
+ return 1;
+}
+
+static int nn_(SpatialConvolutionMap_accGradParameters)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int kH = luaT_getfieldcheckint(L, 1, "kH");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane");
+ int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane");
+ real scale = luaL_optnumber(L, 4, 1);
+
+ THTensor *connTable = luaT_getfieldcheckudata(L, 1, "connTable", torch_(Tensor_id));
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id));
+ THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ // contiguous
+ input = THTensor_(newContiguous)(input);
+ gradOutput = THTensor_(newContiguous)(gradOutput);
+
+ // get raw pointers
+ real *input_data = THTensor_(data)(input);
+ real *gradOutput_data = THTensor_(data)(gradOutput);
+ real *weight_data = THTensor_(data)(weight);
+ real *gradWeight_data = THTensor_(data)(gradWeight);
+
+ // and dims
+ long input_n = input->size[0];
+ long input_h = input->size[1];
+ long input_w = input->size[2];
+ long output_n = gradOutput->size[0];
+ long output_h = gradOutput->size[1];
+ long output_w = gradOutput->size[2];
+ long weight_n = weight->size[0];
+ long weight_h = weight->size[1];
+ long weight_w = weight->size[2];
+
+ // gradients wrt bias
+ int k;
+ THTensor *gradOutputPlane = THTensor_(new)();
+ real *gradBias_data = THTensor_(data)(gradBias);
+ for(k = 0; k < nOutputPlane; k++) {
+ THTensor_(select)(gradOutputPlane, gradOutput, 0, k);
+ gradBias_data[k] += scale * THTensor_(sumall)(gradOutputPlane);
+ }
+ THTensor_(free)(gradOutputPlane);
+
+ // gradients wrt weight
+ int nkernel = connTable->size[0];
+ for(k = 0; k < nkernel; k++)
+ {
+ int o = (int)THTensor_(get2d)(connTable,k,1)-1;
+ int i = (int)THTensor_(get2d)(connTable,k,0)-1;
+
+ // gradient to kernel
+ THTensor_(validXCorr2DRevptr)(gradWeight_data + k*weight_w*weight_h,
+ scale,
+ input_data + i*input_w*input_h, input_h, input_w,
+ gradOutput_data + o*output_w*output_h, output_h, output_w,
+ dH, dW);
+ }
+
+ // clean up
+ THTensor_(free)(input);
+ THTensor_(free)(gradOutput);
+ return 0;
+}
+
+static const struct luaL_Reg nn_(SpatialConvolutionMap__) [] = {
+ {"SpatialConvolutionMap_updateOutput", nn_(SpatialConvolutionMap_updateOutput)},
+ {"SpatialConvolutionMap_updateGradInput", nn_(SpatialConvolutionMap_updateGradInput)},
+ {"SpatialConvolutionMap_accGradParameters", nn_(SpatialConvolutionMap_accGradParameters)},
+ {NULL, NULL}
+};
+
+static void nn_(SpatialConvolutionMap_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(SpatialConvolutionMap__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/SpatialMaxPooling.c b/generic/SpatialMaxPooling.c
new file mode 100644
index 0000000..b9fab3b
--- /dev/null
+++ b/generic/SpatialMaxPooling.c
@@ -0,0 +1,163 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/SpatialMaxPooling.c"
+#else
+
+static int nn_(SpatialMaxPooling_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int kH = luaT_getfieldcheckint(L, 1, "kH");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ luaL_argcheck(L, input->nDimension == 3, 2, "3D tensor expected");
+ luaL_argcheck(L, input->size[2] >= kW && input->size[1] >= kH, 2, "input image smaller than kernel size");
+
+ // sizes
+ long nslices = input->size[0];
+ long iheight = input->size[1];
+ long iwidth = input->size[2];
+ long oheight = (iheight - kH) / dH + 1;
+ long owidth = (iwidth - kW) / dW + 1;
+
+ // get contiguous input
+ input = THTensor_(newContiguous)(input);
+
+ // resize output
+ THTensor_(resize3d)(output, nslices, oheight, owidth);
+
+ // indices will contain i,j locatyions for each output point
+ THTensor_(resize4d)(indices, 2, nslices, oheight, owidth);
+
+ // get raw pointers
+ real *input_data = THTensor_(data)(input);
+ real *output_data = THTensor_(data)(output);
+ real *indices_data = THTensor_(data)(indices);
+
+ // compute max pooling for each input slice
+ long k;
+ for (k = 0; k < nslices; k++) {
+ // pointers to slices
+ real *input_p = input_data + k*iwidth*iheight;
+ real *output_p = output_data + k*owidth*oheight;
+ real *indy_p = indices_data + k*owidth*oheight;
+ real *indx_p = indices_data + (k+nslices)*owidth*oheight;
+
+ // loop over output
+ int i,j;
+ for(i = 0; i < oheight; i++) {
+ for(j = 0; j < owidth; j++) {
+ // local pointers
+ real *ip = input_p + i*iwidth*dH + j*dW;
+ real *op = output_p + i*owidth + j;
+ real *indyp = indy_p + i*owidth + j;
+ real *indxp = indx_p + i*owidth + j;
+
+ // compute local max:
+ long maxindex = -1;
+ real maxval = -THInf;
+ long tcntr = 0;
+ int x,y;
+ for(y = 0; y < kH; y++) {
+ for(x = 0; x < kW; x++) {
+ real val = *(ip + y*iwidth + x);
+ if (val > maxval) {
+ maxval = val;
+ maxindex = tcntr;
+ }
+ tcntr++;
+ }
+ }
+
+ // set output to local max
+ *op = maxval;
+
+ // store location of max (x,y)
+ *indyp = (int)(maxindex / dW)+1;
+ *indxp = (maxindex % dW) +1;
+ }
+ }
+ }
+
+ // cleanup
+ THTensor_(free)(input);
+
+ return 1;
+}
+
+static int nn_(SpatialMaxPooling_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int kH = luaT_getfieldcheckint(L, 1, "kH");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ // get contiguous gradOutput
+ gradOutput = THTensor_(newContiguous)(gradOutput);
+
+ // resize
+ THTensor_(resizeAs)(gradInput, input);
+ THTensor_(zero)(gradInput);
+
+ // sizes
+ int ichannels = input->size[0];
+ int iheight = input->size[1];
+ int iwidth = input->size[2];
+ int ochannels = ichannels;
+ int oheight = gradOutput->size[1];
+ int owidth = gradOutput->size[2];
+
+ // get raw pointers
+ real *gradInput_data = THTensor_(data)(gradInput);
+ real *gradOutput_data = THTensor_(data)(gradOutput);
+ real *indices_data = THTensor_(data)(indices);
+
+ // backprop
+ long k;
+ for (k = 0; k < input->size[0]; k++) {
+ // pointers to slices
+ real *gradOutput_p = gradOutput_data + k*owidth*oheight;
+ real *gradInput_p = gradInput_data + k*iwidth*iheight;
+ real *indy_p = indices_data + k*owidth*oheight;
+ real *indx_p = indices_data + (k+ochannels)*owidth*oheight;
+
+ // calculate max points
+ int i,j;
+ for(i = 0; i < oheight; i++) {
+ for(j = 0; j < owidth; j++) {
+ // retrieve position of max
+ long maxi = *(indy_p + i*owidth + j) - 1 + i*dH;
+ long maxj = *(indx_p + i*owidth + j) - 1 + j*dW;
+
+ // update gradient
+ *(gradInput_p + maxi*iwidth + maxj) += *(gradOutput_p + i*owidth + j);
+ }
+ }
+ }
+
+ // cleanup
+ THTensor_(free)(gradOutput);
+
+ return 1;
+}
+
+static const struct luaL_Reg nn_(SpatialMaxPooling__) [] = {
+ {"SpatialMaxPooling_updateOutput", nn_(SpatialMaxPooling_updateOutput)},
+ {"SpatialMaxPooling_updateGradInput", nn_(SpatialMaxPooling_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(SpatialMaxPooling_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(SpatialMaxPooling__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/SpatialSubSampling.c b/generic/SpatialSubSampling.c
new file mode 100644
index 0000000..705253f
--- /dev/null
+++ b/generic/SpatialSubSampling.c
@@ -0,0 +1,278 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/SpatialSubSampling.c"
+#else
+
+static int nn_(SpatialSubSampling_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int kH = luaT_getfieldcheckint(L, 1, "kH");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ real *weight_data = THTensor_(data)(weight);
+ real *bias_data = THTensor_(data)(bias);
+ real *output_data;
+ real *input_data;
+
+
+ luaL_argcheck(L, input->nDimension == 3 || input->nDimension == 4, 2, "3D or 4D(batch mode) tensor expected");
+
+ int dimw = 2;
+ int dimh = 1;
+ if (input->nDimension == 4) {
+ dimw++;
+ dimh++;
+ }
+
+ long inputWidth = input->size[dimw];
+ long inputHeight = input->size[dimh];
+ long outputWidth = (inputWidth - kW) / dW + 1;
+ long outputHeight = (inputHeight - kH) / dH + 1;
+
+
+ luaL_argcheck(L, input->size[dimh-1] == nInputPlane, 2, "invalid number of input planes");
+ luaL_argcheck(L, inputWidth >= kW && inputHeight >= kH, 2, "input image smaller than kernel size");
+
+ input = THTensor_(newContiguous)(input);
+ input_data = THTensor_(data)(input);
+
+ long nbatch = 1;
+ if (input->nDimension == 3)
+ {
+ THTensor_(resize3d)(output, nInputPlane, outputHeight, outputWidth);
+ }
+ else
+ {
+ nbatch = input->size[0];
+ THTensor_(resize4d)(output, nbatch, nInputPlane, outputHeight, outputWidth);
+ }
+
+ output_data = THTensor_(data)(output);
+
+ long i, k, p;
+
+ for(p = 0; p < nbatch; p++)
+ {
+ //input_data += p*nInputPlane*inputWidth*inputHeight;
+ //output_data += p*nInputPlane*outputHeight*outputWidth;
+ for(k = 0; k < nInputPlane; k++)
+ {
+ real *ptr_output;
+ long xx, yy;
+
+ /* Get the good mask for (k,i) (k out, i in) */
+ real the_weight = weight_data[k];
+
+ /* Initialize to the bias */
+ real z = bias_data[k];
+ for(i = 0; i < outputWidth*outputHeight; i++)
+ output_data[i] = z;
+
+ /* For all output pixels... */
+ ptr_output = output_data;
+ for(yy = 0; yy < outputHeight; yy++)
+ {
+ for(xx = 0; xx < outputWidth; xx++)
+ {
+ // Compute the mean of the input image...
+ real *ptr_input = input_data+yy*dH*inputWidth+xx*dW;
+ real sum = 0;
+ long kx, ky;
+
+ for(ky = 0; ky < kH; ky++)
+ {
+ for(kx = 0; kx < kW; kx++)
+ sum += ptr_input[kx];
+ ptr_input += inputWidth; // next input line
+ }
+
+ // Update output
+ *ptr_output++ += the_weight*sum;
+ }
+ }
+
+ // Next input/output plane
+ output_data += outputWidth*outputHeight;
+ input_data += inputWidth*inputHeight;
+ }
+ }
+
+ THTensor_(free)(input);
+
+ return 1;
+}
+
+static int nn_(SpatialSubSampling_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int kH = luaT_getfieldcheckint(L, 1, "kH");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ int dimw = 2;
+ int dimh = 1;
+ long nbatch = 1;
+ if (input->nDimension == 4) {
+ dimw++;
+ dimh++;
+ nbatch = input->size[0];
+ }
+
+ long inputWidth = input->size[dimw];
+ long inputHeight = input->size[dimh];
+ long outputWidth = (inputWidth - kW) / dW + 1;
+ long outputHeight = (inputHeight - kH) / dH + 1;
+
+ real *weight_data = THTensor_(data)(weight);
+ real *gradOutput_data = THTensor_(data)(gradOutput);
+ real *gradInput_data;
+
+ THTensor_(resizeAs)(gradInput, input);
+ THTensor_(zero)(gradInput);
+ gradInput_data = THTensor_(data)(gradInput);
+ gradOutput_data = THTensor_(data)(gradOutput);
+
+ long i, k, p;
+
+ for(p = 0; p < nbatch; p++)
+ {
+ //gradInput_data += p*nInputPlane*inputWidth*inputHeight;
+ //gradOutput_data += p*nInputPlane*outputWidth*outputHeight;
+ for(k = 0; k < nInputPlane; k++)
+ {
+ real the_weight = weight_data[k];
+ real *ptr_gradOutput = gradOutput_data;
+ long xx, yy;
+
+ for(yy = 0; yy < outputHeight; yy++)
+ {
+ for(xx = 0; xx < outputWidth; xx++)
+ {
+ real *ptr_gradInput = gradInput_data+yy*dH*inputWidth+xx*dW;
+ real z = *ptr_gradOutput++ * the_weight;
+ long kx, ky;
+
+ for(ky = 0; ky < kH; ky++)
+ {
+ for(kx = 0; kx < kW; kx++)
+ ptr_gradInput[kx] += z;
+ ptr_gradInput += inputWidth;
+ }
+ }
+ }
+ gradOutput_data += outputWidth*outputHeight;
+ gradInput_data += inputWidth*inputHeight;
+ }
+ }
+
+ return 1;
+}
+
+static int nn_(SpatialSubSampling_accGradParameters)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ real scale = luaL_optnumber(L, 4, 1);
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int kH = luaT_getfieldcheckint(L, 1, "kH");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane");
+
+ THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id));
+ THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id));
+
+ int dimw = 2;
+ int dimh = 1;
+ long nbatch = 1;
+ if (input->nDimension == 4) {
+ dimw++;
+ dimh++;
+ nbatch = input->size[0];
+ }
+
+ long inputWidth = input->size[dimw];
+ long inputHeight = input->size[dimh];
+ long outputWidth = (inputWidth - kW) / dW + 1;
+ long outputHeight = (inputHeight - kH) / dH + 1;
+
+ real *gradWeight_data = THTensor_(data)(gradWeight);
+ real *gradBias_data = THTensor_(data)(gradBias);
+ real *gradOutput_data = THTensor_(data)(gradOutput);
+ real *input_data;
+
+ input = THTensor_(newContiguous)(input);
+ input_data = THTensor_(data)(input);
+
+ long i, k, p;
+ for(p = 0; p < nbatch; p++)
+ {
+ //input_data += p*nInputPlane*inputWidth*inputHeight;
+ //gradOutput_data += p*nInputPlane*inputWidth*inputHeight;
+ for(k = 0; k < nInputPlane; k++)
+ {
+ real *ptr_gradOutput = gradOutput_data;
+ real sum;
+ long xx, yy;
+
+ sum = 0;
+ for(i = 0; i < outputWidth*outputHeight; i++)
+ sum += gradOutput_data[i];
+ gradBias_data[k] += scale*sum;
+
+ sum = 0;
+ for(yy = 0; yy < outputHeight; yy++)
+ {
+ for(xx = 0; xx < outputWidth; xx++)
+ {
+ real *ptr_input = input_data+yy*dH*inputWidth+xx*dW;
+ real z = *ptr_gradOutput++;
+ long kx, ky;
+
+ for(ky = 0; ky < kH; ky++)
+ {
+ for(kx = 0; kx < kW; kx++)
+ sum += z * ptr_input[kx];
+ ptr_input += inputWidth;
+ }
+ }
+ }
+ gradWeight_data[k] += scale*sum;
+ gradOutput_data += outputWidth*outputHeight;
+ input_data += inputWidth*inputHeight;
+ }
+ }
+
+
+ THTensor_(free)(input);
+
+ return 0;
+}
+
+static const struct luaL_Reg nn_(SpatialSubSampling__) [] = {
+ {"SpatialSubSampling_updateOutput", nn_(SpatialSubSampling_updateOutput)},
+ {"SpatialSubSampling_updateGradInput", nn_(SpatialSubSampling_updateGradInput)},
+ {"SpatialSubSampling_accGradParameters", nn_(SpatialSubSampling_accGradParameters)},
+ {NULL, NULL}
+};
+
+static void nn_(SpatialSubSampling_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(SpatialSubSampling__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/Sqrt.c b/generic/Sqrt.c
new file mode 100644
index 0000000..a739e96
--- /dev/null
+++ b/generic/Sqrt.c
@@ -0,0 +1,46 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/Sqrt.c"
+#else
+
+static int nn_(Sqrt_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ *output_data = sqrt(*input_data););
+
+ return 1;
+}
+
+static int nn_(Sqrt_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, input);
+
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \
+ *gradInput_data = 0.5 * (*gradOutput_data / *output_data););
+
+ return 1;
+}
+
+static const struct luaL_Reg nn_(Sqrt__) [] = {
+ {"Sqrt_updateOutput", nn_(Sqrt_updateOutput)},
+ {"Sqrt_updateGradInput", nn_(Sqrt_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(Sqrt_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(Sqrt__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/Square.c b/generic/Square.c
new file mode 100644
index 0000000..409055d
--- /dev/null
+++ b/generic/Square.c
@@ -0,0 +1,45 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/Square.c"
+#else
+
+static int nn_(Square_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ *output_data = *input_data * *input_data;);
+
+ return 1;
+}
+
+static int nn_(Square_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, input);
+
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \
+ *gradInput_data = 2.0 * (*gradOutput_data) * (*input_data););
+
+ return 1;
+}
+
+static const struct luaL_Reg nn_(Square__) [] = {
+ {"Square_updateOutput", nn_(Square_updateOutput)},
+ {"Square_updateGradInput", nn_(Square_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(Square_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(Square__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/Tanh.c b/generic/Tanh.c
new file mode 100644
index 0000000..5c24d15
--- /dev/null
+++ b/generic/Tanh.c
@@ -0,0 +1,45 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/Tanh.c"
+#else
+
+static int nn_(Tanh_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ *output_data = tanh(*input_data);)
+
+ return 1;
+}
+
+static int nn_(Tanh_updateGradInput)(lua_State *L)
+{
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, output);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \
+ real z = *output_data; \
+ *gradInput_data = *gradOutput_data * (1. - z*z););
+ return 1;
+}
+
+static const struct luaL_Reg nn_(Tanh__) [] = {
+ {"Tanh_updateOutput", nn_(Tanh_updateOutput)},
+ {"Tanh_updateGradInput", nn_(Tanh_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(Tanh_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(Tanh__), "nn");
+ lua_pop(L,1);
+
+}
+
+#endif
diff --git a/generic/TemporalConvolution.c b/generic/TemporalConvolution.c
new file mode 100644
index 0000000..fa14a22
--- /dev/null
+++ b/generic/TemporalConvolution.c
@@ -0,0 +1,194 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/TemporalConvolution.c"
+#else
+
+static int nn_(TemporalConvolution_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int inputFrameSize = luaT_getfieldcheckint(L, 1, "inputFrameSize");
+ int outputFrameSize = luaT_getfieldcheckint(L, 1, "outputFrameSize");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor *outputWindow, *inputWindow;
+ int nInputFrame, nOutputFrame;
+ long k;
+
+ luaL_argcheck(L, input->nDimension == 2, 2, "2D tensor expected");
+ luaL_argcheck(L, input->size[1] == inputFrameSize, 2, "invalid input frame size");
+ luaL_argcheck(L, input->size[0] >= kW, 2, "input sequence smaller than kernel size");
+
+ input = THTensor_(newContiguous)(input);
+ outputWindow = THTensor_(new)();
+ inputWindow = THTensor_(new)();
+
+ nInputFrame = input->size[0];
+ nOutputFrame = (nInputFrame - kW) / dW + 1;
+
+ THTensor_(resize2d)(output,
+ nOutputFrame,
+ outputFrameSize);
+
+ /* bias first */
+ for(k = 0; k < nOutputFrame; k++)
+ {
+ THTensor_(select)(outputWindow, output, 0, k);
+ THTensor_(copy)(outputWindow, bias);
+ }
+
+ /* ouch */
+ for(k = 0; nOutputFrame > 0; k++)
+ {
+ long outputFrameStride = (kW-1)/dW+1;
+ long inputFrameStride = outputFrameStride*dW;
+ long nFrame = (nInputFrame-k*dW-kW)/inputFrameStride + 1;
+ nOutputFrame -= nFrame;
+
+ THTensor_(setStorage2d)(inputWindow, input->storage,
+ input->storageOffset+k*dW*input->size[1],
+ nFrame, inputFrameStride*input->size[1],
+ kW*input->size[1], 1);
+
+ THTensor_(setStorage2d)(outputWindow, output->storage,
+ output->storageOffset + k*output->size[1],
+ nFrame, outputFrameStride*output->size[1],
+ output->size[1], 1);
+
+ THTensor_(transpose)(weight, NULL, 0, 1);
+ THTensor_(addmm)(outputWindow, 1, outputWindow, 1, inputWindow, weight);
+ THTensor_(transpose)(weight, NULL, 0, 1);
+ }
+
+ THTensor_(free)(outputWindow);
+ THTensor_(free)(inputWindow);
+ THTensor_(free)(input);
+
+ return 1;
+}
+
+static int nn_(TemporalConvolution_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ long nInputFrame = input->size[0];
+ long nOutputFrame = gradOutput->size[0];
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor *gradOutputWindow;
+ THTensor *gradInputWindow;
+ long k;
+
+ gradOutputWindow = THTensor_(new)();
+ gradInputWindow = THTensor_(new)();
+
+ THTensor_(resizeAs)(gradInput, input);
+ THTensor_(zero)(gradInput);
+
+ /* ouch */
+ for(k = 0; nOutputFrame > 0; k++)
+ {
+ long outputFrameStride = (kW-1)/dW+1;
+ long inputFrameStride = outputFrameStride*dW;
+ long nFrame = (nInputFrame-k*dW-kW)/inputFrameStride + 1;
+ nOutputFrame -= nFrame;
+
+ THTensor_(setStorage2d)(gradOutputWindow, gradOutput->storage,
+ gradOutput->storageOffset + k*gradOutput->size[1],
+ nFrame, outputFrameStride*gradOutput->size[1],
+ gradOutput->size[1], 1);
+
+ THTensor_(setStorage2d)(gradInputWindow, gradInput->storage,
+ gradInput->storageOffset+k*dW*gradInput->size[1],
+ nFrame, inputFrameStride*gradInput->size[1],
+ kW*gradInput->size[1], 1);
+
+ THTensor_(addmm)(gradInputWindow, 1, gradInputWindow, 1, gradOutputWindow, weight);
+ }
+
+ THTensor_(free)(gradOutputWindow);
+ THTensor_(free)(gradInputWindow);
+
+ return 1;
+}
+
+static int nn_(TemporalConvolution_accGradParameters)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ real scale = luaL_optnumber(L, 4, 1);
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ long nInputFrame = input->size[0];
+ long nOutputFrame = gradOutput->size[0];
+
+ THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id));
+ THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id));
+
+ THTensor *gradOutputWindow;
+ THTensor *inputWindow;
+ long k;
+
+ input = THTensor_(newContiguous)(input);
+ gradOutputWindow = THTensor_(new)();
+ inputWindow = THTensor_(new)();
+
+ /* bias first */
+ for(k = 0; k < nOutputFrame; k++)
+ {
+ THTensor_(select)(gradOutputWindow, gradOutput, 0, k);
+ THTensor_(cadd)(gradBias, gradBias, scale, gradOutputWindow);
+ }
+
+ /* ouch */
+ for(k = 0; nOutputFrame > 0; k++)
+ {
+ long outputFrameStride = (kW-1)/dW+1;
+ long inputFrameStride = outputFrameStride*dW;
+ long nFrame = (nInputFrame-k*dW-kW)/inputFrameStride + 1;
+ nOutputFrame -= nFrame;
+
+ THTensor_(setStorage2d)(inputWindow, input->storage,
+ input->storageOffset+k*dW*input->size[1],
+ nFrame, inputFrameStride*input->size[1],
+ kW*input->size[1], 1);
+
+ THTensor_(setStorage2d)(gradOutputWindow, gradOutput->storage,
+ gradOutput->storageOffset + k*gradOutput->size[1],
+ nFrame, outputFrameStride*gradOutput->size[1],
+ gradOutput->size[1], 1);
+
+ THTensor_(transpose)(gradOutputWindow, NULL, 0, 1);
+ THTensor_(addmm)(gradWeight, 1, gradWeight, scale, gradOutputWindow, inputWindow);
+ THTensor_(transpose)(gradOutputWindow, NULL, 0, 1);
+ }
+
+ THTensor_(free)(gradOutputWindow);
+ THTensor_(free)(inputWindow);
+ THTensor_(free)(input);
+
+ return 0;
+}
+
+static const struct luaL_Reg nn_(TemporalConvolution__) [] = {
+ {"TemporalConvolution_updateOutput", nn_(TemporalConvolution_updateOutput)},
+ {"TemporalConvolution_updateGradInput", nn_(TemporalConvolution_updateGradInput)},
+ {"TemporalConvolution_accGradParameters", nn_(TemporalConvolution_accGradParameters)},
+ {NULL, NULL}
+};
+
+static void nn_(TemporalConvolution_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(TemporalConvolution__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/TemporalSubSampling.c b/generic/TemporalSubSampling.c
new file mode 100644
index 0000000..39e7f3b
--- /dev/null
+++ b/generic/TemporalSubSampling.c
@@ -0,0 +1,139 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/TemporalSubSampling.c"
+#else
+
+static int nn_(TemporalSubSampling_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int inputFrameSize = luaT_getfieldcheckint(L, 1, "inputFrameSize");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor *outputFrame, *inputWindow;
+ int nInputFrame, nOutputFrame;
+ long k;
+
+ luaL_argcheck(L, input->nDimension == 2, 2, "2D tensor expected");
+ luaL_argcheck(L, input->size[1] == inputFrameSize, 2, "invalid input frame size");
+ luaL_argcheck(L, input->size[0] >= kW, 2, "input sequence smaller than kernel size");
+
+ outputFrame = THTensor_(new)();
+ inputWindow = THTensor_(new)();
+
+ nInputFrame = input->size[0];
+ nOutputFrame = (nInputFrame - kW) / dW + 1;
+
+ THTensor_(resize2d)(output,
+ nOutputFrame,
+ inputFrameSize);
+
+ for(k = 0; k < nOutputFrame; k++)
+ {
+ THTensor_(narrow)(inputWindow, input, 0, k*dW, kW);
+ THTensor_(select)(outputFrame, output, 0, k);
+ THTensor_(sum)(outputFrame, inputWindow, 0);
+ THTensor_(cmul)(outputFrame, outputFrame, weight);
+ THTensor_(cadd)(outputFrame, outputFrame, 1, bias);
+ }
+
+ THTensor_(free)(outputFrame);
+ THTensor_(free)(inputWindow);
+
+ return 1;
+}
+
+static int nn_(TemporalSubSampling_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor *gradOutputFrame;
+ THTensor *gradInputWindow, *buffer, *kwunit;
+ long k;
+
+ gradOutputFrame = THTensor_(new)();
+ gradInputWindow = THTensor_(new)();
+ buffer = THTensor_(new)();
+ kwunit = THTensor_(newWithSize1d)(kW);
+
+ THTensor_(fill)(kwunit, 1);
+ THTensor_(resizeAs)(gradInput, input);
+ THTensor_(zero)(gradInput);
+
+ for(k = 0; k < gradOutput->size[0]; k++)
+ {
+ THTensor_(narrow)(gradInputWindow, gradInput, 0, k*dW, kW);
+ THTensor_(select)(gradOutputFrame, gradOutput, 0, k);
+ THTensor_(cmul)(buffer, weight, gradOutputFrame);
+ THTensor_(addr)(gradInputWindow, 1, gradInputWindow, 1, kwunit, buffer);
+ }
+
+ THTensor_(free)(gradOutputFrame);
+ THTensor_(free)(gradInputWindow);
+ THTensor_(free)(buffer);
+ THTensor_(free)(kwunit);
+
+ return 1;
+}
+
+static int nn_(TemporalSubSampling_accGradParameters)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ real scale = luaL_optnumber(L, 4, 1);
+
+ int kW = luaT_getfieldcheckint(L, 1, "kW");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+
+ THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id));
+ THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id));
+
+ THTensor *gradOutputFrame;
+ THTensor *inputWindow, *buffer;
+ long k;
+
+
+ gradOutputFrame = THTensor_(new)();
+ inputWindow = THTensor_(new)();
+ buffer = THTensor_(new)();
+
+ for(k = 0; k < gradOutput->size[0]; k++)
+ {
+ THTensor_(narrow)(inputWindow, input, 0, k*dW, kW);
+ THTensor_(select)(gradOutputFrame, gradOutput, 0, k);
+ THTensor_(sum)(buffer, inputWindow, 0);
+ THTensor_(addcmul)(gradWeight, gradWeight, scale, buffer, gradOutputFrame);
+ THTensor_(cadd)(gradBias, gradBias, scale, gradOutputFrame);
+ }
+
+ THTensor_(free)(gradOutputFrame);
+ THTensor_(free)(inputWindow);
+ THTensor_(free)(buffer);
+
+ return 0;
+}
+
+static const struct luaL_Reg nn_(TemporalSubSampling__) [] = {
+ {"TemporalSubSampling_updateOutput", nn_(TemporalSubSampling_updateOutput)},
+ {"TemporalSubSampling_updateGradInput", nn_(TemporalSubSampling_updateGradInput)},
+ {"TemporalSubSampling_accGradParameters", nn_(TemporalSubSampling_accGradParameters)},
+ {NULL, NULL}
+};
+
+static void nn_(TemporalSubSampling_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(TemporalSubSampling__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/Threshold.c b/generic/Threshold.c
new file mode 100644
index 0000000..760e842
--- /dev/null
+++ b/generic/Threshold.c
@@ -0,0 +1,47 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/Threshold.c"
+#else
+
+static int nn_(Threshold_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ real val = luaT_getfieldchecknumber(L, 1, "val");
+ real threshold = luaT_getfieldchecknumber(L, 1, "threshold");
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(output, input);
+ TH_TENSOR_APPLY2(real, output, real, input, \
+ *output_data = (*input_data > threshold) ? *input_data : val;);
+
+ return 1;
+}
+
+static int nn_(Threshold_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ real threshold = luaT_getfieldchecknumber(L, 1, "threshold");
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THTensor_(resizeAs)(gradInput, input);
+ TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \
+ if ((*input_data) > threshold) *gradInput_data = 1; \
+ else *gradInput_data = 0; \
+ *gradInput_data = (*gradOutput_data) * (*gradInput_data););
+ return 1;
+}
+
+static const struct luaL_Reg nn_(Threshold__) [] = {
+ {"Threshold_updateOutput", nn_(Threshold_updateOutput)},
+ {"Threshold_updateGradInput", nn_(Threshold_updateGradInput)},
+ {NULL, NULL}
+};
+
+static void nn_(Threshold_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(Threshold__), "nn");
+ lua_pop(L,1);
+}
+
+#endif
diff --git a/generic/VolumetricConvolution.c b/generic/VolumetricConvolution.c
new file mode 100644
index 0000000..0ec2247
--- /dev/null
+++ b/generic/VolumetricConvolution.c
@@ -0,0 +1,118 @@
+#ifndef TH_GENERIC_FILE
+#define TH_GENERIC_FILE "generic/VolumetricConvolution.c"
+#else
+
+static int nn_(VolumetricConvolution_updateOutput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ int dT = luaT_getfieldcheckint(L, 1, "dT");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id));
+ THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id));
+
+ luaL_argcheck(L, input->nDimension == 4, 2, "4D tensor expected");
+
+ long nOutputPlane = weight->size[0];
+ long nInputPlane = weight->size[1];
+ long kT = weight->size[2];
+ long kH = weight->size[3];
+ long kW = weight->size[4];
+ long inputDepth = input->size[1];
+ long inputHeight = input->size[2];
+ long inputWidth = input->size[3];
+ long outputDepth = (inputDepth - kT) / dT + 1;
+ long outputWidth = (inputWidth - kW) / dW + 1;
+ long outputHeight = (inputHeight - kH) / dH + 1;
+
+ THTensor_(resize4d)(output, nOutputPlane, outputDepth, outputHeight, outputWidth);
+
+ /* add bias */
+ long i;
+ THTensor *outn = THTensor_(new)();
+ for (i=0; i<bias->size[0]; i++) {
+ THTensor_(select)(outn,output,0,i);
+ THTensor_(fill)(outn, THTensor_(get1d)(bias, i));
+ }
+ THTensor_(free)(outn);
+
+ /* do convolutions */
+ THTensor_(conv3Dmv)(output, 1.0, 1.0, input, weight, dT, dH, dW, "V", "X");
+
+ return 1;
+}
+
+
+static int nn_(VolumetricConvolution_updateGradInput)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ int dT = luaT_getfieldcheckint(L, 1, "dT");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id));
+
+ THArgCheck( nOutputPlane == gradOutput->size[0], 1, "Number of output features is not equal to nOutputPlane" );
+
+ /* gradient to input */
+ THTensor *tweight = THTensor_(newTranspose)(weight,0,1);
+ THTensor_(conv3Dmv)(gradInput, 0.0, 1.0, gradOutput, tweight, dT, dH, dW, "F", "C");
+ THTensor_(free)(tweight);
+
+ return 1;
+}
+
+static int nn_(VolumetricConvolution_accGradParameters)(lua_State *L)
+{
+ THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id));
+ THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id));
+ real scale = luaL_optnumber(L, 4, 1);
+ int dT = luaT_getfieldcheckint(L, 1, "dT");
+ int dW = luaT_getfieldcheckint(L, 1, "dW");
+ int dH = luaT_getfieldcheckint(L, 1, "dH");
+ int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane");
+
+ THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id));
+ THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id));
+ THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id));
+
+ THArgCheck( nOutputPlane == gradOutput->size[0], 1, "Number of output features is not equal to nOutputPlane" );
+
+ long k;
+
+ /* gradient to bias */
+ real *gradBias_data = THTensor_(data)(gradBias);
+ THTensor* gradOutSlice = THTensor_(new)();
+ for(k = 0; k < nOutputPlane; k++)
+ {
+ THTensor_(select)(gradOutSlice, gradOutput, 0, k);
+ gradBias_data[k] += scale*THTensor_(sumall)(gradOutSlice);
+ }
+ THTensor_(free)(gradOutSlice);
+
+ /* gradient to kernels */
+ THTensor_(conv3DRevger)(gradWeight, 1.0, scale, input, gradOutput, dT, dH, dW);
+
+ return 0;
+}
+
+static const struct luaL_Reg nn_(VolumetricConvolution__) [] = {
+ {"VolumetricConvolution_updateOutput", nn_(VolumetricConvolution_updateOutput)},
+ {"VolumetricConvolution_updateGradInput", nn_(VolumetricConvolution_updateGradInput)},
+ {"VolumetricConvolution_accGradParameters", nn_(VolumetricConvolution_accGradParameters)},
+ {NULL, NULL}
+};
+
+static void nn_(VolumetricConvolution_init)(lua_State *L)
+{
+ luaT_pushmetaclass(L, torch_(Tensor_id));
+ luaT_registeratname(L, nn_(VolumetricConvolution__), "nn");
+ lua_pop(L,1);
+}
+
+#endif