                               nFrame, inputFrameStride*input->size[1],
                               kW*input->size[1], 1);
 
-      THCudaTensor_setStorage2d(outputWindow, output->storage, 
+      THCudaTensor_setStorage2d(outputWindow, output->storage,
                               output->storageOffset + k*output->size[1],
                               nFrame, outputFrameStride*output->size[1],
                               output->size[1], 1);
 
       THCudaTensor_transpose(weight, NULL, 0, 1);
-      THCudaTensor_addmm(outputWindow, 1, 1, inputWindow, weight);
+      THCudaTensor_addmm(outputWindow, 1, outputWindow, 1, inputWindow, weight);
       THCudaTensor_transpose(weight, NULL, 0, 1);
     }
   }

                                nFrame, inputFrameStride*inputSample->size[1],
                                kW*inputSample->size[1], 1);

        THCudaTensor_setStorage2d(gradOutputWindow, gradOutputSample->storage, 
                                gradOutputSample->storageOffset + k*gradOutputSample->size[1],
                                nFrame, outputFrameStride*gradOutputSample->size[1],
                                gradOutputSample->size[1], 1);

        THCudaTensor_transpose(gradOutputWindow, NULL, 0, 1);
        THCudaTensor_addmm(gradWeight, 1, scale, gradOutputWindow, inputWindow);
        THCudaTensor_transpose(gradOutputWindow, NULL, 0, 1);
      }
    }

  input = THCudaTensor_newContiguous(input);
  outputWindow = THCudaTensor_new();
  inputWindow = THCudaTensor_new();

  nInputFrame = input->size[dimS];
  nOutputFrame = (nInputFrame - kW) / dW + 1;

  if (input->nDimension == 2)
  {
    THCudaTensor_resize2d(output,
                          nOutputFrame,
                          outputFrameSize);

    /* bias first */
    for(k = 0; k < nOutputFrame; k++)
    {
      THCudaTensor_select(outputWindow, output, 0, k);
      THCudaTensor_copy(outputWindow, bias);
    }


    /* ouch */
    for(k = 0; nOutputFrame > 0; k++)
