ó
àÆ÷Xc        	   @` sŽ  d  Z  d d l m Z m Z m Z d d l Z d d l Z d d l Z d d l m	 Z	 d d l
 j j Z d d l Z d d l m Z m Z m Z m Z m Z d d l m Z d „  Z e e e d d f d e e e d	 „ Z e e e d d d f d e e e d
 „ Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d S(   sO   
Ops for downsampling images.
Planned:
Pool, DownsampleAvg, DownsampleSoftmax.
i    (   t   absolute_importt   print_functiont   divisionN(   t   xrange(   t   goft   OpenMPOpt   tensort   Variablet   Apply(   t   DisconnectedTypec         C` s4   t  t ƒ |  | ƒ } t t ƒ |  | | | ƒ } | S(   sM  
    Takes as input a 4-D tensor. It sets all non maximum values
    of non-overlapping patches of size (patch_size[0],patch_size[1]) to zero,
    keeping only the maximum values. The output has the same dimensions as
    the input.

    Parameters
    ----------
    input : 4-D theano tensor of input images
        Input images. Max pooling will be done over the 2 last dimensions.
    patch_size : tuple of length 2 or theano vector of ints of size 2.
        Size of the patch (patch height, patch width).
        (2,2) will retain only one non-zero value per patch of 4 values.

    (   t   Poolt   Truet   MaxPoolGrad(   t   inputt
   patch_sizet   outputt   outs(    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   max_pool_2d_same_size   s    t   maxc	         C` sm  | d k	 rC | d k	 r' t d ƒ ‚ qj t j d d d ƒ| } n' | d k rj | d k rj t d ƒ ‚ n  | d k	 r­ | d k	 r‘ t d ƒ ‚ q­ t j d d d ƒ| } n  | d k	 rö | d d h k rÚ t d	 ƒ ‚ qö t j d
 d d ƒ| } n  |  j d k  rt d ƒ ‚ n  | d k r<t j d d d ƒt } n  t | d d d | ƒ}	 |	 |  | | | ƒ }
 |
 S(   sž  Downscale the input by a specified factor

    Takes as input a N-D tensor, where N >= 2. It downscales the input image by
    the specified factor, by keeping only the maximum value of non-overlapping
    patches of size (ws[0],ws[1])

    Parameters
    ----------
    input : N-D theano tensor of input images
        Input images. Max pooling will be done over the 2 last dimensions.
    ws : tuple of length 2 or theano vector of ints of size 2.
        Factor by which to downscale (vertical ws, horizontal ws).
        (2,2) will halve the image in each dimension.
    ignore_border : bool (default None, will print a warning and set to False)
        When True, (5,5) input with ws=(2,2) will generate a (2,2) output.
        (3,3) otherwise.
    stride : tuple of two ints or theano vector of ints of size 2.
        Stride size, which is the number of shifts over rows/cols to get the
        next pool region. If stride is None, it is considered equal to ws
        (no overlap on pooling regions).
    pad : tuple of two ints or theano vector of ints of size 2.
        (pad_h, pad_w), pad zeros to extend beyond four borders of the
        images, pad_h is the size of the top and bottom margins, and
        pad_w is the size of the left and right margins.
    mode : {'max', 'sum', 'average_inc_pad', 'average_exc_pad'}
        Operation executed on each window. `max` and `sum` always exclude
        the padding in the computation. `average` gives you the choice to
        include or exclude it.
    ds
        *deprecated*, use parameter ws instead.
    st
        *deprecated*, use parameter stride instead.
    padding
        *deprecated*, use parameter pad instead.

    s[   You can't provide a tuple value to both 'ws' and 'ds'. Please provide a value only to 'ws'.sr   DEPRECATION: the 'ds' parameter is not going to exist anymore as it is going to be replaced by the parameter 'ws'.t
   stackleveli   s3   You must provide a tuple value for the window size.sb   You can't provide a tuple value to both 'st and 'stride'. Please provide a value only to 'stride'.sv   DEPRECATION: the 'st' parameter is not going to exist anymore as it is going to be replaced by the parameter 'stride'.i    s_   You can't provide a tuple value to both 'padding' and pad.  Please provide a value only to pad.sx   DEPRECATION: the 'padding' parameter is not going to exist anymore as it is going to be replaced by the parameter 'pad'.s!   pool_2d requires a dimension >= 2sÊ  pool_2d() will have the parameter ignore_border default value changed to True (currently False). To have consistent behavior with all Theano version, explicitly add the parameter ignore_border=True. On the GPU, using ignore_border=True is needed to use cuDNN. When using ignore_border=False and not using cuDNN, the only GPU combination supported is when `ws == stride and pad == (0, 0) and mode == 'max'`. Otherwise, the convolution will be executed on CPU.t   ndimt   modeN(   i    i    (   t   Nonet
   ValueErrort   warningst   warnR   t   NotImplementedErrort   FalseR
   (   R   t   wst   ignore_bordert   stridet   padR   t   dst   stt   paddingt   opR   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   pool_2d)   sJ    '					c	         C` sm  | d k	 rC | d k	 r' t d ƒ ‚ qj t j d d d ƒ| } n' | d k rj | d k rj t d ƒ ‚ n  | d k	 r­ | d k	 r‘ t d ƒ ‚ q­ t j d d d ƒ| } n  | d k	 rö | d d h k rÚ t d	 ƒ ‚ qö t j d
 d d ƒ| } n  |  j d k  rt d ƒ ‚ n  | d k r<t j d d d ƒt } n  t | d d d | ƒ}	 |	 |  | | | ƒ }
 |
 S(   sð  Downscale the input by a specified factor

    Takes as input a N-D tensor, where N >= 3. It downscales the input image by
    the specified factor, by keeping only the maximum value of non-overlapping
    patches of size (ws[0],ws[1],ws[2])

    Parameters
    ----------
    input : N-D theano tensor of input images
        Input images. Max pooling will be done over the 3 last dimensions.
    ws : tuple of length 3 or theano vector of ints of size 3
        Factor by which to downscale (vertical ws, horizontal ws, depth ws).
        (2,2,2) will halve the image in each dimension.
    ignore_border : bool (default None, will print a warning and set to False)
        When True, (5,5,5) input with ws=(2,2,2) will generate a (2,2,2) output.
        (3,3,3) otherwise.
    st : tuple of three ints or theano vector of ints of size 3
        Stride size, which is the number of shifts over rows/cols/slices to get
        the next pool region. If st is None, it is considered equal to ws
        (no overlap on pooling regions).
    pad : tuple of two ints or theano vector of ints of size 3
        (pad_h, pad_w, pad_d), pad zeros to extend beyond six borders of the
        images, pad_h is the size of the top and bottom margins,
        pad_w is the size of the left and right margins, and pad_d is the size
        of the front and back margins
    mode : {'max', 'sum', 'average_inc_pad', 'average_exc_pad'}
        Operation executed on each window. `max` and `sum` always exclude
        the padding in the computation. `average` gives you the choice to
        include or exclude it.
    ds
        *deprecated*, use parameter ws instead.
    st
        *deprecated*, use parameter st instead.
    padding
        *deprecated*, use parameter pad instead.

    s[   You can't provide a tuple value to both 'ws' and 'ds'. Please provide a value only to 'ws'.sr   DEPRECATION: the 'ds' parameter is not going to exist anymore as it is going to be replaced by the parameter 'ws'.R   i   s3   You must provide a tuple value for the window size.sb   You can't provide a tuple value to both 'st and 'stride'. Please provide a value only to 'stride'.sv   DEPRECATION: the 'st' parameter is not going to exist anymore as it is going to be replaced by the parameter 'stride'.i    s_   You can't provide a tuple value to both 'padding' and pad.  Please provide a value only to pad.sx   DEPRECATION: the 'padding' parameter is not going to exist anymore as it is going to be replaced by the parameter 'pad'.i   s!   pool_3d requires a dimension >= 3sÍ  pool_3d() will have the parameter ignore_border default value changed to True (currently False). To have consistent behavior with all Theano version, explicitly add the parameter ignore_border=True. On the GPU, using ignore_border=True is needed to use cuDNN. When using ignore_border=False and not using cuDNN, the only GPU combination supported is when `ws == stride and pad == (0, 0, 0) and mode == 'max'`. Otherwise, the convolution will be executed on CPU.R   R   N(   i    i    i    (   R   R   R   R   R   R   R   R
   (   R   R   R   R   R   R   R    R!   R"   R#   R   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   pool_3d•   sJ    (					R
   c        
   B` s¹   e  Z d  Z d d d f Z e e e e e d e e e d „ ƒ Z e d d e d „ Z d „  Z	 e e d	 „ Z
 d
 „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z RS(   sk  
    sum or average over different patches.

    Parameters
    ----------
    ws : list or tuple of N ints
        Downsample factor over rows, columns etc.
        ws indicates the size of the pooling region.
    ignore_border : bool
        If ws doesn't divide imgshape, do we include an extra row/col/slice
        of partial downsampling (False) or ignore it (True).
    stride : list or tuple of N ints or None
        Stride size, which is the number of shifts over rows/cols/slices to get the
        next pool region. If stride is None, it is considered equal to ws
        (no overlap on pooling regions).
    pad : tuple of N ints or None
        For each downsampling dimension, this specifies the number of zeros to
        add as padding on both sides. For 2D and (pad_h, pad_w), pad_h specifies the
        size of the top and bottom margins, pad_w specifies the size of the left and
        right margins. No padding is added if pad is None.
    mode : {'max', 'sum', 'average_inc_pad', 'average_exc_pad'}
        ('average_inc_pad' excludes the padding from the count,
        'average_exc_pad' include it)
    ndim : int
        The number of pooling dimensions N.
        The default is 2.
    ds
        *deprecated*, use parameter ws instead.
    st
        *deprecated*, use parameter st instead.
    padding
        *deprecated*, use parameter pad instead.


    R   R   R   i   c	         ` s  | d k	 rC | d k	 r' t d ƒ ‚ qj t j d d d ƒ| } n' | d k rj | d k rj t d ƒ ‚ n  | d k	 r­ | d k	 r‘ t d ƒ ‚ q­ t j d d d ƒ| } n  | d k	 r d ˆ }	 ˆ d |	 h k rä t d	 ƒ ‚ q t j d
 d d ƒ| ‰ n  ˆ d k rd ‰ n  ˆ d k s't ‚ t ˆ ƒ ˆ k  rQt d j ˆ ƒ ƒ ‚ n  | d k rf| } n  ˆ d k rd ˆ ‰ n  t ‡ ‡ ‡ f d †  t	 ˆ ƒ Dƒ ƒ }
 ‡  f d †  } g  t	 ˆ ƒ D]$ } | |
 | | | | | ƒ ^ qÃ} t
 ˆ ˆ  ƒ | } | S(   sD  
        Return the shape of the output from this op, for input of given
        shape and flags.

        Parameters
        ----------
        imgshape : tuple, list, or similar of integer or scalar Theano variable
            The shape of a tensor of images. The last N elements are
            interpreted as the number of rows, and the number of cols.
        ws : list or tuple of N ints
            Downsample factor over rows and column.
            ws indicates the pool region size.
        ignore_border : bool
            If ws doesn't divide imgshape, do we include an extra row/col/slice
            of partial downsampling (False) or ignore it (True).
        stride : list or tuple of N ints or None
            Stride size, which is the number of shifts over rows/cols/slices to get the
            next pool region. If stride is None, it is considered equal to ws
            (no overlap on pooling regions).
        pad : tuple of N ints or None
            For each downsampling dimension, this specifies the number of zeros to
            add as padding on both sides. For 2D and (pad_h, pad_w), pad_h specifies the
            size of the top and bottom margins, pad_w specifies the size of the left and
            right margins. No padding is added if pad is None.
        ndim : int
            The number of pooling dimensions N.
            The default is 2.
        ds
            *deprecated*, use parameter ws instead.
        st
            *deprecated*, use parameter st instead.
        padding
            *deprecated*, use parameter pad instead.

        Returns
        -------
        list
            The shape of the output from this op, for input of given shape.
            This will have the same length as imgshape, but with last N
            elements reduced as per the downsampling & ignore_border flags.

        s[   You can't provide a tuple value to both 'ws' and 'ds'. Please provide a value only to 'ws'.sr   DEPRECATION: the 'ds' parameter is not going to exist anymore as it is going to be replaced by the parameter 'ws'.R   i   s3   You must provide a tuple value for the window size.sb   You can't provide a tuple value to both 'st and 'stride'. Please provide a value only to 'stride'.sv   DEPRECATION: the 'st' parameter is not going to exist anymore as it is going to be replaced by the parameter 'stride'.i    s_   You can't provide a tuple value to both 'padding' and pad.  Please provide a value only to pad.sx   DEPRECATION: the 'padding' parameter is not going to exist anymore as it is going to be replaced by the parameter 'pad'.s)   imgshape must have at least {} dimensionsc         3` s3   |  ]) } t  j ˆ  ˆ | ƒ ˆ | d  Vq d S(   i   N(   R   t   extract_constant(   t   .0t   i(   t   imgshapeR   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>“  s   c         ` sÿ   ˆ  ra | | k r |  | S|  | | d } t  | t j ƒ rN t j | d ƒ St j | d ƒ Snš t  |  t j ƒ r¾ t j t j | | ƒ |  d | d t j d |  d | | d ƒ d ƒ S| | k rÚ |  d | d St d |  d | | | ƒ d Sd  S(   Ni   i    (	   t
   isinstancet   theanoR   R   t   maximumt   numpyt   switcht   geR   (   t   vt
   downsampleR   t   out(   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   compute_out–  s    N(   i    (   i    (   R   R   R   R   t   AssertionErrort   lent	   TypeErrort   formatt   tupleR   t   list(   R)   R   R   R   R   R   R    R!   R"   t   zero_padt   patch_shapeR3   R(   t	   out_shapet   rval(    (   R   R)   R   R   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR<   )  sV    .		
			7R   c         C` sW   t  t |  ƒ j d | ƒ | |  _ | |  _ | d k rJ t d | ƒ ‚ n  | |  _ d  S(   Nt   openmpR   t   average_inc_padt   average_exc_padt   sums^   Pool mode parameter only support 'max', 'sum', 'average_inc_pad' and 'average_exc_pad'. Got %s(   s   maxR?   R@   s   sum(   t   superR
   t   __init__R   R   R   R   (   t   selfR   R   R   R>   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRC   °  s    		c         C` sœ  t  | j ƒ d k r˜t  | j j ƒ |  _ | j j |  _ t j j | j j ƒ } t j j | j j	 ƒ } t j j | j j
 ƒ } | j j | ƒ | j j | ƒ | j j | ƒ t | t j ƒ rã | j g | | <t g | | <n d  g | | <t g | | <t | t j ƒ r/| j g | | <t g | | <n d  g | | <t g | | <t | t j ƒ r{| j g | | <t g | | <q˜d  g | | <t g | | <n  d  S(   Ni   (   R5   t   inputsR#   R    R   R   R+   R   t   constantR!   R"   t   appendR*   t   Constantt   dataR   R   R   (   RD   t   nodet   storage_mapt   compute_mapt   implR   R!   R   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   prepare_nodeº  s0    c         ` s  t  j | ƒ } |  j } | d  k r- ˆ } n  ˆ  d  k rF d	 | ‰  n t ˆ  t t f ƒ rÕ t ˆ  ƒ d k r† |  j r† t	 d ƒ ‚ n  t ˆ t t f ƒ rÕ t
 ‡  ‡ f d †  t | ƒ Dƒ ƒ rÒ t	 d ƒ ‚ qÒ qÕ n  t  j ˆ ƒ ‰ t  j | ƒ } t  j ˆ  ƒ ‰  ˆ j d k st ‚ | j d k s,t ‚ ˆ  j d k sAt ‚ | j j | k  r_t ƒ  ‚ n  ˆ j t  j k r€t d ƒ ‚ n  | j t  j k r¡t d ƒ ‚ n  ˆ  j t  j k rÂt d ƒ ‚ n  | j |  t f | } t  j | j | ƒ } t j |  | ˆ | ˆ  g | ƒ  g ƒ S(
   Ni    s*   padding works only with ignore_border=Truec         3` s#   |  ] } ˆ  | ˆ | k Vq d  S(   N(    (   R'   R(   (   R   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>å  s    s$   padding must be smaller than stridesi   s(   Pool downsample parameters must be ints.s   Stride parameters must be ints.s    Padding parameters must be ints.(   i    (   R   t   as_tensor_variableR   R   R*   R8   R9   R   R   R   t   anyt   rangeR4   t   typeR6   t   dtypet
   int_dtypest   broadcastableR   t
   TensorTypeR   R   (   RD   t   xR   R   R   t   ndt   broadR2   (    (   R   R   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt	   make_nodeØ  s>    		%c      	   ` s’  | \ ‰ } } ‰ | \ } |  j  ‰ | j | j k oR ˆ j k oR ˆ f k n s] t ‚ t ˆ j ƒ ˆ k  rŠ t d j ˆ ƒ ƒ ‚ n  |  j ˆ j | |  j | ˆ ˆ ƒ } |  j sÛ t d „  | ˆ Dƒ ƒ sÛ t ‚ n  | d d  k sþ | d j | k rt
 j | d ˆ j ƒ| d <n  | d } | j ˆ }	 t ‡ ‡ ‡ f d †  t ˆ ƒ Dƒ ƒ ‰  |  j d k }
 t ˆ ƒ d k rìt
 j ˆ j ˆ  ˆ  d ˆ j ƒ} ˆ | t d  ƒ f t ˆ j ƒ ˆ t ‡  ‡ f d †  t ˆ ƒ Dƒ ƒ <n ˆ } t
 j } |  j d k rt
 j } n |  j d	 k r1t
 j } n  g  t ˆ ƒ D] } g  ^ q>} x² t ˆ ƒ D]¤ } x› t |	 | ƒ D]‰ } | | | } t j | | | ˆ  | ƒ } |
 sãt j | ˆ | ƒ } t j | ˆ  | ˆ | ƒ } n  | | j t | | ƒ ƒ qtWq]Wx† t
 j ˆ j ˆ  Œ  D]m } | | } | | } xP t
 j |	 Œ  D]? } | | g  t ˆ ƒ D] } | | | | ^ q`ƒ | | <qGWqWd  S(
   Ns.   Pool requires input with {} or more dimensionsc         s` s   |  ] } | d  k Vq d S(   i    N(    (   R'   t   z(    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>  s    i    RS   c         3` s-   |  ]# } ˆ j  ˆ  | d  ˆ | Vq d S(   i   N(   t   shape(   R'   R(   (   RX   R   RW   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>  s    R?   c         3` s.   |  ]$ } t  ˆ | ˆ  | ˆ | ƒ Vq d  S(   N(   t   slice(   R'   R(   (   t   img_shpR   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>  s    RA   R   (   R   R\   R4   R5   R   R7   R<   R   t   allR   R-   t   emptyRS   R8   R   R   R   t   zerosR]   RA   t   averaget   builtinst   minRG   t   ndindex(   RD   RJ   t   inpR2   R   R   R[   t   z_shapet   zzt   pool_out_shpt   inc_padt   yt   funcR(   t   region_slicest   jt   startt   endt   kt   zzkt   ykt   r(    (   R^   RX   R   RW   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   performû  sP    		9$	$#
($J	!"

c         C` sX   | j  d | j  d | j  d } } } |  j | d | |  j | | |  j ƒ } | g S(   Ni   i   i   i    (   RE   R<   R   R   (   RD   RJ   t	   in_shapesR   R   R   t   shp(    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   infer_shape/  s    )c      
   C` sè   | \ } } } } | \ } g  | d D] } t  ƒ  ƒ  ^ q& }	 |  j d k r  |  | | | | ƒ }
 t d |  j d |  j ƒ | |
 | d | d | d | ƒg |	 St d |  j d |  j d |  j ƒ | | d | d | d | ƒg |	 Sd  S(	   Ni   R   R   R   R   R   R   R   (   R	   R   R   R   R   t   AveragePoolGrad(   RD   Rf   t   gradsRW   R   R   R   t   gzR(   t   disct   maxout(    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   grad5  s    	#	&		c         C` s   d g d g d g d g g S(   Ni   i    (    (   RD   RJ   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   connection_patternD  s    c   	      C` s›   |  j  d k r1 | d g | d } |  | Œ  g S| d d  k rH d  g S|  | Œ  } | \ } } } } t |  j |  j  |  j ƒ | | | d | | | ƒ g S(   NR   i    i   (   R   R   t   DownsampleFactorMaxGradGradR   R   (	   RD   RE   t   eval_pointst   eval_inputsR[   RW   R   R   R   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   R_opG  s    c         C` s&   d g } | t  t |  ƒ j ƒ  7} | S(   Ns   <algorithm>(   RB   R
   t	   c_headers(   RD   t   headers(    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR„   [  s    	c      
   C` sê  |  j  d k r$ t j j j ƒ  ‚ n  | \ } } } }	 | \ }
 |  j } | j d j } | | } | d } t |  j ƒ } |  j	 r d } n d } d	 } x7 t
 | ƒ D]) } | d
 t d | d | d | ƒ 7} q¦ W| d 7} |  j  d k r–x1 t
 | ƒ D]# } | d t d | d | ƒ 7} qù W| d 7} x1 t
 | ƒ D]# } | d t d | d | ƒ 7} q7W| d 7} x t
 | ƒ D] } | d 7} quW| d 7} n|  j  d  k r´| d 7} x1 t
 | ƒ D]# } | d t d | d | ƒ 7} q¼W| d 7} x t
 | ƒ D] } | d 7} qúW|  j  d k r*| d 7} q´|  j  d k r{|  j r{d j d „  t
 | ƒ Dƒ ƒ } | d t d | ƒ 7} q´d j d „  t
 | ƒ Dƒ ƒ } | d t d | ƒ 7} n  x t
 | ƒ D] } | d 7} qÁW| d 7} | t ƒ  S(!   NR   RA   R@   R?   i    t   fails^   #pragma omp parallel for private(r_st, r_end, r_idx, i_idx, o_idx, collector) schedule(static)t    s  
        int typenum = PyArray_ObjectType((PyObject*)%(x)s, 0);
        if(PyArray_NDIM(%(x)s)!=%(total_ndim)s)
        {
            PyErr_SetString(PyExc_ValueError, "x must be a %(total_ndim)sD ndarray");
            %(fail)s;
        }
        if(PyArray_DIM(%(ws)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "ws must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(stride)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "stride must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(pad)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "pad must be a vector of size %(nd)s");
            %(fail)s;
        }
        int z[%(nd)s]; // shape of the output
        int r[%(nd)s]; // shape of the padded_input
        int ws[%(nd)s];
        int st[%(nd)s];
        int pd[%(nd)s];
        int nonzero_padding;
        nonzero_padding = 0;
        for (int i=0; i<%(nd)s; i++)
        {
            ws[i] = *((npy_intp*)PyArray_GETPTR1(%(ws)s, i));
            st[i] = *((npy_intp*)PyArray_GETPTR1(%(stride)s, i));
            pd[i] = *((npy_intp*)PyArray_GETPTR1(%(pad)s, i));
            r[i] = PyArray_DIMS(%(x)s)[%(non_pool_ndim)s + i] + 2 * pd[i];
            if (pd[i]>0)
                nonzero_padding = 1;
        }
        if (!%(ignore_border)s && nonzero_padding)
        {
            PyErr_SetString(PyExc_ValueError,
              "padding must be zero when ignore border is False");
            %(fail)s;
        }
        if (%(ignore_border)s)
        {
            for (int i=0; i<%(nd)s; i++)
            {
                // '/' in C is different from '/' in python
                if (r[i] - ws[i] < 0)
                {
                  z[i] = 0;
                }
                else
                {
                  z[i] = (r[i] - ws[i]) / st[i] + 1;
                }
            }
        }
        else
        {
            for (int i=0; i<%(nd)s; i++)
            {
                // decide how many rows/cols the output has
                if (st[i] >= ws[i])
                {
                    z[i] = (r[i] - 1) / st[i] + 1;
                }
                else
                {
                    z[i] = std::max(0, (r[i] - 1 - ws[i] + st[i]) / st[i]) + 1;
                }
                assert(z[i] > 0);
            }
        }
        // memory allocation of z if necessary
        int mem_nec;
        mem_nec = 0;
        if ((!%(z)s) || *PyArray_DIMS(%(z)s)!=%(total_ndim)s)
        {
            mem_nec = 1;
        }
        if (!mem_nec)
        {
            for (int i=0; i<%(non_pool_ndim)s; i++)
            {
                if (PyArray_DIMS(%(z)s)[i] != PyArray_DIMS(%(x)s)[i])
                {
                    mem_nec = 1;
                    break;
                }
            }
        }
        if (!mem_nec)
        {
            for (int i=0; i<%(nd)s; i++)
            {
                if (PyArray_DIMS(%(z)s)[%(non_pool_ndim)s + i] != z[i])
                {
                    mem_nec = 1;
                    break;
                }
            }
        }
        if (mem_nec)
        {
          if (%(z)s) Py_XDECREF(%(z)s);
          npy_intp dims[%(total_ndim)s];
          for (int i=0; i<%(non_pool_ndim)s; i++)
          {
              dims[i] = PyArray_DIMS(%(x)s)[i];
          }
          for (int i=0; i<%(nd)s; i++)
          {
              dims[%(non_pool_ndim)s + i] = z[i];
          }
          //TODO: zeros not necessary
          %(z)s = (PyArrayObject*) PyArray_ZEROS(%(total_ndim)s, dims, typenum,0);
        }
        // initialize temp var for the value in a region
        dtype_%(x)s collector;
        int z_prod;
        // do not run if any z[i] is zero
        z_prod = 1;
        for (int i=0; i<%(nd)s; i++)
        {
            z_prod *= z[i];
        }
        if (z_prod)
        {
            // will be used to hold start and end index of a region
            int r_st[%(nd)s];
            int r_end[%(nd)s];
            // index for iterating over the pooling regions
            int r_idx[%(nd)s];
            // placeholder for PyArray indexing (output)
            npy_intp o_idx[%(total_ndim)s];
            // placeholder for PyArray indexing (input)
            npy_intp i_idx[%(total_ndim)s];
            // loop over non-pooling dimensions
            int non_pooling_prod = 1;
            for (int i=0; i<%(non_pool_ndim)s; i++)
            {
                non_pooling_prod *= PyArray_DIMS(%(x)s)[i];
            }
            %(omp_parallel)s
            // first loop over non-pooling dimensions
            for (int t=0; t<non_pooling_prod; t++)
            {
                // compute the non-pooling index in each dimension
                if (%(non_pool_ndim)s!=0)
                {
                    o_idx[0] = t;
                    i_idx[0] = t;
                    for (int i=1; i<%(non_pool_ndim)s; i++)
                    {
                        o_idx[i] = o_idx[i - 1] / PyArray_DIMS(%(x)s)[i - 1];
                        o_idx[i - 1] = o_idx[i - 1] %% PyArray_DIMS(%(x)s)[i - 1];
                        i_idx[i] = o_idx[i];
                        i_idx[i - 1] = o_idx[i - 1];
                    }
                }

                // then loop over each region in each pooling dimension
        sÎ  
                for (r_idx[%(i)s]=0; r_idx[%(i)s] < z[%(i)s]; r_idx[%(i)s]++) {
                  r_st[%(i)s] = r_idx[%(i)s] * st[%(i)s];
                  r_end[%(i)s] = r_st[%(i)s] + ws[%(i)s];
                  // skip the padding
                  r_st[%(i)s] = r_st[%(i)s] < pd[%(i)s] ? pd[%(i)s] : r_st[%(i)s];
                  r_end[%(i)s] = r_end[%(i)s] > (r[%(i)s] - pd[%(i)s]) ? r[%(i)s] - pd[%(i)s] : r_end[%(i)s];
                  // from padded_img space to img space
                  r_st[%(i)s] -= pd[%(i)s];
                  r_end[%(i)s] -= pd[%(i)s];
                  // handle the case where no padding, ignore border is True
                  if (%(ignore_border)s)
                  {
                    r_end[%(i)s] = r_end[%(i)s] > r[%(i)s] ? r[%(i)s] : r_end[%(i)s];
                  }
                  // use the index to find the correct position in the output
                  o_idx[%(non_pool_ndim)s + %(i)s] = r_idx[%(i)s];
            R(   R   t   non_pool_ndimsi  
                  // get a pointer to the correct position in the output
                  dtype_%(z)s * z;
                  if (%(total_ndim)s == 4)
                    z = ((dtype_%(z)s*)(PyArray_GETPTR4(%(z)s, o_idx[0], o_idx[1], o_idx[2], o_idx[3])));
                  else
                    z = ((dtype_%(z)s*)(PyArray_GetPtr(%(z)s, o_idx)));
        s   
                  // set the first index of dimension %(i)s
                  i_idx[%(non_pool_ndim)s + %(i)s] = r_st[%(i)s];
                s_  
                  // use the first element as the initial value of collector
                  if (%(total_ndim)s == 4)
                    collector = ((dtype_%(x)s*)(PyArray_GETPTR4(%(x)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])))[0];
                  else
                    collector = ((dtype_%(x)s*)(PyArray_GetPtr(%(x)s,i_idx)))[0];
            sù   
                  // go through the pooled region in the unpadded input
                  for(int m%(i)s=r_st[%(i)s]; m%(i)s<r_end[%(i)s]; m%(i)s++)
                  {
                    i_idx[%(non_pool_ndim)s + %(i)s] = m%(i)s;
                s”  
                    // update maximum
                    dtype_%(x)s a;
                    if (%(total_ndim)s == 4)
                      a = ((dtype_%(x)s*)(PyArray_GETPTR4(%(x)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])))[0];
                    else
                      a = ((dtype_%(x)s*)(PyArray_GetPtr(%(x)s,i_idx)))[0];
                    collector = (a > collector) ? a : collector;
            s=   
                  } // for loop over region
                s1   
                  z[0] = collector;
            so   
                  // initialize the sum at zero
                  collector = ((dtype_%(x)s)(0));
            ss  
                    // update sum
                    dtype_%(x)s a;
                    if (%(total_ndim)s == 4)
                      a = ((dtype_%(x)s*)(PyArray_GETPTR4(%(x)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])))[0];
                    else
                      a = ((dtype_%(x)s*)(PyArray_GetPtr(%(x)s,i_idx)))[0];
                    collector += a;
            s5   
                  z[0] = collector;
                s    * c         s` s   |  ] } d  | Vq d S(   s   ws[%d]N(    (   R'   R(   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>u  s    sI   
                  z[0] = collector / (%(region_size)s);
                t   region_sizec         s` s   |  ] } d  | | f Vq d S(   s   (r_end[%d]-r_st[%d])N(    (   R'   R(   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>{  s    s:   
            } // loop over pooling dimension
            sT   
          } // for loop over non-pooling dimensions
        } // if z_prod
        (   s   maxs   sums   average_exc_pads   average_inc_pad(   s   sums   average_exc_pads   average_inc_pad(   R   R+   R   t   utilst   MethodNotDefinedR   RE   t   intR   R>   R   t   dictt   joint   locals(   RD   RJ   t   nameRf   R2   t   subRW   R   R   R   R[   RX   t
   total_ndimRˆ   R†   R   t   omp_parallelt   ccodeR(   R‰   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   c_code`  sz    		

		¥$

c         C` s   d d d d |  j  f S(   Ni    i   i   i   (   R>   (   RD   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   c_code_cache_versionŠ  s    (   t   __name__t
   __module__t   __doc__t	   __props__t   staticmethodR   R   R<   RC   RN   RZ   Ru   Rx   R~   R   Rƒ   R„   R•   R–   (    (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR
     s"   #…
	#	4						ÿ +t   PoolGradc        
   B` sY   e  Z d	 Z e d
 e d
 d
 d d
 d
 d
 d „ ƒ Z d d d
 d „ Z d „  Z d „  Z	 RS(   R   R   R   i   c	         ` sÏ  | d k	 rC | d k	 r' t d ƒ ‚ qj t j d d d ƒ| } n' | d k rj | d k rj t d ƒ ‚ n  | d k	 r­ | d k	 r‘ t d ƒ ‚ q­ t j d d d ƒ| } n  | d k	 rð ˆ d k	 rÔ t d ƒ ‚ qð t j d	 d d ƒ| ‰ n  t ˆ ƒ ˆ k  rt d
 j ˆ ƒ ƒ ‚ n  | d k r/| } n  ˆ d k rHd ˆ ‰ n  t ‡ ‡ ‡ f d †  t ˆ ƒ Dƒ ƒ }	 ‡  f d †  }
 g  t ˆ ƒ D]$ } |
 |	 | | | | | ƒ ^ qŒ} t	 ˆ ˆ  ƒ | } | S(   s8  Return the shape of the output from this op, for input of given
        shape and flags.

        Parameters
        ----------
        imgshape : tuple of integers or scalar Theano variables
            the shape of a tensor of images. The last N elements are
            interpreted as the downsampling dimensions.
        ws : tuple of N ints
            downsample factor over rows and columns this parameter
            indicates the size of the pooling region
        ignore_border : bool
            If ws doesn't divide imgshape, do we include an extra row/col/slice
            of partial downsampling (False) or ignore it (True).
        stride : list or tuple of N ints or None
            Stride size, which is the number of shifts over rows/cols/slices to get the
            next pool region. If stride is None, it is considered equal to ws
            (no overlap on pooling regions).
        pad : tuple of N ints or None
            For each downsampling dimension, this specifies the number of zeros to
            add as padding on both sides. For 2D and (pad_h, pad_w), pad_h specifies the
            size of the top and bottom margins, pad_w specifies the size of the left and
            right margins. No padding is added if pad is None.
        ndim : int
            The number of pooling dimensions N.
            The default is 2.
        ds
            *deprecated*, use parameter ws instead.
        st
            *deprecated*, use parameter st instead.
        padding
            *deprecated*, use parameter pad instead.

        Returns
        -------
        list :
            the shape of the output from this op, for input of given
            shape.  This will have the same length as imgshape, but
            with last N elements reduced as per the downsampling &
            ignore_border flags.

        s[   You can't provide a tuple value to both 'ws' and 'ds'. Please provide a value only to 'ws'.s~   DEPRECATION: the 'ds' parameter in PoolGrad is not going to exist anymore as it is going to be replaced by the parameter 'ws'.R   i   s3   You must provide a tuple value for the window size.sb   You can't provide a tuple value to both 'st and 'stride'. Please provide a value only to 'stride'.s‚   DEPRECATION: the 'st' parameter in PoolGrad is not going to exist anymore as it is going to be replaced by the parameter 'stride'.s_   You can't provide a tuple value to both 'padding' and pad.  Please provide a value only to pad.s„   DEPRECATION: the 'padding' parameter in PoolGrad is not going to exist anymore as it is going to be replaced by the parameter 'pad'.s)   imgshape must have at least {} dimensionsi    c         3` s3   |  ]) } t  j ˆ  ˆ | ƒ ˆ | d  Vq d S(   i   N(   R   R&   (   R'   R(   (   R)   R   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>÷  s   c         ` së   ˆ  rM |  | | d } t  | t j ƒ r: t j | d ƒ St j | d ƒ Snš t  |  t j ƒ rª t j t j | | ƒ |  d | d t j d |  d | | d ƒ d ƒ S| | k rÆ |  d | d St d |  d | | d ƒ d Sd  S(   Ni   i    (	   R*   R+   R   R   R,   R-   R.   R/   R   (   R0   R1   R   R2   (   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR3   ú  s    N(   i    (
   R   R   R   R   R5   R6   R7   R8   R   R9   (   R)   R   R   R   R   R   R    R!   R"   R;   R3   R(   R<   R=   (    (   R   R)   R   R   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR<   ‘  sN    .				7R   c         C` sW   | |  _  | |  _ | d k r1 t d | ƒ ‚ n  | |  _ t t |  ƒ j d | ƒ d  S(   NR   RA   R?   R@   s^   Pool mode parameter only support 'max', 'sum', 'average_inc_pad' and 'average_exc_pad'. Got %sR>   (   s   maxs   sums   average_inc_pads   average_exc_pad(   R   R   R   R   RB   Rœ   RC   (   RD   R   R   R   R>   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRC     s    			c         C` sœ  t  | j ƒ d k  r˜t  | j j ƒ |  _ | j j |  _ t j j | j j ƒ } t j j | j j	 ƒ } t j j | j j
 ƒ } | j j | ƒ | j j | ƒ | j j | ƒ t | t j ƒ rã | j g | | <t g | | <n d  g | | <t g | | <t | t j ƒ r/| j g | | <t g | | <n d  g | | <t g | | <t | t j ƒ r{| j g | | <t g | | <q˜d  g | | <t g | | <n  d  S(   Ni   (   R5   RE   R#   R    R   R   R+   R   RF   R!   R"   RG   R*   RH   RI   R   R   R   (   RD   RJ   RK   RL   RM   R   R!   R   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRN     s0    c         C` s   | d g S(   Ni    (    (   RD   RJ   Rv   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRx   9  s    (   s   ignore_borders   modes   ndimN(
   R—   R˜   Rš   R›   R   R   R<   RC   RN   Rx   (    (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRœ   Ž  s   ~
	R   c           B` sS   e  Z d  d d „ Z d d d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z	 RS(	   i   c      	   C` s&   t  j |  | d d d | d | ƒd  S(   NR   R   R   R>   (   Rœ   RC   (   RD   R   R   R>   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRC   >  s    c         C` s-  t  j | ƒ } t  j | ƒ } t  j | ƒ } |  j } | d  k rK | } n  | d  k rd d | } n  t  j | ƒ } t  j | ƒ } t  j | ƒ } t | t ƒ r¯ | j | k sµ t ‚ t | t ƒ rÓ | j | k sÙ t ‚ t | t ƒ r÷ | j | k sý t ‚ t | t ƒ r| j d k s!t ‚ t | t ƒ r?| j d k sEt ‚ t | t ƒ rc| j d k sit ‚ | j | j k o”| j k o”| k n sŸt ‚ | j t  j k rÀt	 d ƒ ‚ n  | j t  j k rát	 d ƒ ‚ n  | j t  j k rt	 d ƒ ‚ n  t
 |  | | | | | | g | j ƒ  g ƒ S(   Ni    i   s(   Pool downsample parameters must be ints.s   Stride parameters must be ints.s    Padding parameters must be ints.(   i    (   R   RO   R   R   R*   R   R4   RS   RT   R6   R   RR   (   RD   RW   R}   R{   R   R   R   RX   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRZ   A  s2    		$$$$$$6c         ` s@  |  j  d k s t ‚ | \ ‰ } } } } ‰ | \ } |  j ‰ | j | j k om ˆ j k om ˆ f k n sx t ‚ t ˆ j ƒ ˆ k  r¥ t d j ˆ ƒ ƒ ‚ n  | j ˆ }	 t ‡ ‡ ‡ f d †  t ˆ ƒ Dƒ ƒ ‰  t	 ˆ ƒ d k r[t
 j ˆ j ˆ  ˆ  d ˆ j ƒ}
 ˆ |
 t d  ƒ f t ˆ j ƒ ˆ t ‡  ‡ f d †  t ˆ ƒ Dƒ ƒ <n ˆ }
 t
 j |
 ƒ } g  t ˆ ƒ D] } g  ^ q}} x… t ˆ ƒ D]w } xn t |	 | ƒ D]\ } t j	 | | | ˆ | ƒ } t j | | | ˆ  | ƒ } | | j t | | ƒ ƒ q³WqœWxÑ t
 j ˆ j ˆ  Œ  D]¸ } | | } | | } |
 | } | | } x‡ t
 j |	 Œ  D]v } | | } xc t j g  t ˆ ƒ D] } | | | | ^ q“Œ  D]- } | | | k r²| | c | | 7<q²q²WqmWq/W| t d  ƒ f t ˆ j ƒ ˆ t ‡  ‡ f d †  t ˆ ƒ Dƒ ƒ } | | d <d  S(   NR   s5   MaxPoolGrad requires input with {} or more dimensionsc         3` s-   |  ]# } ˆ j  ˆ  | d  ˆ | Vq d S(   i   N(   R\   (   R'   R(   (   RX   R   RW   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>h  s    i    RS   c         3` s.   |  ]$ } t  ˆ | ˆ  | ˆ | ƒ Vq d  S(   N(   R]   (   R'   R(   (   R^   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>n  s    c         3` s.   |  ]$ } t  ˆ | ˆ  | ˆ | ƒ Vq d  S(   N(   R]   (   R'   R(   (   R^   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>Œ  s    (   R   R4   R   R\   R5   R   R7   R8   R   R   R-   Ra   RS   R]   R   t
   zeros_likeRc   Rd   RG   Re   t	   itertoolst   product(   RD   RJ   Rf   R2   R}   R{   R   R   t   gx_stgRi   Rk   t   gxR(   t   region_rangesRn   Ro   Rp   Rq   t   gxkt   gzkRs   t   maxoutkRt   t   maxout_valuet   c(    (   R^   RX   R   RW   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRu   ^  sF    		9($J"




/# 'c      	   C` s‘   | \ } } } } } } | \ }	 t  j j | ƒ t  j j | ƒ t d |  j d |  j ƒ | | |	 | | | ƒ g g  | d D] }
 t ƒ  ƒ  ^ qz S(   NR   R   i   (   R+   R   R   R€   R   R   R	   (   RD   Rf   Rz   RW   R}   R{   R   R   R   t   ggxR(   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR~     s    		c         C` s(   d g d g d g d g d g d g g S(   Ni   i    (    (   RD   RJ   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR   ™  s    c         C` sc  |  j  d k s t ‚ | \ } } } }	 }
 } | \ } |  j } | j d j } | | } | d } t |  j ƒ } |  j r„ d } n d } d } x1 t | ƒ D]# } | d t d | d	 | ƒ 7} q W| d
 7} x1 t | ƒ D]# } | d t d | d	 | ƒ 7} qÛ W| d 7} x t | ƒ D] } | d 7} qWx t | ƒ D] } | d 7} q:W| d 7} | t	 ƒ  S(   NR   i    R†   s\   #pragma omp parallel for private(r_st, r_end, r_idx, i_idx, o_idx, maximum) schedule(static)R‡   s  
        // sanity checks
        int x_typenum = PyArray_ObjectType((PyObject*)%(x)s, 0);
        int z_typenum = PyArray_ObjectType((PyObject*)%(z)s, 0);
        int gz_typenum = PyArray_ObjectType((PyObject*)%(gz)s, 0);
        if ((x_typenum != z_typenum) || (x_typenum != gz_typenum))
        {
            PyErr_SetString(PyExc_ValueError, "input types must all match");
            %(fail)s;
        }
        if(PyArray_NDIM(%(x)s)!=%(total_ndim)s)
        {
            PyErr_SetString(PyExc_ValueError, "x must be a %(total_ndim)sD ndarray");
            %(fail)s;
        }
        if(PyArray_NDIM(%(z)s)!=%(total_ndim)s)
        {
            PyErr_SetString(PyExc_ValueError, "z must be a %(total_ndim)sD ndarray");
            %(fail)s;
        }
        if(PyArray_NDIM(%(gz)s)!=%(total_ndim)s)
        {
            PyErr_SetString(PyExc_ValueError, "gz must be a %(total_ndim)sD ndarray");
            %(fail)s;
        }
        if(PyArray_DIM(%(ws)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "ws must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(stride)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "stride must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(pad)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "pad must be a vector of size %(nd)s");
            %(fail)s;
        }
        int z[%(nd)s]; // shape of the output
        int r[%(nd)s]; // shape of the padded_input
        int ws[%(nd)s];
        int st[%(nd)s];
        int pd[%(nd)s];
        int nonzero_padding;
        nonzero_padding = 0;
        for (int i=0; i<%(nd)s; i++)
        {
            ws[i] = *((npy_intp*)PyArray_GETPTR1(%(ws)s, i));
            st[i] = *((npy_intp*)PyArray_GETPTR1(%(stride)s, i));
            pd[i] = *((npy_intp*)PyArray_GETPTR1(%(pad)s, i));
            z[i] = PyArray_DIMS(%(z)s)[%(non_pool_ndim)s + i];
            r[i] = PyArray_DIMS(%(x)s)[%(non_pool_ndim)s + i] + 2 * pd[i];
            if (pd[i]>0)
                nonzero_padding = 1;
        }
        // allocating memory for output, if necessary
        int mem_nec;
        mem_nec = 0;
        if ((!%(gx)s) || !PyArray_ISCONTIGUOUS(%(gx)s)
            || *PyArray_DIMS(%(gx)s)!=%(total_ndim)s)
        {
            mem_nec = 1;
        }
        if (!mem_nec)
        {
            for (int i=0; i<%(total_ndim)s; i++)
            {
                if (PyArray_DIMS(%(gx)s)[i] != PyArray_DIMS(%(x)s)[i])
                {
                    mem_nec = 1;
                    break;
                }
            }
        }
        if (mem_nec)
        {
          Py_XDECREF(%(gx)s);
          %(gx)s = (PyArrayObject*) PyArray_ZEROS(%(total_ndim)s, PyArray_DIMS(%(x)s), x_typenum,0);
        }
        else {
          PyArray_FILLWBYTE(%(gx)s, 0);
        }
        dtype_%(z)s maximum; // temp var for maximum value in a region
        int z_prod;
        // do not run if any z[i] is zero
        z_prod = 1;
        for (int i=0; i<%(nd)s; i++)
        {
            z_prod *= z[i];
        }
        if (z_prod)
        {
            // will be used to hold start and end index of a region
            int r_st[%(nd)s];
            int r_end[%(nd)s];
            // index for iterating over the pooling regions
            int r_idx[%(nd)s];
            // placeholder for PyArray indexing (output)
            npy_intp o_idx[%(total_ndim)s];
            // placeholder for PyArray indexing (input)
            npy_intp i_idx[%(total_ndim)s];
            // loop over non-pooling dimensions
            int non_pooling_prod = 1;
            for (int i=0; i<%(non_pool_ndim)s; i++)
            {
                non_pooling_prod *= PyArray_DIMS(%(x)s)[i];
            }
            %(omp_parallel)s
            // first loop over non-pooling dimensions
            for (int t=0; t<non_pooling_prod; t++)
            {
                // compute the non-pooling index in each dimension
                if (%(non_pool_ndim)s!=0)
                {
                    o_idx[0] = t;
                    i_idx[0] = t;
                    for (int i=1; i<%(non_pool_ndim)s; i++)
                    {
                        o_idx[i] = o_idx[i - 1] / PyArray_DIMS(%(x)s)[i - 1];
                        o_idx[i - 1] =o_idx[i - 1] %% PyArray_DIMS(%(x)s)[i - 1];
                        i_idx[i] = o_idx[i];
                        i_idx[i - 1] = o_idx[i - 1];
                    }
                }

                // then loop over each region in each pooling dimension
        sÚ  
                for (r_idx[%(i)s]=0; r_idx[%(i)s] < z[%(i)s]; r_idx[%(i)s]++) {
                  r_st[%(i)s] = r_idx[%(i)s] * st[%(i)s];
                  r_end[%(i)s] = r_st[%(i)s] + ws[%(i)s];
                  // skip the padding
                  r_st[%(i)s] = r_st[%(i)s] < pd[%(i)s] ? pd[%(i)s] : r_st[%(i)s];
                  r_end[%(i)s] = r_end[%(i)s] > (r[%(i)s] - pd[%(i)s]) ? r[%(i)s] - pd[%(i)s] : r_end[%(i)s];
                  // from padded_img space to img space
                  r_st[%(i)s] -= pd[%(i)s];
                  r_end[%(i)s] -= pd[%(i)s];
                  // use the index to find the correct position in the output
                  o_idx[%(non_pool_ndim)s + %(i)s] = r_idx[%(i)s];
            R(   Rˆ   s   
                  dtype_%(gz)s * gz;
                  if (%(total_ndim)s == 4)
                  {
                    // the maximum value
                    maximum = ((dtype_%(z)s*)(PyArray_GETPTR4(%(z)s,o_idx[0],o_idx[1],o_idx[2],o_idx[3])))[0];
                    // the gradient corresponding to this maximum value in z
                    gz = ((dtype_%(gz)s*)(PyArray_GETPTR4(%(gz)s, o_idx[0],o_idx[1],o_idx[2],o_idx[3])));
                  }
                  else
                  {
                    // the maximum value
                    maximum = ((dtype_%(z)s*)(PyArray_GetPtr(%(z)s,o_idx)))[0];
                    // the gradient corresponding to this maximum value in z
                    gz = ((dtype_%(gz)s*)(PyArray_GetPtr(%(gz)s, o_idx)));
                  }
        sù   
                  // go through the pooled region in the unpadded input
                  for(int m%(i)s=r_st[%(i)s]; m%(i)s<r_end[%(i)s]; m%(i)s++)
                  {
                    i_idx[%(non_pool_ndim)s + %(i)s] = m%(i)s;
                sË  
                    dtype_%(x)s a;
                    dtype_%(gx)s * gx;
                    if (%(total_ndim)s == 4)
                    {
                      a = ((dtype_%(x)s*)(PyArray_GETPTR4(%(x)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])))[0];
                      gx = ((dtype_%(gx)s*)(PyArray_GETPTR4(%(gx)s, i_idx[0],i_idx[1],i_idx[2],i_idx[3])));
                    }
                    else
                    {
                      a = ((dtype_%(x)s*)(PyArray_GetPtr(%(x)s,i_idx)))[0];
                      gx = ((dtype_%(gx)s*)(PyArray_GetPtr(%(gx)s, i_idx)));
                    }
                    if (a == maximum){
                      gx[0] = gx[0] + gz[0];
                    }
        s=   
                  } // for loop over region
                s>   
                } // loop over pooling dimension
            sV   
            } // for loop over non-pooling dimensions
        } // if z_prod
        (
   R   R4   R   RE   RŒ   R   R>   R   R   R   (   RD   RJ   R   Rf   R2   R‘   RW   R[   R{   R   R   R   R¡   RX   R’   Rˆ   R†   R   R“   R”   R(   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR•   œ  s>    		

		‚c         C` s   d d |  j  f S(   Ni    i
   (   R>   (   RD   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR–   t  s    N(
   R—   R˜   R   RC   RZ   Ru   R~   R   R•   R–   (    (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR   =  s   	1	
		ØRy   c           B` sV   e  Z d  d d „ Z d	 d	 d	 d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z	 RS(
   R?   i   c         C` s,   | d k s t  ‚ t j |  | | | ƒ d  S(   NRA   R?   R@   (   s   sums   average_inc_pads   average_exc_pad(   R4   Rœ   RC   (   RD   R   R   R   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRC   y  s    c         C` sé  t  j | ƒ } t  j | ƒ } |  j } | d  k r< | } n  | d  k rU d | } n  t  j | ƒ } t  j | ƒ } t  j | ƒ } t | t ƒ r  | j | k s¦ t ‚ t | t ƒ rÄ | j | k sÊ t ‚ t | t ƒ rè | j d k sî t ‚ t | t ƒ r| j d k st ‚ | j | j k o/| k n s:t ‚ t | t ƒ rX| j d k s^t ‚ | j t  j k rt	 d ƒ ‚ n  | j t  j k r t	 d ƒ ‚ n  | j t  j k rÁt	 d ƒ ‚ n  t
 |  | | | | | g | j ƒ  g ƒ S(   Ni    i   s(   Pool downsample parameters must be ints.s   Stride parameters must be ints.s    Padding parameters must be ints.(   i    (   R   RO   R   R   R*   R   R4   RS   RT   R6   R   RR   (   RD   RW   R{   R   R   R   t   dummyRX   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRZ     s.    		$$$$($c         ` sÆ  | \ ‰ } } } ‰ | \ } |  j  ‰ | j | j k oU ˆ j k oU ˆ f k n s` t ‚ t ˆ j ƒ ˆ k  r t d j ˆ ƒ ƒ ‚ n  |  j d k rº t ˆ ƒ d k rº t ƒ  ‚ n  |  j ˆ j | |  j	 | ˆ ˆ ƒ } | d d  k s| d j | k r t j | d ˆ j ƒ| d <n  | d }	 |	 j ˆ }
 t ‡ ‡ ‡ f d †  t ˆ ƒ Dƒ ƒ ‰  |  j d k } |  j d k } t j ˆ j ˆ  ˆ  d ˆ j ƒ} g  t ˆ ƒ D] } g  ^ q¯} g  t ˆ ƒ D] } g  ^ qÎ} x· t ˆ ƒ D]© } x  t |
 | ƒ D]Ž } | s| r'| | | } n t j | | | ˆ | ƒ } t j | | | ˆ  | ƒ } | | j t | | ƒ ƒ | | j | | ƒ qWqíWd  g ˆ } xÇ t j ˆ j ˆ  Œ  D]® } | | } | | } x‘ t j |
 Œ  D]€ } d } x@ t ˆ ƒ D]2 } | | | | | | <| | | | | 9} qW| rK| | } n | | | } | | c | 7<qéWq¿W| t d  ƒ f t ˆ j ƒ ˆ t ‡  ‡ f d	 †  t ˆ ƒ Dƒ ƒ } | | d <d  S(
   Ns9   AveragePoolGrad requires input with {} or more dimensionsR@   i    RS   c         3` s-   |  ]# } ˆ j  ˆ  | d  ˆ | Vq d S(   i   N(   R\   (   R'   R(   (   RX   R   RW   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>¬  s    R?   RA   i   c         3` s.   |  ]$ } t  ˆ | ˆ  | ˆ | ƒ Vq d  S(   N(   R]   (   R'   R(   (   R^   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>Ô  s    (   R   R\   R4   R5   R   R7   R   R   R<   R   R   R-   R`   RS   R8   R   Ra   Rc   Rd   RG   R]   Re   (   RD   RJ   Rf   R2   R{   R   R   R    Rg   Rh   Ri   Rj   t   sum_modeR¡   R(   Rm   t   region_sizesRn   Ro   Rp   t   region_sliceRq   R¤   R£   Rt   R‰   t   val(    (   R^   RX   R   RW   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRu   œ  sX    		9!$#
($

 'c   
      C` s‚   | \ } } } } } | \ } t  j j | ƒ t d |  j d |  j d |  j ƒ | | | | ƒ g g  | d D] }	 t ƒ  ƒ  ^ qk S(   NR   R   R   i   (   R+   R   R   R
   R   R   R   R	   (
   RD   Rf   Rz   RW   R{   R   R   R   R¨   R(   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR~   ×  s    	c         C` s"   d g d g d g d g d g g S(   Ni   i    (    (   RD   RJ   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR   ß  s    c         C` s‘  | \ } } } }	 }
 | \ } |  j  } | j d j  } | | } | d } t |  j d k ƒ } t |  j d k ƒ } |  j r‡ d } n d } d } x= t | ƒ D]/ } | d t d	 | d
 | d | d | ƒ 7} q  W| d 7} d j d „  t | ƒ Dƒ ƒ } x1 t | ƒ D]# } | d t d	 | d | ƒ 7} q	W| d 7} x t | ƒ D] } | d 7} qGWx t | ƒ D] } | d 7} qhW| d 7} | t ƒ  S(   Ni    R†   R?   RA   s`   #pragma omp parallel for private(r_st, r_end, r_pad_width, r_idx, i_idx, o_idx) schedule(static)R‡   sÖ  
        // sanity checks
        int x_typenum = PyArray_ObjectType((PyObject*)%(x)s, 0);
        int gz_typenum = PyArray_ObjectType((PyObject*)%(gz)s, 0);
        if (x_typenum != gz_typenum)
        {
            PyErr_SetString(PyExc_ValueError, "input types must all match");
            %(fail)s;
        }
        if(PyArray_NDIM(%(x)s)!=%(total_ndim)s)
        {
            PyErr_SetString(PyExc_ValueError, "x must be a %(total_ndim)sD ndarray");
            %(fail)s;
        }
        if(PyArray_NDIM(%(gz)s)!=%(total_ndim)s)
        {
            PyErr_SetString(PyExc_ValueError, "gz must be a %(total_ndim)sD ndarray");
            %(fail)s;
        }
        if(PyArray_DIM(%(ws)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "ws must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(stride)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "stride must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(pad)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "pad must be a vector of size %(nd)s");
            %(fail)s;
        }
        int z[%(nd)s]; // shape of the output
        int r[%(nd)s]; // shape of the padded_input
        int ws[%(nd)s];
        int st[%(nd)s];
        int pd[%(nd)s];
        int nonzero_padding;
        nonzero_padding = 0;
        for (int i=0; i<%(nd)s; i++)
        {
            ws[i] = *((npy_intp*)PyArray_GETPTR1(%(ws)s, i));
            st[i] = *((npy_intp*)PyArray_GETPTR1(%(stride)s, i));
            pd[i] = *((npy_intp*)PyArray_GETPTR1(%(pad)s, i));
            z[i] = PyArray_DIMS(%(gz)s)[%(non_pool_ndim)s + i];
            r[i] = PyArray_DIMS(%(x)s)[%(non_pool_ndim)s + i] + 2 * pd[i];
            if (pd[i]>0)
                nonzero_padding = 1;
        }
        if (!%(inc_pad)s && !%(sum_mode)s && nonzero_padding)
        {
            PyErr_SetString(PyExc_ValueError,
              "padding must be zero for average_exc_pad");
            %(fail)s;
        }
        // allocating memory for output, if necessary
        int mem_nec;
        mem_nec = 0;
        if ((!%(gx)s) || !PyArray_ISCONTIGUOUS(%(gx)s)
            || *PyArray_DIMS(%(gx)s)!=%(total_ndim)s)
        {
            mem_nec = 1;
        }
        if (!mem_nec)
        {
            for (int i=0; i<%(total_ndim)s; i++)
            {
                if (PyArray_DIMS(%(gx)s)[i] != PyArray_DIMS(%(x)s)[i])
                {
                    mem_nec = 1;
                    break;
                }
            }
        }
        if (mem_nec)
        {
          Py_XDECREF(%(gx)s);
          %(gx)s = (PyArrayObject*) PyArray_ZEROS(%(total_ndim)s, PyArray_DIMS(%(x)s), x_typenum,0);
        }
        else {
          PyArray_FILLWBYTE(%(gx)s, 0);
        }
        int z_prod;
        // do not run if any z[i] is zero
        z_prod = 1;
        for (int i=0; i<%(nd)s; i++)
        {
            z_prod *= z[i];
        }
        if (z_prod)
        {
            // will be used to hold start and end index of a region
            int r_st[%(nd)s];
            int r_end[%(nd)s];
            // padded region size
            int r_pad_width[%(nd)s];
            // index for iterating over the pooling regions
            int r_idx[%(nd)s];
            // placeholder for PyArray indexing (output)
            npy_intp o_idx[%(total_ndim)s];
            // placeholder for PyArray indexing (input)
            npy_intp i_idx[%(total_ndim)s];
            // loop over non-pooling dimensions
            int non_pooling_prod = 1;
            for (int i=0; i<%(non_pool_ndim)s; i++)
            {
                non_pooling_prod *= PyArray_DIMS(%(x)s)[i];
            }
            %(omp_parallel)s
            // first loop over non-pooling dimensions
            for (int t=0; t<non_pooling_prod; t++)
            {
                // compute the non-pooling index in each dimension
                if (%(non_pool_ndim)s!=0)
                {
                    o_idx[0] = t;
                    i_idx[0] = t;
                    for (int i=1; i<%(non_pool_ndim)s; i++)
                    {
                        o_idx[i] = o_idx[i - 1] / PyArray_DIMS(%(x)s)[i - 1];
                        o_idx[i - 1] =o_idx[i - 1] %% PyArray_DIMS(%(x)s)[i - 1];
                        i_idx[i] = o_idx[i];
                        i_idx[i - 1] = o_idx[i - 1];
                    }
                }

                // then loop over each region in each pooling dimension
        s®  
                for (r_idx[%(i)s]=0; r_idx[%(i)s] < z[%(i)s]; r_idx[%(i)s]++) {
                  r_st[%(i)s] = r_idx[%(i)s] * st[%(i)s];
                  if (!%(sum_mode)s && !%(inc_pad)s && r_st[%(i)s] < pd[%(i)s])
                  {
                    r_st[%(i)s] = pd[%(i)s];
                  }
                  r_end[%(i)s] = r_st[%(i)s] + ws[%(i)s];
                  r_end[%(i)s] = r_end[%(i)s] > r[%(i)s] ? r[%(i)s] : r_end[%(i)s];
                  r_pad_width[%(i)s] = r_end[%(i)s] - r_st[%(i)s];
                  // from padded_img space to img space
                  r_st[%(i)s] = r_st[%(i)s] - pd[%(i)s] > 0 ? r_st[%(i)s] - pd[%(i)s] : 0;
                  r_end[%(i)s] = r_end[%(i)s] > r[%(i)s] - pd[%(i)s] ? r[%(i)s] - 2 * pd[%(i)s] : r_end[%(i)s] - pd[%(i)s];

                  // use the index to find the correct position in the output
                  o_idx[%(non_pool_ndim)s + %(i)s] = r_idx[%(i)s];
            R(   Rª   Rj   Rˆ   s  
                  dtype_%(gz)s * gz;
                  dtype_%(gz)s val;
                  if (%(total_ndim)s == 4)
                  {
                    // the gradient for this region
                    gz = ((dtype_%(gz)s*)(PyArray_GETPTR4(%(gz)s, o_idx[0],o_idx[1],o_idx[2],o_idx[3])));
                  }
                  else
                  {
                    // the gradient for this region
                    gz = ((dtype_%(gz)s*)(PyArray_GetPtr(%(gz)s, o_idx)));
                  }
                  // compute the contribution
                  if (%(sum_mode)s)
                  {
                    val = gz[0];
                  }
                  else
                  {
                    val = gz[0] / (%(region_size)s);
                  }
        s    * c         s` s   |  ] } d  | Vq d S(   s   r_pad_width[%d]N(    (   R'   R(   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>ž  s    sù   
                  // go through the pooled region in the unpadded input
                  for(int m%(i)s=r_st[%(i)s]; m%(i)s<r_end[%(i)s]; m%(i)s++)
                  {
                    i_idx[%(non_pool_ndim)s + %(i)s] = m%(i)s;
                s°  
                    dtype_%(gx)s * gx;
                    if (%(total_ndim)s == 4)
                    {
                      gx = ((dtype_%(gx)s*)(PyArray_GETPTR4(%(gx)s, i_idx[0],i_idx[1],i_idx[2],i_idx[3])));
                    }
                    else
                    {
                      gx = ((dtype_%(gx)s*)(PyArray_GetPtr(%(gx)s, i_idx)));
                    }
                    gx[0] = gx[0] + val;
        s=   
                  } // for loop over region
                s>   
                } // loop over pooling dimension
            sV   
            } // for loop over non-pooling dimensions
        } // if z_prod
        (	   R   RE   RŒ   R   R>   R   R   RŽ   R   (   RD   RJ   R   Rf   R2   R‘   RW   R{   R   R   R   R¡   RX   R’   Rˆ   R†   Rj   Rª   R“   R”   R(   R‰   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR•   â  s@    		

		ƒ*c         C` s   d d |  j  f S(   Ni    i   (   R>   (   RD   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR–   Á  s    N(
   R—   R˜   RC   R   RZ   Ru   R~   R   R•   R–   (    (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRy   x  s   	;			ßR€   c           B` se   e  Z d Z d d d d „ Z d d d „ Z d „  Z d „  Z d	 „  Z d
 „  Z	 d „  Z
 d „  Z RS(   R   R   R   R   i   c         C` sM   | |  _  | |  _ | |  _ t t |  ƒ j d | ƒ |  j d k sI t ‚ d  S(   NR>   R   (   R   R   R   RB   R€   RC   R4   (   RD   R   R   R   R>   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRC   È  s
    			c         ` s#  t  j | ƒ } t  j | ƒ } t  j | ƒ } |  j } | d  k rK ˆ } n  ˆ  d  k rd d	 | ‰  n t ˆ  t t f ƒ ró t ˆ  ƒ d k r¤ |  j r¤ t	 d ƒ ‚ n  t ˆ t t f ƒ ró t
 ‡  ‡ f d †  t | ƒ Dƒ ƒ rð t	 d ƒ ‚ qð qó n  t  j ˆ ƒ ‰ t  j | ƒ } t  j ˆ  ƒ ‰  ˆ j d k s5t ‚ | j d k sJt ‚ ˆ  j d k s_t ‚ | j | j k oŠ| j k oŠ| k n s•t ‚ ˆ j t  j k r¶t d ƒ ‚ n  | j t  j k r×t d ƒ ‚ n  ˆ  j t  j k røt d ƒ ‚ n  t |  | | | ˆ | ˆ  g | j ƒ  g ƒ S(
   Ni    s*   padding works only with ignore_border=Truec         3` s#   |  ] } ˆ  | ˆ | k Vq d  S(   N(    (   R'   R(   (   R   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>ß  s    s$   padding must be smaller than stridesi   s(   Pool downsample parameters must be ints.s   Stride parameters must be ints.s    Padding parameters must be ints.(   i    (   R   RO   R   R   R*   R8   R9   R   R   R   RP   RQ   R4   RS   RT   R6   R   RR   (   RD   RW   R}   R{   R   R   R   RX   (    (   R   R   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRZ   Ï  s<    		%6c         ` s~  | \ ‰ } } } } ‰ | \ } |  j  ‰ | j | j k oX ˆ j k oX ˆ f k n sc t ‚ t ˆ j ƒ ˆ k  r t d j ˆ ƒ ƒ ‚ n  | d d  k s¶ | d j | j k rØ t j | j d ˆ j	 ƒ| d <n  | d }	 |	 j ˆ }
 t
 ‡ ‡ ‡ f d †  t ˆ ƒ Dƒ ƒ ‰  t ˆ ƒ d k rt j ˆ j ˆ  ˆ  d ˆ j	 ƒ} ˆ | t d  ƒ f t ˆ j ƒ ˆ t
 ‡  ‡ f d †  t ˆ ƒ Dƒ ƒ <t j ˆ j ˆ  ˆ  d ˆ j	 ƒ} | | t d  ƒ f t ˆ j ƒ ˆ t
 ‡  ‡ f d †  t ˆ ƒ Dƒ ƒ <n ˆ } | } g  t ˆ ƒ D] } g  ^ q} xu t ˆ ƒ D]g } x^ t |
 | ƒ D]L } | | | } t j | | | ˆ  | ƒ } | | j t | | ƒ ƒ qRWq;WxÑ t j ˆ j ˆ  Œ  D]¸ } | | } |	 | } | | } | | } x‡ t j |
 Œ  D]v } | | } xc t j g  t ˆ ƒ D] } | | | | ^ q"Œ  D]- } | | | k rA| | c | | 7<qAqAWqüWq¾Wd  S(   NsE   DownsampleFactorMaxGradGrad requires input with {} or more dimensionsi    RS   c         3` s-   |  ]# } ˆ j  ˆ  | d  ˆ | Vq d S(   i   N(   R\   (   R'   R(   (   RX   R   RW   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>ÿ  s    c         3` s.   |  ]$ } t  ˆ | ˆ  | ˆ | ƒ Vq d  S(   N(   R]   (   R'   R(   (   R^   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>  s    c         3` s.   |  ]$ } t  ˆ | ˆ  | ˆ | ƒ Vq d  S(   N(   R]   (   R'   R(   (   R^   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>  s    (   R   R\   R4   R5   R   R7   R   R-   Ra   RS   R8   R   R   R]   Rc   Rd   RG   Re   Rž   RŸ   (   RD   RJ   Rf   R2   R}   R¨   R   R   R[   t   ggzRi   t   y_paddedt
   ggx_paddedR(   R¢   Rn   Ro   Rp   Rq   t   ggxkt   ggzkRs   R¥   Rt   R¦   R§   (    (   R^   RX   R   RW   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRu   ñ  sJ    		9&"
($G$J"




/c         C` s   | d g S(   Ni   (    (   RD   RJ   Rv   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRx   %  s    c   
   	   C` s‹   | \ } } } } } } | \ }	 t  j j | ƒ t  j j | ƒ t d |  j d |  j ƒ | | |	 | | | ƒ t ƒ  ƒ  t ƒ  ƒ  t ƒ  ƒ  g S(   NR   R   (   R+   R   R   R   R   R   R	   (
   RD   Rf   Rz   RW   R}   R¨   R   R   R   R{   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR~   (  s    			c         C` s(   d g d g d g d g d g d g g S(   Ni   i    (    (   RD   RJ   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR   4  s    c         C` sr  |  j  d k r$ t j j j ƒ  ‚ n  | \ } } } }	 }
 } | \ } |  j } | j d j } | | } | d } t |  j ƒ } |  j	 r“ d } n d } d } x1 t
 | ƒ D]# } | d t d | d	 | ƒ 7} q¬ W| d
 7} x1 t
 | ƒ D]# } | d t d | d	 | ƒ 7} qê W| d 7} x t
 | ƒ D] } | d 7} q(Wx t
 | ƒ D] } | d 7} qIW| d 7} | t ƒ  S(   NR   i    R†   s\   #pragma omp parallel for private(r_st, r_end, r_idx, i_idx, o_idx, maximum) schedule(static)R‡   s  
        int z_typenum = PyArray_ObjectType((PyObject*)%(maxout)s, 0);
        int z[%(nd)s]; // shape of the output
        int r[%(nd)s]; // shape of the padded_input
        int ws[%(nd)s];
        int st[%(nd)s];
        int pd[%(nd)s];
        if(PyArray_DIM(%(ws)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "ws must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(stride)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "stride must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(pad)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "pad must be a vector of size %(nd)s");
            %(fail)s;
        }
        for (int i=0; i<%(nd)s; i++)
        {
            ws[i] = *((npy_intp*)PyArray_GETPTR1(%(ws)s, i));
            st[i] = *((npy_intp*)PyArray_GETPTR1(%(stride)s, i));
            pd[i] = *((npy_intp*)PyArray_GETPTR1(%(pad)s, i));
            z[i] = PyArray_DIMS(%(maxout)s)[%(non_pool_ndim)s + i];
            r[i] = PyArray_DIMS(%(x)s)[%(non_pool_ndim)s + i] + 2 * pd[i];
        }
        // allocating memory for output, if necessary
        int mem_nec;
        mem_nec = 0;
        if ((!%(z)s) || !PyArray_ISCONTIGUOUS(%(z)s)
            || *PyArray_DIMS(%(z)s)!=%(total_ndim)s)
        {
            mem_nec = 1;
        }
        if (!mem_nec)
        {
            for (int i=0; i<%(total_ndim)s; i++)
            {
                if (PyArray_DIMS(%(z)s)[i] != PyArray_DIMS(%(maxout)s)[i])
                {
                    mem_nec = 1;
                    break;
                }
            }
        }
        if (mem_nec)
        {
          Py_XDECREF(%(z)s);
          %(z)s = (PyArrayObject*) PyArray_ZEROS(%(total_ndim)s, PyArray_DIMS(%(maxout)s), z_typenum,0);
        }
        else {
          PyArray_FILLWBYTE(%(z)s, 0);
        }
        dtype_%(maxout)s maximum; // temp var for maximum value in a region
        // will be used to hold start and end index of a region
        int r_st[%(nd)s];
        int r_end[%(nd)s];
        // index for iterating over the pooling regions
        int r_idx[%(nd)s];
        // placeholder for PyArray indexing (output)
        npy_intp o_idx[%(total_ndim)s];
        // placeholder for PyArray indexing (input)
        npy_intp i_idx[%(total_ndim)s];
        // loop over non-pooling dimensions
        int non_pooling_prod;
        non_pooling_prod = 1;
        for (int i=0; i<%(non_pool_ndim)s; i++)
        {
            non_pooling_prod *= PyArray_DIMS(%(x)s)[i];
        }
        %(omp_parallel)s
        // first loop over non-pooling dimensions
        for (int t=0; t<non_pooling_prod; t++)
        {
            // compute the non-pooling index in each dimension
            if (%(non_pool_ndim)s!=0)
            {
                o_idx[0] = t;
                i_idx[0] = t;
                for (int i=1; i<%(non_pool_ndim)s; i++)
                {
                    o_idx[i] = o_idx[i - 1] / PyArray_DIMS(%(x)s)[i - 1];
                    o_idx[i - 1] = o_idx[i - 1] %% PyArray_DIMS(%(x)s)[i - 1];
                    i_idx[i] = o_idx[i];
                    i_idx[i - 1] = o_idx[i - 1];
                }
            }

            // then loop over each region in each pooling dimension
        sÚ  
                for (r_idx[%(i)s]=0; r_idx[%(i)s] < z[%(i)s]; r_idx[%(i)s]++) {
                  r_st[%(i)s] = r_idx[%(i)s] * st[%(i)s];
                  r_end[%(i)s] = r_st[%(i)s] + ws[%(i)s];
                  // skip the padding
                  r_st[%(i)s] = r_st[%(i)s] < pd[%(i)s] ? pd[%(i)s] : r_st[%(i)s];
                  r_end[%(i)s] = r_end[%(i)s] > (r[%(i)s] - pd[%(i)s]) ? r[%(i)s] - pd[%(i)s] : r_end[%(i)s];
                  // from padded_img space to img space
                  r_st[%(i)s] -= pd[%(i)s];
                  r_end[%(i)s] -= pd[%(i)s];
                  // use the index to find the correct position in the output
                  o_idx[%(non_pool_ndim)s + %(i)s] = r_idx[%(i)s];
            R(   Rˆ   sä  
                  dtype_%(z)s * z;
                  if (%(total_ndim)s == 4)
                  {
                    // the maximum value
                    maximum = ((dtype_%(maxout)s*)(PyArray_GETPTR4(%(maxout)s,o_idx[0],o_idx[1],o_idx[2],o_idx[3])))[0];
                    // z at this position
                    z = ((dtype_%(z)s*)(PyArray_GETPTR4(%(z)s,o_idx[0],o_idx[1],o_idx[2],o_idx[3])));
                  }
                  else
                  {
                    // the maximum value
                    maximum = ((dtype_%(maxout)s*)(PyArray_GetPtr(%(maxout)s,o_idx)))[0];
                    // z at this position
                    z = ((dtype_%(z)s*)(PyArray_GetPtr(%(z)s,o_idx)));
                  }
        sù   
                  // go through the pooled region in the unpadded input
                  for(int m%(i)s=r_st[%(i)s]; m%(i)s<r_end[%(i)s]; m%(i)s++)
                  {
                    i_idx[%(non_pool_ndim)s + %(i)s] = m%(i)s;
                sÊ  
                    dtype_%(x)s a;
                    dtype_%(ggx)s * ggx;
                    if (%(total_ndim)s == 4)
                    {
                      a = ((dtype_%(x)s*)(PyArray_GETPTR4(%(x)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])))[0];
                      ggx = ((dtype_%(ggx)s*)(PyArray_GETPTR4(%(ggx)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])));
                    }
                    else
                    {
                      a = ((dtype_%(x)s*)(PyArray_GetPtr(%(x)s,i_idx)))[0];
                      ggx = ((dtype_%(ggx)s*)(PyArray_GetPtr(%(ggx)s,i_idx)));
                    }
                    if (a == maximum){
                      z[0] += ggx[0];
                    }
        s=   
                  } // for loop over region
                s<   
              } // loop over pooling dimension
            s=   
          } // for loop over non-pooling dimensions
        (   R   R+   R   RŠ   R‹   R   RE   RŒ   R   R>   R   R   R   (   RD   RJ   R   Rf   R2   R‘   RW   R}   R¨   R   R   R   R[   RX   R’   Rˆ   R†   R   R“   R”   R(   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR•   7  s@    		

		^c         C` s   d d |  j  f S(   Ni    i   (   R>   (   RD   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR–   ë  s    (   s   ignore_borders   modes   ndimN(   R—   R˜   Rš   R   RC   RZ   Ru   Rx   R~   R   R•   R–   (    (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR€   Å  s   "	4				´t
   MaxPoolRopc           B` se   e  Z d  Z d d d f Z e d d e d „ Z e e d „ Z d „  Z d	 „  Z	 d
 „  Z
 d „  Z RS(   sÏ  
    Implements the R-operator for the downsample operation.

    Parameters
    ----------
    ws : list or tuple of N ints
        Downsample factor over rows, columns etc.
        ws indicates the size of the pooling region.
    ignore_border : bool
        If ws doesn't divide imgshape, do we include an extra row/col/slice
        of partial downsampling (False) or ignore it (True).
    stride : list or tuple of N ints or None
        Stride size, which is the number of shifts over rows/cols/slices to get the
        next pool region. If stride is None, it is considered equal to ws
        (no overlap on pooling regions).
    pad : tuple of N ints or None
        For each downsampling dimension, this specifies the number of zeros to
        add as padding on both sides. For 2D and (pad_h, pad_w), pad_h specifies the
        size of the top and bottom margins, pad_w specifies the size of the left and
        right margins. No padding is added if pad is None.
    mode : {'max', 'sum', 'average_inc_pad', 'average_exc_pad'}
        ('average_inc_pad' excludes the padding from the count,
        'average_exc_pad' include it)
    ndim : int
        The number of pooling dimensions N.
        The default is 2.
    R   R   R   R   i   c         C` sJ   t  t |  ƒ j d | ƒ | |  _ | |  _ | |  _ | d k sF t ‚ d  S(   NR>   R   (   RB   R³   RC   R   R   R   R4   (   RD   R   R   R   R>   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRC     s
    			c   	      ` s'  t  j | ƒ } t  j | ƒ } |  j } | d  k r< ˆ } n  ˆ  d  k rU d
 | ‰  n t ˆ  t t f ƒ rä t ˆ  ƒ d k r• |  j r• t	 d ƒ ‚ n  t ˆ t t f ƒ rä t
 ‡  ‡ f d †  t | ƒ Dƒ ƒ rá t	 d ƒ ‚ qá qä n  t  j ˆ ƒ ‰ t  j | ƒ } t  j ˆ  ƒ ‰  ˆ j d k s&t ‚ | j d k s;t ‚ ˆ  j d k sPt ‚ | j j | k  rnt ƒ  ‚ n  ˆ j j d ƒ st d ƒ ‚ n  | j j d ƒ s°t d ƒ ‚ n  ˆ  j j d ƒ sÑt d	 ƒ ‚ n  | j |  t f | } t  j | j | ƒ } t j |  | | ˆ | ˆ  g | ƒ  g ƒ S(   Ni    s*   padding works only with ignore_border=Truec         3` s#   |  ] } ˆ  | ˆ | k Vq d  S(   N(    (   R'   R(   (   R   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>#  s    s$   padding must be smaller than stridesi   RŒ   s(   Pool downsample parameters must be ints.s   Stride parameters must be ints.s    Padding parameters must be ints.(   i    (   R   RO   R   R   R*   R8   R9   R   R   R   RP   RQ   R4   RR   R6   RS   t
   startswithRU   R   RV   R   R   (	   RD   RW   t
   eval_pointR   R   R   RX   RY   R2   (    (   R   R   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRZ     s@    		%c         ` s"  | \ ‰ } } } ‰ | \ } |  j  ‰ | j | j k oU ˆ j k oU ˆ f k n s` t ‚ t ˆ j ƒ ˆ k  r t d j ˆ ƒ ƒ ‚ n  t j ˆ j | |  j | ˆ ˆ ƒ } |  j sÞ t	 d „  | ˆ Dƒ ƒ sÞ t ‚ n  | d d  k s| d j | k r t j | d ˆ j ƒ| d <n  | d }	 |	 j ˆ }
 t ‡ ‡ ‡ f d †  t ˆ ƒ Dƒ ƒ ‰  |  j d k } t ˆ ƒ d k rZt j ˆ j ˆ  ˆ  d ˆ j ƒ} ˆ | t d  ƒ f t ˆ j ƒ ˆ t ‡  ‡ f d †  t ˆ ƒ Dƒ ƒ <t j | j ˆ  ˆ  d | j ƒ} | | t d  ƒ f t | j ƒ ˆ t ‡  ‡ f d †  t ˆ ƒ Dƒ ƒ <n ˆ } | } g  t ˆ ƒ D] } g  ^ qs} x² t ˆ ƒ D]¤ } x› t |
 | ƒ D]‰ } | | | } t j | | | ˆ  | ƒ } | st j | ˆ | ƒ } t j | ˆ  | ˆ | ƒ } n  | | j t | | ƒ ƒ q©Wq’Wxá t j ˆ j ˆ  Œ  D]È } |	 | } | | } | | } x¡ t j |
 Œ  D] } | g  t ˆ ƒ D] } | | | | ^ qœ} | g  t ˆ ƒ D] } | | | | ^ qË} t j t j | ƒ | j ƒ } | | | | <q†WqRWd  S(	   Ns.   Pool requires input with {} or more dimensionsc         s` s   |  ] } | d  k Vq d S(   i    N(    (   R'   R[   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>C  s    i    RS   c         3` s-   |  ]# } ˆ j  ˆ  | d  ˆ | Vq d S(   i   N(   R\   (   R'   R(   (   RX   R   RW   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>I  s    R?   c         3` s.   |  ]$ } t  ˆ | ˆ  | ˆ | ƒ Vq d  S(   N(   R]   (   R'   R(   (   R^   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>P  s    c         3` s.   |  ]$ } t  ˆ | ˆ  | ˆ | ƒ Vq d  S(   N(   R]   (   R'   R(   (   R^   R   (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pys	   <genexpr>S  s    (   R   R\   R4   R5   R   R7   R
   R<   R   R_   R   R-   R`   RS   R8   R   R   R   Ra   R]   Rc   Rd   RG   Re   t   unravel_indext   argmax(   RD   RJ   Rf   R2   t   exR   R   R[   Rg   Rh   Ri   Rj   Rk   t   eyR(   Rm   Rn   Ro   Rp   Rq   Rr   Rs   t   eykRt   t   ykslicet   eykslicet   idx(    (   R^   RX   R   RW   s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyRu   9  sR    		9$	$#
($G$J!"


//c         C` s&   d g } | t  t |  ƒ j ƒ  7} | S(   Ns   <algorithm>(   RB   R³   R„   (   RD   R…   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR„   r  s    	c      
   C` s½  |  j  d k r$ t j j j ƒ  ‚ n  | \ } } } }	 }
 | \ } |  j } | j d j } | | } | d } t |  j ƒ } |  j	 r d } n d } d } x7 t
 | ƒ D]) } | d t d | d	 | d
 | ƒ 7} q© W| d 7} x1 t
 | ƒ D]# } | d t d | d
 | ƒ 7} qí W| d 7} x1 t
 | ƒ D]# } | d t d | d
 | ƒ 7} q+W| d 7} x t
 | ƒ D] } | d 7} qiW| d 7} x t
 | ƒ D] } | d 7} q”W| d 7} | t ƒ  S(   NR   i    R†   sn   #pragma omp parallel for private(r_st, r_end, r_idx, i_idx, o_idx, collector, eval_collector) schedule(static)R‡   sü  
        int typenum = PyArray_ObjectType((PyObject*)%(x)s, 0);
        if(PyArray_NDIM(%(x)s)!=%(total_ndim)s)
        {
            PyErr_SetString(PyExc_ValueError, "x must be a %(total_ndim)sD ndarray");
            %(fail)s;
        }
        if(PyArray_NDIM(%(ex)s)!=%(total_ndim)s)
        {
            PyErr_SetString(PyExc_ValueError, "eval_point must be a %(total_ndim)sD ndarray");
            %(fail)s;
        }
        if(PyArray_DIM(%(ws)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "ws must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(stride)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "stride must be a vector of size %(nd)s");
            %(fail)s;
        }
        if(PyArray_DIM(%(pad)s, 0)!=%(nd)s)
        {
            PyErr_SetString(PyExc_ValueError, "pad must be a vector of size %(nd)s");
            %(fail)s;
        }
        int z[%(nd)s]; // shape of the output
        int r[%(nd)s]; // shape of the padded_input
        int ws[%(nd)s];
        int st[%(nd)s];
        int pd[%(nd)s];
        int nonzero_padding;
        nonzero_padding = 0;
        for (int i=0; i<%(nd)s; i++)
        {
            ws[i] = *((npy_intp*)PyArray_GETPTR1(%(ws)s, i));
            st[i] = *((npy_intp*)PyArray_GETPTR1(%(stride)s, i));
            pd[i] = *((npy_intp*)PyArray_GETPTR1(%(pad)s, i));
            r[i] = PyArray_DIMS(%(x)s)[%(non_pool_ndim)s + i] + 2 * pd[i];
            if (pd[i]>0)
                nonzero_padding = 1;
        }
        if (!%(ignore_border)s && nonzero_padding)
        {
            PyErr_SetString(PyExc_ValueError,
              "padding must be zero when ignore border is False");
            %(fail)s;
        }
        if (%(ignore_border)s)
        {
            for (int i=0; i<%(nd)s; i++)
            {
                // '/' in C is different from '/' in python
                if (r[i] - ws[i] < 0)
                {
                  z[i] = 0;
                }
                else
                {
                  z[i] = (r[i] - ws[i]) / st[i] + 1;
                }
            }
        }
        else
        {
            for (int i=0; i<%(nd)s; i++)
            {
                // decide how many rows/cols the output has
                if (st[i] >= ws[i])
                {
                    z[i] = (r[i] - 1) / st[i] + 1;
                }
                else
                {
                    z[i] = std::max(0, (r[i] - 1 - ws[i] + st[i]) / st[i]) + 1;
                }
                assert(z[i] > 0);
            }
        }
        // memory allocation of z if necessary
        int mem_nec;
        mem_nec = 0;
        if ((!%(z)s) || *PyArray_DIMS(%(z)s)!=%(total_ndim)s)
        {
            mem_nec = 1;
        }
        if (!mem_nec)
        {
            for (int i=0; i<%(non_pool_ndim)s; i++)
            {
                if (PyArray_DIMS(%(z)s)[i] != PyArray_DIMS(%(x)s)[i])
                {
                    mem_nec = 1;
                    break;
                }
            }
        }
        if (!mem_nec)
        {
            for (int i=0; i<%(nd)s; i++)
            {
                if (PyArray_DIMS(%(z)s)[%(non_pool_ndim)s + i] != z[i])
                {
                    mem_nec = 1;
                    break;
                }
            }
        }
        if (mem_nec)
        {
          if (%(z)s) Py_XDECREF(%(z)s);
          npy_intp dims[%(total_ndim)s];
          for (int i=0; i<%(non_pool_ndim)s; i++)
          {
              dims[i] = PyArray_DIMS(%(x)s)[i];
          }
          for (int i=0; i<%(nd)s; i++)
          {
              dims[%(non_pool_ndim)s + i] = z[i];
          }
          //TODO: zeros not necessary
          %(z)s = (PyArrayObject*) PyArray_ZEROS(%(total_ndim)s, dims, typenum,0);
        }
        // initialize temp var for the value in a region
        dtype_%(x)s collector;
        dtype_%(ex)s eval_collector;
        int z_prod;
        // do not run if any z[i] is zero
        z_prod = 1;
        for (int i=0; i<%(nd)s; i++)
        {
            z_prod *= z[i];
        }
        if (z_prod)
        {
            // will be used to hold start and end index of a region
            int r_st[%(nd)s];
            int r_end[%(nd)s];
            // index for iterating over the pooling regions
            int r_idx[%(nd)s];
            // placeholder for PyArray indexing (output)
            npy_intp o_idx[%(total_ndim)s];
            // placeholder for PyArray indexing (input)
            npy_intp i_idx[%(total_ndim)s];
            // loop over non-pooling dimensions
            int non_pooling_prod = 1;
            for (int i=0; i<%(non_pool_ndim)s; i++)
            {
                non_pooling_prod *= PyArray_DIMS(%(x)s)[i];
            }
            %(omp_parallel)s
            // first loop over non-pooling dimensions
            for (int t=0; t<non_pooling_prod; t++)
            {
                // compute the non-pooling index in each dimension
                if (%(non_pool_ndim)s!=0)
                {
                    o_idx[0] = t;
                    i_idx[0] = t;
                    for (int i=1; i<%(non_pool_ndim)s; i++)
                    {
                        o_idx[i] = o_idx[i - 1] / PyArray_DIMS(%(x)s)[i - 1];
                        o_idx[i - 1] = o_idx[i - 1] %% PyArray_DIMS(%(x)s)[i - 1];
                        i_idx[i] = o_idx[i];
                        i_idx[i - 1] = o_idx[i - 1];
                    }
                }

                // then loop over each region in each pooling dimension
        sÎ  
                for (r_idx[%(i)s]=0; r_idx[%(i)s] < z[%(i)s]; r_idx[%(i)s]++) {
                  r_st[%(i)s] = r_idx[%(i)s] * st[%(i)s];
                  r_end[%(i)s] = r_st[%(i)s] + ws[%(i)s];
                  // skip the padding
                  r_st[%(i)s] = r_st[%(i)s] < pd[%(i)s] ? pd[%(i)s] : r_st[%(i)s];
                  r_end[%(i)s] = r_end[%(i)s] > (r[%(i)s] - pd[%(i)s]) ? r[%(i)s] - pd[%(i)s] : r_end[%(i)s];
                  // from padded_img space to img space
                  r_st[%(i)s] -= pd[%(i)s];
                  r_end[%(i)s] -= pd[%(i)s];
                  // handle the case where no padding, ignore border is True
                  if (%(ignore_border)s)
                  {
                    r_end[%(i)s] = r_end[%(i)s] > r[%(i)s] ? r[%(i)s] : r_end[%(i)s];
                  }
                  // use the index to find the correct position in the output
                  o_idx[%(non_pool_ndim)s + %(i)s] = r_idx[%(i)s];
            R(   R   Rˆ   si  
                  // get a pointer to the correct position in the output
                  dtype_%(z)s * z;
                  if (%(total_ndim)s == 4)
                    z = ((dtype_%(z)s*)(PyArray_GETPTR4(%(z)s, o_idx[0], o_idx[1], o_idx[2], o_idx[3])));
                  else
                    z = ((dtype_%(z)s*)(PyArray_GetPtr(%(z)s, o_idx)));
        sƒ   
              // set the first index of dimension %(i)s
              i_idx[%(non_pool_ndim)s + %(i)s] = r_st[%(i)s];
            s&  
              // use the first element as the initial value of collector
              if (%(total_ndim)s == 4) {
                collector = ((dtype_%(x)s*)(PyArray_GETPTR4(%(x)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])))[0];
                eval_collector = ((dtype_%(ex)s*)(PyArray_GETPTR4(%(ex)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])))[0];
              } else {
                collector = ((dtype_%(x)s*)(PyArray_GetPtr(%(x)s,i_idx)))[0];
                eval_collector = ((dtype_%(ex)s*)(PyArray_GetPtr(%(ex)s,i_idx)))[0];
              }
        så   
              // go through the pooled region in the unpadded input
              for(int m%(i)s=r_st[%(i)s]; m%(i)s<r_end[%(i)s]; m%(i)s++)
              {
                i_idx[%(non_pool_ndim)s + %(i)s] = m%(i)s;
            s´  
                // update maximum
                dtype_%(x)s a;
                dtype_%(ex)s ea;
                if (%(total_ndim)s == 4) {
                  a = ((dtype_%(x)s*)(PyArray_GETPTR4(%(x)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])))[0];
                  ea = ((dtype_%(ex)s*)(PyArray_GETPTR4(%(ex)s,i_idx[0],i_idx[1],i_idx[2],i_idx[3])))[0];
                }
                else {
                  a = ((dtype_%(x)s*)(PyArray_GetPtr(%(x)s,i_idx)))[0];
                  ea = ((dtype_%(ex)s*)(PyArray_GetPtr(%(ex)s,i_idx)))[0];
                }
                if (a > collector) {
                  collector = a;
                  eval_collector = ea;
                }
        s5   
              } // for loop over region
            s.   
              z[0] = eval_collector;
        s:   
            } // loop over pooling dimension
            sT   
          } // for loop over non-pooling dimensions
        } // if z_prod
        (   R   R+   R   RŠ   R‹   R   RE   RŒ   R   R>   R   R   R   (   RD   RJ   R   Rf   R2   R‘   RW   R¸   R   R   R   R[   RX   R’   Rˆ   R†   R   R“   R”   R(   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR•   w  sN    		

		«$	c         C` s   d |  j  f S(   Ni    (   R>   (   RD   (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR–   ˆ	  s    (   R—   R˜   R™   Rš   R   R   RC   RZ   Ru   R„   R•   R–   (    (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyR³   ï  s   $	9		ÿ (   R™   t
   __future__R    R   R   R   Rž   R-   t	   six.movesR   t   six.moves.builtinst   movesRc   R+   R   R   R   R   R   t   theano.gradientR	   R   R   R$   R%   R
   Rœ   R   Ry   R€   R³   (    (    (    s9   /tmp/pip-build-X4mzal/theano/theano/tensor/signal/pool.pyt   <module>   s2   (	klÿ ÿ Ž¯ÿ <ÿ Nÿ +