ó
àÆ÷Xc           @` sª   d  d l  m Z m Z m Z d  d l m Z d  d l Z d  d l Z d  d l	 m
 Z d  d l m Z d  d l m Z d  d l m Z d e j f d	 „  ƒ  YZ e ƒ  Z d S(
   i    (   t   absolute_importt   print_functiont   division(   t   xrangeN(   t   basic(   t   strutil(   t   grad_undefined(   t   DisconnectedTypet
   ConvGrad3Dc           B` sS   e  Z d  Z d Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z	 d „  Z
 RS(	   s0   
    Gradient of Conv3D with respect to W.

    c         C` s   d S(   Ni   (   i   (    (   t   self(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/ConvGrad3D.pyt   c_code_cache_version   s    c   	      C` s…   t  j | ƒ } t  j | ƒ } t  j | ƒ } t  j | ƒ } t j |  d | | | | g d t  j | j t t t t t f ƒ ƒ  g ƒS(   Nt   inputst   outputs(   t   Tt   as_tensor_variablet   theanot   Applyt
   TensorTypet   dtypet   False(	   R	   t   Vt   dt   WShapet   dCdHt   V_t   d_t   WShape_t   dCdH_(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/ConvGrad3D.pyt	   make_node   s    c         C` s?   | j  \ } } } } | d | d | d | d | d f g S(   Ni    i   i   i   i   (   R   (   R	   t   nodet   input_shapesR   R   t   W_shapeR   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/ConvGrad3D.pyt   infer_shape'   s    c         C` s   t  g t  g t g t  g g S(   N(   t   TrueR   (   R	   R   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/ConvGrad3D.pyt   connection_pattern+   s    c         C` sÜ   | \ } } } } | \ } t  j | d d d d d  d  … f ƒ } t j j j | | | | | j d d !ƒ }	 t |  d | ƒ }
 t ƒ  ƒ  } t j j j	 | | t  j | d d d d d  d  … f ƒ | ƒ } |	 |
 | | g S(   Ni    i   i   (
   R   t
   zeros_likeR   t   tensort   nnett   convTransp3Dt   shapeR   R   t   conv3D(   R	   R   t   output_gradientst   CR   R   t   Bt   dLdAt   zt   dLdCt   dLddt	   dLdWShapet   dLdB(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/ConvGrad3D.pyt   grad/   s    	(+@c         C` s÷  | \ } } } } | j  d } | j  d }	 | j  d }
 | j  d } | j  d | k s_ t ‚ | \ } } } t j | d | j ƒ} x\t d | d ƒ D]G} x>t d | d ƒ D])} x t d | d ƒ D]} xt d | ƒ D]ñ } xè t d |	 ƒ D]× } xÎ t d |
 ƒ D]½ } x´ t d | ƒ D]£ } xš t d | d ƒ D]… } x| t d | d ƒ D]g } | | | | | | f c | | | | | | f | | | | | | | | | | | | f 7<qZWq@Wq&WqWqú Wqä WqÎ Wq´ Wqš W| | d d <d  S(   Ni    i   i   i   R   i   (   R'   t   AssertionErrort   Nt   zerosR   R   (   R	   R   R   t   output_storageR   R   R   R   t	   batchSizet   outputHeightt   outputWidtht	   outputDurt   drt   dct   dtt   dCdWt   kt   lt   mt   it   pt   qt   rt   jR-   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/ConvGrad3D.pyt   perform=   s,    :c         C` s?   | \ } } } }	 | d }
 | d } d } t  j | t ƒ  ƒ S(   Nt   faili    s   
            ///////////// < code generated by ConvGradW3D >

            //printf("				ConvGradW3D c code\n");

            //Check dimensionality of inputs
            if (PyArray_NDIM(%(dCdH)s) != 5)
            {
                PyErr_Format(PyExc_ValueError, "ConvGrad3D: dCdH must be a 5 dimensional tensor");
                            %(fail)s
            }

            if (PyArray_NDIM(%(V)s) != 5)
            {
                PyErr_Format(PyExc_ValueError, "ConvGrad3D: V must be a 5 dimensional tensor");
                %(fail)s
            }

            if (PyArray_NDIM(%(WShape)s) != 1)
            {
                PyErr_Format(PyExc_ValueError,"ConvGrad3D: WShape must be a vector.");
                %(fail)s
            }

            if (PyArray_NDIM(%(d)s) != 1)
            {
                PyErr_Format(PyExc_ValueError,"ConvGrad3D: d must be a vector.");
                %(fail)s
            }

            if (PyArray_DIMS(%(d)s)[0] != 3)
            {
                PyErr_Format(PyExc_ValueError,"ConvGrad3D: 3 stride length arguments expected (row, col, time) but %%li were given", (long)PyArray_DIMS(%(d)s)[0]);
                %(fail)s
            }
{ //extra scope so that fail will not jump over declarations

            //Read and check sizes of inputs
            const int batchSize = PyArray_DIMS(%(V)s)[0];
            if (PyArray_DIMS(%(WShape)s)[0] != 5)
            {
                PyErr_Format(PyExc_ValueError,"ConvGrad3D: WShape must specify a 5D shape");
                %(fail)s
            }
            if (!PyArray_ISCONTIGUOUS(%(WShape)s))
            {
                PyErr_Format(PyExc_ValueError,"ConvGrad3D: WShape must be contiguous");
                %(fail)s
            }

{ //extra scope so that fail will not jump over declarations
            dtype_%(WShape)s * WShape = (dtype_%(WShape)s *) PyArray_DATA(%(WShape)s);
            const int outputChannels =  WShape[0];
            const int inputChannels = PyArray_DIMS(%(V)s)[4];
            if (WShape[4] != inputChannels)
            {
                PyErr_Format(PyExc_ValueError, "ConvGrad3D: W operates on a %%i channel image but the image has %%i channels",(int) WShape[1],inputChannels);
                %(fail)s

            }
{ //extra scope so fail works
            const int filterHeight = WShape[1];
            const int filterWidth = WShape[2];
            const int filterDur = WShape[3];
            const int vidHeight = PyArray_DIMS(%(V)s)[1];
            const int vidWidth = PyArray_DIMS(%(V)s)[2];
            const int vidDur = PyArray_DIMS(%(V)s)[3];
            if (vidHeight < filterHeight)
            {
                PyErr_Format(PyExc_ValueError, "ConvGrad3D: W has a height of %%i but V is only %%i pixels tall", filterHeight, vidHeight);
                %(fail)s
            }
            if (vidWidth < filterWidth)
            {
                PyErr_Format(PyExc_ValueError,"ConvGrad3D: W has a width of %%i but V is only %%i pixels tall",filterWidth,vidWidth);
                %(fail)s
            }
            if (vidDur < filterDur)
            {
                PyErr_Format(PyExc_ValueError,"ConvGrad3D: W has a duration of %%i but V is only %%i pixels long",filterDur,vidDur);
                %(fail)s
            }

{ // extra scope so fail works
            //Read and check stride arguments
            const int dr = *(dtype_%(d)s*)PyArray_GETPTR1(%(d)s,0);
            const int dc = *(dtype_%(d)s*)PyArray_GETPTR1(%(d)s,1);
            const int dt = *(dtype_%(d)s*)PyArray_GETPTR1(%(d)s,2);
            if (dr <= 0 || dc <= 0 || dt <= 0)
            {
                PyErr_Format(PyExc_ValueError,"ConvGrad3D: Strides should all be positive but they are %%i, %%i, %%i",dr,dc,dt);
                %(fail)s
            }

{ // extra scope so fail works
            //Compute correct sized of output
            const int outputHeight = int( (vidHeight - filterHeight) / dr )+1;
            const int outputWidth = int( (vidWidth - filterWidth) / dc )+1;
            const int outputDur = int( (vidDur - filterDur) / dt ) +1;



            if (PyArray_DIMS(%(dCdH)s)[0] != batchSize ||
                PyArray_DIMS(%(dCdH)s)[4] != outputChannels ||
                PyArray_DIMS(%(dCdH)s)[1] != outputHeight ||
                PyArray_DIMS(%(dCdH)s)[2] != outputWidth ||
                PyArray_DIMS(%(dCdH)s)[3] != outputDur)
            {
                PyErr_Format(PyExc_ValueError, "dCdH is the wrong size, expected (%%i,%%i,%%i,%%i,%%i), got (%%li,%%li,%%li,%%li,%%li)", batchSize,  outputHeight, outputWidth, outputDur, outputChannels, (long)PyArray_DIMS(%(dCdH)s)[0], (long)PyArray_DIMS(%(dCdH)s)[1], (long)PyArray_DIMS(%(dCdH)s)[2], (long)PyArray_DIMS(%(dCdH)s)[3], (long)PyArray_DIMS(%(dCdH)s)[4]);
                %(fail)s
            }
{ // extra scope for fail

            npy_intp dims[5];
            dims[0] = outputChannels;
            dims[4] = inputChannels;
            dims[1] = filterHeight;
            dims[2] = filterWidth;
            dims[3] = filterDur;

            if(!(%(dCdW)s)  || PyArray_DIMS(%(dCdW)s)[0]!=dims[0] ||
                  PyArray_DIMS(%(dCdW)s)[1]!=dims[1] ||
                  PyArray_DIMS(%(dCdW)s)[2]!=dims[2] ||
                  PyArray_DIMS(%(dCdW)s)[3]!=dims[3] ||
                  PyArray_DIMS(%(dCdW)s)[4]!=dims[4] ){
               Py_XDECREF(%(dCdW)s);
               %(dCdW)s = (PyArrayObject *) PyArray_SimpleNew(5, dims, PyArray_DESCR(%(V)s)->type_num);

               if (!(%(dCdW)s)) {
                  PyErr_Format(PyExc_MemoryError,"ConvGrad3D: Could not allocate dCdW");
                %(fail)s
               }
            }
{ //extra scope so fail works

            #define ELEM5(x, i,j,k,l,m) * ( dtype_ ## x *) ( PyArray_BYTES(x) + (i)*PyArray_STRIDES(x)[0]+(j)*PyArray_STRIDES(x)[1]+(k)*PyArray_STRIDES(x)[2]+(l)*PyArray_STRIDES(x)[3]+(m)*PyArray_STRIDES(x)[4] )

            #define ELEM_AT(x, i) * ( dtype_ ## x *) ( PyArray_BYTES(x) + (i) )

            const int dhs3 = PyArray_STRIDES(%(dCdH)s)[3];
            const int dtvs3 = dt * PyArray_STRIDES(%(V)s)[3];

            // Compute dCdW
            //TODO-- see if this can be made faster by using ELEM_AT instead of ELEM5
            // dCdW[j,k,l,m,z] = sum_i sum_p sum_q sum_r dCdH[i,p,q,r,j]  *  V[i,dr*p+k,dc*q+l,dt*r+m,z]
            for (int j = 0; j < outputChannels; j++) {
                for (int z = 0; z < inputChannels; z++) {
                    for (int k = 0; k < filterHeight; k++) {
                        for (int l = 0; l < filterWidth; l++) {
                            for (int m = 0; m < filterDur; m++) {

                                //printf("writePos %%i %%i %%i %%i %%i \n",j,k,l,m,z);

                                dtype_%(dCdW)s & writePos =  ELEM5(%(dCdW)s, j,k,l,m,z);
                                writePos = 0;
                                for (int i = 0; i < batchSize; i++) {
                                    for (int p = 0; p < outputHeight; p++) {
                                        for (int q = 0; q < outputWidth; q++) {
                                            int Hpos = i * PyArray_STRIDES(%(dCdH)s)[0] + j * PyArray_STRIDES(%(dCdH)s)[4] + p * PyArray_STRIDES(%(dCdH)s)[1] + q * PyArray_STRIDES(%(dCdH)s)[2] ;
                                            int Vpos = i * PyArray_STRIDES(%(V)s)[0] + z * PyArray_STRIDES(%(V)s)[4] +  (dr * p+k) * PyArray_STRIDES(%(V)s)[1] +  (dc*q+l) * PyArray_STRIDES(%(V)s)[2] + m * PyArray_STRIDES(%(V)s)[3];

                                            for (int r = 0; r < outputDur; r++) {
                                                writePos += ELEM5(%(dCdH)s,i,p,q,r,j) * ELEM5(%(V)s,i,dr*p+k,dc*q+l,dt*r+m,z);
                                                //writePos += ELEM_AT(%(dCdH)s,Hpos) * ELEM_AT(%(V)s,Vpos);
                                                Hpos += dhs3;
                                                Vpos += dtvs3;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

}}}}}}} // extra scope for fail
            ///////////// < /code generated by ConvGradW3D >
        (   R   t   render_stringt   locals(   R	   R   t   nodenameR   R   t   subR   R   R   R   RH   R>   t
   codeSource(    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/ConvGrad3D.pyt   c_code^   s
    

´(    (   t   __name__t
   __module__t   __doc__t	   __props__R
   R   R    R"   R2   RG   RN   (    (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/ConvGrad3D.pyR      s   						!(   t
   __future__R    R   R   t	   six.movesR   t   numpyR4   R   t   theano.tensorR   R   t   theano.miscR   t   theano.gradientR   R   t   OpR   t
   convGrad3D(    (    (    s=   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/ConvGrad3D.pyt   <module>   s   ÿ 