Move HardTanh.c -> lib/THNN/generic
diff --git a/generic/HardTanh.c b/generic/HardTanh.c
new file mode 100644
index 0000000..70d0e81
--- /dev/null
+++ b/generic/HardTanh.c
@@ -0,0 +1,97 @@
+#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);
+  real min_val = luaT_getfieldchecknumber(L, 1, "min_val");
+  real max_val = luaT_getfieldchecknumber(L, 1, "max_val");
+  THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_Tensor);
+
+  THTensor_(resizeAs)(output, input);
+  
+  if (input->nDimension == 1 || !THTensor_(isContiguous)(input) || !THTensor_(isContiguous)(output))
+  {
+    TH_TENSOR_APPLY2(real, output, real, input,     \
+         if(*input_data < min_val)     \
+           *output_data = min_val;   \
+         else if(*input_data <= max_val)    \
+           *output_data = *input_data;  \
+         else       \
+           *output_data = max_val;);
+  }
+  else
+  {
+    real* ptr_output = THTensor_(data)(output);
+    real* ptr_input  = THTensor_(data)(input);
+    long i;
+
+#pragma omp parallel for private(i)
+    for (i = 0; i < THTensor_(nElement)(input); i++)
+    {
+      if(ptr_input[i] < min_val)
+        ptr_output[i] = min_val;
+      else if (ptr_input[i] <= max_val)
+        ptr_output[i] = ptr_input[i];
+      else
+        ptr_output[i] = max_val;
+    }
+  }
+  return 1;
+}
+
+static int nn_(HardTanh_updateGradInput)(lua_State *L)
+{
+  THTensor *input = luaT_checkudata(L, 2, torch_Tensor);
+  real min_val = luaT_getfieldchecknumber(L, 1, "min_val");
+  real max_val = luaT_getfieldchecknumber(L, 1, "max_val");
+  THTensor *gradOutput = luaT_checkudata(L, 3, torch_Tensor);
+  THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_Tensor);
+
+  THTensor_(resizeAs)(gradInput, input);
+
+  if (input->nDimension == 1 || 
+      !THTensor_(isContiguous)(input) || 
+      !THTensor_(isContiguous)(gradOutput) ||
+      !THTensor_(isContiguous)(gradInput))
+  {
+    TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input,  \
+         if(*input_data < min_val || *input_data > max_val)    \
+           *gradInput_data = 0;                             \
+         else           \
+           *gradInput_data = *gradOutput_data;);
+  }
+  else
+  {
+    real* ptr_gradOutput = THTensor_(data)(gradOutput);
+    real* ptr_gradInput  = THTensor_(data)(gradInput);
+    real* ptr_input      = THTensor_(data)(input);
+    long i;
+
+#pragma omp parallel for private(i)
+    for (i = 0; i < THTensor_(nElement)(input); i++)
+    {
+      if(ptr_input[i] < min_val || ptr_input[i] > max_val)
+        ptr_gradInput[i] = 0;
+      else
+        ptr_gradInput[i] = ptr_gradOutput[i];
+    }
+  }
+  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_pushmetatable(L, torch_Tensor);
+  luaT_registeratname(L, nn_(HardTanh__), "nn");
+  lua_pop(L,1);
+}
+
+#endif