
Xc           @` sl  d  Z  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 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 m Z d d	 l m Z m Z d d
 l m Z d d l m Z d d l m Z d d l m Z d d l m Z m Z d d l m Z e j  d  Z! e" a# e" d  Z$ e" a% d   Z& d f  d     YZ' d   Z( d   Z) d   Z* d   Z+ d   Z, d   Z- d   Z. d   Z/ d   Z0 d   Z1 d   Z2 d    Z3 d!   Z4 d" e j5 f d#     YZ6 d$ e7 f d%     YZ8 d& e j9 f d'     YZ: d(   Z; d) e j5 f d*     YZ< d+ e7 f d,     YZ= d S(-   s4   
Defines Linkers that deal with C implementations.

i    (   t   absolute_importt   print_functiont   division(   t   copyN(   t   config(   t   PY3(   t   izip(   t   string_typest   reraise(   t   StringIOt   xrange(   t   graph(   t   link(   t   utils(   t   cmodule(   t   get_lockt   release_lock(   t	   CallCaches   theano.gof.ccc         C` s   t  j t j d |  S(   s   

    Parameters
    ----------
    init_args
        If not None, the (k, v) pairs in this dictionary will be forwarded to
        the ModuleCache constructor as keyword arguments.

    t	   init_args(   R   t   get_module_cacheR   t
   compiledir(   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR   &   s    
c           C` s1   t  d  k r- t t j j t j d   a  n  t  S(   Nt   persistent_cache(   t   _persistent_module_cachet   NoneR   t   ost   patht   joinR   R   (    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   get_persistent_module_cache6   s    t	   CodeBlockc           B` s   e  Z d  Z d   Z RS(   s%  
    Represents a computation unit composed of declare, behavior, and cleanup.

    The constructor initializes a L{CodeBlock} with templatized declare,
    behavior and cleanup. The sub parameter will be used in the other
    arguments' templates. sub should contain a key called 'id' that maps to an
    identifier for this block. The identifier will be used to determine the
    failure code and a label to jump to. It should also contain a key called
    'failure_var' that contains the name of the variable that contains the error
    code.

    Parameters
    ----------
    declare
        C code that declares variables for use by the computation.
    behavior
        C code that performs the computation.
    cleanup
        C code that cleans up things allocated or incref-ed in behavior.

    c         C` s/   | |  _  | |  _ d | | d | |  _ d  S(   Ns   __label_%(id)i:
s   
double __DUMMY_%(id)i;
(   t   declaret   behaviort   cleanup(   t   selfR   R   R   t   sub(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   __init__U   s    		(   t   __name__t
   __module__t   __doc__R"   (    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR   >   s   c         C` s   d |  S(   s   
    Code contained in sub['fail'], usually substituted for %(fail)s.

    It sets information about current error, then goto the code
    actually handling the failure, which is defined in struct_gen().

    s  {
        %(failure_var)s = %(id)s;
        if (!PyErr_Occurred()) {
            PyErr_SetString(PyExc_RuntimeError,
                "Unexpected error in an Op's C code. "
                "No Python exception was set.");
            }
        goto __label_%(id)i;}(    (   R!   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   failure_codea   s    c         C` s   d |  S(   s   
    Code for failure in the struct init.

    Parameters:
    ----------
    sub
      Dictionary used to template the struct.
      * failure_var -> must contain a variable name to use for
      the failure code.
    s   {
        if (!PyErr_Occurred()) {
            PyErr_SetString(PyExc_RuntimeError,
                "Unexpected error in an Op's C code. "
                "No Python exception was set.");
            }
        return %(id)d;
}(    (   R!   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   failure_code_inits   s    c         C` s^   d } d } d } x= |  D]5 } | | j  7} | d | j } d | j | } q W| | | S(   s$  
    From a list of L{CodeBlock} instances, returns a string
    that executes them all in sequence.

    Eg for C{(decl1, task1,
    cleanup1)} and C{(decl2, task2, cleanup2)} the returned string
    will be of the form:

        decl1
        decl2
        {
         task1
         {
          task2
          cleanup2
         }
         cleanup1
        }

    Parameters:
    ----------
    blocks
         List of CodeBlock instances such that
         * declarations, behavior and cleanup are in the run()
         method of the struct
    t    s   
{
%ss   %s
}
(   R   R   R   (   t   blockst   declt   headt   tailt   block(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   code_gen   s    c         C` sg  d } d } d } d } x9 | D]1 } | | j  7} | d | j } | | j 7} q Wt |  }	 d j g  |  D] }
 d |
 ^ qm  } d j g  |  D] }
 d |
 |
 f ^ q  } d j g  |  D] }
 d |
 ^ q  } d j g  |  D] }
 d |
 ^ q  } d j |   } d j g  |  D] }
 d	 |
 ^ q } d
 | } t |  } | j t    d | } | S(   s  
    Generates a struct conforming to the following specifications:

    Parameters
    ----------
     args
        All of the PyObject* type, stored in the struct
        they represent the storage and must be length 1 python lists.
     struct_builders
        List of L{CodeBlock} instances such that
        * declarations are in the struct
        * behavior is in the constructor
        * cleanup is in the destructor
     blocks
        List of CodeBlock instances such that
        * declarations, behavior and cleanup are in the run()
        method of the struct
     sub
        Dictionary used to template the struct.
        * failure_var -> must contain a variable name to use for
        the failure code.

    Returns
    -------
    object
        In a nutshell, this returns code for a struct that represents
        a function with state. The state's initialization and destruction
        are handled by struct_builders and the actual behavior of the
        function is handled by blocks.

    R(   s   
%ss   
s   PyObject* %s;s   this->%s = %s;s   Py_XINCREF(%s);s   Py_XDECREF(this->%s);s   , s   PyObject* %ssk  
        if (%(failure_var)s) {
            // When there is a failure, this code puts the exception
            // in __ERROR.
            PyObject* err_type = NULL;
            PyObject* err_msg = NULL;
            PyObject* err_traceback = NULL;
            PyErr_Fetch(&err_type, &err_msg, &err_traceback);
            if (!err_type) {err_type = Py_None;Py_INCREF(Py_None);}
            if (!err_msg) {err_msg = Py_None; Py_INCREF(Py_None);}
            if (!err_traceback) {err_traceback = Py_None; Py_INCREF(Py_None);}
            PyObject* old_err_type = PyList_GET_ITEM(__ERROR, 0);
            PyObject* old_err_msg = PyList_GET_ITEM(__ERROR, 1);
            PyObject* old_err_traceback = PyList_GET_ITEM(__ERROR, 2);
            PyList_SET_ITEM(__ERROR, 0, err_type);
            PyList_SET_ITEM(__ERROR, 1, err_msg);
            PyList_SET_ITEM(__ERROR, 2, err_traceback);
            {Py_XDECREF(old_err_type);}
            {Py_XDECREF(old_err_msg);}
            {Py_XDECREF(old_err_traceback);}
        }
        // The failure code is returned to index what code block failed.
        return %(failure_var)s;
        s}  
    namespace {
    struct %(name)s {
        PyObject* __ERROR;

        %(storage_decl)s
        %(struct_decl)s

        %(name)s() {
            // This is only somewhat safe because we:
            //  1) Are not a virtual class
            //  2) Do not use any virtual classes in the members
            //  3) Deal with mostly POD and pointers

            // If this changes, we would have to revise this, but for
            // now I am tired of chasing segfaults because
            // initialization code had an error and some pointer has
            // a junk value.
            memset(this, 0, sizeof(*this));
        }
        ~%(name)s(void) {
            cleanup();
        }

        int init(PyObject* __ERROR, %(args_decl)s) {
            %(storage_incref)s
            %(storage_set)s
            %(struct_init_head)s
            this->__ERROR = __ERROR;
            return 0;
        }
        void cleanup(void) {
            %(struct_cleanup)s
            %(storage_decref)s
        }
        int run(void) {
            int %(failure_var)s = 0;
            %(behavior)s
            %(do_return)s
        }
    };
    }
    (   R   R   R   R.   R   t   dictt   updatet   locals(   t   argst   struct_buildersR)   R!   t   struct_declt   struct_init_headt   struct_init_tailt   struct_cleanupR-   R   t   argt   storage_declt   storage_sett   storage_increft   storage_decreft
   args_namest	   args_declt	   do_returnt   struct_code(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt
   struct_gen   s(     &,&&&
/
c         C` s   d S(   s   
    WRITEME

    R(   (    (   t   rt   nameR!   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   get_nothing@  s    c         C` s   t  g  |  j D]3 \ } } t | t  s t | j d t j  ^ q  sm |  j r t |  j j d t j  r |  j	 j
 | | t  } n |  j	 j
 | | t  } d t   } | | S(   s:   
    Wrapper around c_declare that declares py_name.

    t   check_inputs    
    PyObject* py_%(name)s;
    (   t   anyt   clientst
   isinstanceR   t   getattrt   opR   RE   t   ownert   typet	   c_declaret   Truet   FalseR1   (   RB   RC   R!   t   ct   _RM   t   pre(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   get_c_declareH  s    
0	c         C` s$   d t    } | |  j j | |  S(   sE   
    Wrapper around c_init that initializes py_name to Py_None.

    s?   
    py_%(name)s = Py_None;
    {Py_XINCREF(py_%(name)s);}
    (   R1   RL   t   c_init(   RB   RC   R!   RR   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt
   get_c_init`  s    
c         C` s*  t  g  |  j D]3 \ } } t | t  s t | j d t j  ^ q  r t  g  |  j D]0 \ } } t | t  sV t | j d t  ^ qV  r |  j	 j
 | | t  } qy" |  j	 j
 | | t d t } Wqt k
 r } |  j	 j
 | | t  } qXn |  j	 j
 | | t  } d t   } | | S(   sJ   
    Wrapper around c_extract that initializes py_name from storage.

    RE   t   check_broadcasts\   
    py_%(name)s = PyList_GET_ITEM(storage_%(name)s, 0);
    {Py_XINCREF(py_%(name)s);}
    (   RF   RG   RH   R   RI   RJ   R   RE   RN   RL   t	   c_extractRO   t	   TypeErrorR1   (   RB   RC   R!   RP   RQ   RW   t   eRR   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   get_c_extractl  s     0-	c         C` s   t  |  j j d t j  } t  |  j j d t  rN |  j j | | |  } nP y" |  j j | | | d t } Wn+ t	 k
 r } |  j j | | |  } n Xd t
   } | | S(   sN   
    Wrapper around c_extract_out that initializes py_name from storage.

    RE   RV   s\   
    py_%(name)s = PyList_GET_ITEM(storage_%(name)s, 0);
    {Py_XINCREF(py_%(name)s);}
    (   RI   RK   RJ   R   RE   RN   RL   t   c_extract_outRO   RX   R1   (   RB   RC   R!   RE   RW   RY   RR   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   get_c_extract_out  s    c         C` s$   d t    } |  j j | |  | S(   s9   
    Wrapper around c_cleanup that decrefs py_name.

    s$   
    {Py_XDECREF(py_%(name)s);}
    (   R1   RL   t	   c_cleanup(   RB   RC   R!   t   post(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   get_c_cleanup  s    c         C` s)   d t  d |  j j | |  d | |  S(   sA   
    Wrapper around c_sync that syncs py_name with storage.

    s   
    if (!%(failure_var)s) {
      %(sync)s
      PyObject* old = PyList_GET_ITEM(storage_%(name)s, 0);
      {Py_XINCREF(py_%(name)s);}
      PyList_SET_ITEM(storage_%(name)s, 0, py_%(name)s);
      {Py_XDECREF(old);}
    }
    t   syncRC   (   R/   RL   t   c_sync(   RB   RC   R!   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt
   get_c_sync  s    c         C` sV   t  |  t t f  rF d } x$ |  D] } | | | | |  7} q" W| S|  | | |  S(   s#  
    Apply the list of policies to name.r,sub

    Parameters
    ----------
    policy
        List of functions that map a L{Variable} to a string,
        or a single such function.
    r: L{Variable}

    Returns
    -------
    object
        C{policy[0](r) + policy[1](r) + ...}.

    R(   (   RH   t   listt   tuple(   t   policyRB   RC   R!   t   rett
   sub_policy(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   apply_policy  s    c   	      C` s  d | } |  | k r# | | |  <n  t  |  } | | d <t |  | d <d | | d <d | | d <t g  | d D] } t | |  | |  ^ qs | g   } | d	 | d <t |  | d <d | | d <d | | d <t g  | d	 D] } t | |  | |  ^ q | g   } | | f S(
   sE  
    Update "sub" dict and create two codeblocks with different failure modes

    Parameters
    ----------
    variable : a Variable
    policies : a pair of tuples
        (declare_policy, behavior_policy, cleanup_policy) -- at construction.
        (declare_policy, behavior_policy, cleanup_policy)) -- at execution.
        The first list will produce an element of the 'struct_builders' argument
        in struct_gen. The second list will produce an element of the 'blocks'
        argument in struct_gen.
    id
        The id assigned to this variable's task in the computation.
    symbol_table
        A dict that maps variables to variable names. It is not read by this
        function but a variable name for the variable is computed and added to
        the table.
    sub
        Dictionary for use by L{CodeBlock}.

    s   V%it   idt   fails   py_%st   py_ptrs
   storage_%st   stor_ptri    i   (   R/   R'   R   Rh   R&   (	   t   variablet   policiesRi   t   symbol_tableR!   RC   Re   t   struct_builderR-   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   struct_variable_codeblocks  s"    

33t   CLinkerc           B` s%  e  Z d  Z e d  Z e e d  Z d   Z d   Z d   Z d   Z	 d   Z
 d   Z d	   Z d
   Z d   Z d   Z e e e e d  Z d   Z e e e e d  Z d   Z e e e e e d  Z e e e e e d  Z d   Z e d  Z d   Z e e d  Z d   Z RS(   sw  
    Creates C code for an fgraph, compiles it and returns callables
    through make_thunk and make_function that make use of the compiled
    code.

    no_recycling can contain a list of Variables that belong to the fgraph.
    If a Variable is in no_recycling, CLinker will clear the output storage
    associated to it during the computation (to avoid reusing it).

    c         C` s   d  |  _ | r | |  _ n  d  S(   N(   R   t   fgrapht   schedule(   R    Rt   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR"   "  s    	c         C` su   | d k r g  } n  |  j d k	 rU |  j | k	 rU t |   |  j  j | | |  S| |  _ |  j   | |  _ |  S(   s/   
        Associate linker with fgraph

        N(   R   Rs   RL   Rt   t   acceptt   fetch_variablest   no_recycling(   R    Rs   Rw   t   profile(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyRu   '  s    		
	c         ` s9    j  } | j   _ | j   _   j |    _ g    j D] } t | j  s= | ^ q=   _   j t j   j   j  7_ t	     _
 x   j D] } | j   } | t j k	 r |   j
 k r  j
 | } | j | j k s t  | j j | d f  qMt j | j |  } | d f g | _ |   j
 | <  j j |  q q Wt   f d     j D    _ g    _ xz   j D]o } t | t j  ry7 | j j | j    j j |    j j |  Wqt j t f k
 rqXqqWt t   j  j   j  j   j  j   j     _ d S(   sf   
        Fills the inputs, outputs, variables, orphans, temps and node_order
        fields.

        t   paramsc         3` s6   |  ], } t  | t j  r |   j k r | Vq d  S(   N(   RH   R   t   Constantt   inputs(   t   .0RB   (   R    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pys	   <genexpr>]  s    N(   Rs   R{   t   outputsRt   t
   node_ordert   lenRG   t	   variablesR   R/   t   node_paramst
   run_paramst   NoParamsRL   t   params_typet   AssertionErrort   appendRz   Rc   t   orphanst   constsRH   t	   c_literalt   datat   removeR   t   MethodNotDefinedt   NotImplementedErrort   sett
   differencet   temps(   R    Rs   t   vart   nodeRy   Rm   (    (   R    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyRv   7  s<    	.!"	c   %   	   C` s  t  |  d t  r |  j S|  j } g  } g  } i  } g  } g  } g  } g  } d }	 d }
 x<|  j D]1} t d |	  } | |  j k r d | j j | j	  d | | <qb nt| |  j
 k r t t t g t t t g g } nD| |  j k r1t | t j  st d |   n  t t t g t t t g g } n | |  j k r| j j   s[| | k r|t t t g t t t g g } q!t t t g t t t g g } n | |  j k r| j j   s| | k rt t t g t t t t f g g } q!t t t g t t t t f g g } n t d   t | | |
 | |  \ } } | j | d	 |
 f  | j |  | j | d
 |
 d f  | j |  |
 d 7}
 qb WxUt |  j  D]D\ } } t d |	  } | j   } | t j  k	 r| |  j! | } n  d | } g  | j
 D] } | | ^ q} g  | j D] } | | ^ q%} |
 | d <t" |  | d <| t j  k	 rq| | d <n  t   } |
 d | d <t# |  | d <| t j  k	 r| | d <n  d } d } d } | j$ } y | j | j% | |   Wn t& j' k
 rn- Xt | d t(  s/t) t* | j$  d   y | j | j+ | |   Wn t& j' k
 rbn- Xt | d t(  st) t* | j$  d   yA | j, | | |  } t | t(  st) t* | j$  d   Wn t& j' k
 rn Xy> | j- | |  } t | t(  s$t) t* | j$  d   Wn t& j' k
 r;n Xy> | j. | |  } t | t(  syt) t* | j$  d   Wn t& j' k
 rn Xy | j/ | | | | |  } Wn$ t& j' k
 rt0 d |   n Xt | t(  st) t* | j$  d   d | j$ j1 j2 d | } y | j3 | | | | |  } Wn t& j' k
 rUd } n Xt4 j5 d t* |   | j t6 d | | |   | j | d |
 f  |
 d 7}
 | j t6 | | | i |
 d 6  | j | d	 |
 f  |
 d 7}
 qWg  } | g  t& j7 |  j
 |  j |  j  D] } d | | ^ q7} d d }  t8 | | | t d |	 d  |    }! |! |  _ |  |  _9 | |  _: | |  _; | |  _< | |  _= | |  _> | |  _? |  j
 |  j |  j }" | |  _% | |  _+ |  j= |  j? f |  j@   k rtA d! |  j= d" tB jC tA |  j@   d# d" tB jC tA d$ |  j? d" tB jC tA |  j@   d d" tB jC |  j= |  j? f |  j@   k st)  n  g  t |"  D]< \ }# }$ |" jD |$  d k r|" jE |$  |# k r|# ^ q|  _F |  j S(%   s  
        Generates code for a struct that does the computation of the fgraph and
        stores it in the struct_code field of the instance.

        If reuse_storage is True, outputs and temporaries will be stored in
        the struct so they can be reused each time a function returned by
        make_function is called, which means that the output of a call will
        be invalidated by the next. If reuse_storage is False, that problem
        is avoided.

        This method caches its computations.

        R@   t	   __failurei   t   failure_vart   (t   )s2   All orphans to CLinker must be Constant instances.s8   this shouldn't be possible, please report this exceptiont   initt   geti   s    node_<<<<HASH_PLACEHOLDER>>>>_%iRi   Rj   Ry   R(   is0    didn't return a string for c_support_code_applys-    didn't return a string for c_init_code_applys.    didn't return a string for c_init_code_structs1    didn't return a string for c_support_code_structs1    didn't return a string for c_cleanup_code_structs   %s cannot produce C codes"    didn't return a string for c_codes   // Op class s   
s   compiling un-versioned Apply %st   codes
   storage_%ss   __struct_compiled_op_%ss   <<<<HASH_PLACEHOLDER>>>>RC   s   init_tasks
t   filei    s   tasks
(G   RI   RO   R@   Rw   R   R/   R   RL   R   R   R{   RD   RS   RZ   R_   R   RH   R   Rz   RX   R   t   c_is_simpleRU   R}   Rb   R\   t	   ExceptionRq   R   t	   enumerateR~   R   R   R   R&   R'   RJ   t   c_support_code_applyR   R   R   R   t   strt   c_init_code_applyt   c_init_code_structt   c_support_code_structt   c_cleanup_code_structt   c_codeR   t	   __class__R#   t   c_code_cleanupt   _loggert   infoR   t   uniqRA   t   struct_nameR2   t   r2symbolt   init_blockst
   init_tasksR)   t   taskst   get_init_taskst   printt   syst   stderrt   countt   indext   dupidx(%   R    Rw   R   R   t   symbolR   R   R   R)   R   Ri   Rm   R!   Re   t   builderR-   t   node_numR   Ry   t
   params_varRC   RB   t   isymst   osymst
   sub_structt   struct_supportt   struct_initR7   RJ   R   R   R2   R   R@   t   all_infot   it   x(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR.   o  s0   		!			
  
		



9
										'9c         C` s   g  } xr g  |  j  D] } | j ^ q g  |  j D] } | j ^ q/ D]4 } y | j | j    WqC t j k
 rv qC XqC W| S(   s   
        Returns a list of support code strings that are needed by
        one or more Variables or Ops.
        The support code from Variables is added before the support code from Ops.This might contain duplicates.
        (   R   RL   R~   RJ   R   t   c_support_codeR   R   (   R    Rf   t   yR   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   support_code~  s    $c         C` s  d g } | d d d d g 7} |  j    } x g  |  j D] } | j ^ q8 g  |  j D] } | j ^ qT D]\ } y? y | | j |  7} Wn! t k
 r | | j   7} n XWqh t j k
 r qh Xqh Wt j	 |  } | | j
   7} x g  |  j D] } | j ^ q g  |  j D] } | j ^ qD] } ym y | j |  } Wn t k
 r_| j   } n Xx3 | D]+ } y | j |  Wqgt k
 rqgXqgWWq$t j k
 rq$Xq$W| S(   s   
        Returns a list of compile args that are needed by one
        or more Variables or Ops.

        This might contain duplicates.

        s   -O3s   -fno-math-errnos   -Wno-unused-labels   -Wno-unused-variables   -Wno-write-strings(   t
   c_compilerR   RL   R~   RJ   t   c_compile_argsRX   R   R   R   t   compile_argst   c_no_compile_argsR   t
   ValueError(   R    Rf   R   R   R   t   no_compR   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR     s@    		
$$c         C` s   g  } |  j    } x g  |  j D] } | j ^ q g  |  j D] } | j ^ q; D]\ } y? y | | j |  7} Wn! t k
 r | | j   7} n XWqO t j k
 r qO XqO Wt j	 |  S(   s   
        Returns a list of headers that are needed by one
        or more Types or Ops.

        The return value will not contain duplicates.

        (
   R   R   RL   R~   RJ   t	   c_headersRX   R   R   R   (   R    Rf   R   R   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   headers  s    $c         C` s   g  } xo g  |  j  D] } | j ^ q g  |  j D] } | j ^ q/ D]1 } y | | j   7} WqC t j k
 rs qC XqC Wt j |  S(   s   
        Return a list of code snippets that have to be inserted
        in the module initialization code.

        The return value will not contain duplicates.

        (   R   RL   R~   RJ   t   c_init_codeR   R   R   (   R    Rf   R   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt	   init_code  s    $c         C` s   d  } x g  |  j D] } | j ^ q g  |  j D] } | j ^ q/ D]f } t | d  rC | j   } n qC | d  k r | } qC | rC | | k rC t d | | f   qC qC W| d  k r t j	 S| Sd  S(   NR   s1   Nodes have requested specific different compilers(
   R   R   RL   R~   RJ   t   hasattrR   R   R   t   GCC_compiler(   R    R   R   R   t
   x_compiler(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR     s    $	c         C` s   g  } |  j    } x g  |  j D] } | j ^ q g  |  j D] } | j ^ q; D]\ } y? y | | j |  7} Wn! t k
 r | | j   7} n XWqO t j k
 r qO XqO Wt j	 |  S(   s   
        Returns a list of lib directories that are needed by one
        or more Types or Ops.

        The return value will not contain duplicates.

        (
   R   R   RL   R~   RJ   t   c_header_dirsRX   R   R   R   (   R    Rf   R   R   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   header_dirs  s    $c         C` s   g  } |  j    } x g  |  j D] } | j ^ q g  |  j D] } | j ^ q; D]\ } y? y | | j |  7} Wn! t k
 r | | j   7} n XWqO t j k
 r qO XqO Wt j	 |  S(   s   
        Returns a list of libraries that are needed by one
        or more Types or Ops.

        The return value will not contain duplicates.

        (
   R   R   RL   R~   RJ   t   c_librariesRX   R   R   R   (   R    Rf   R   R   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt	   libraries  s    $c         C` s   g  } |  j    } x g  |  j D] } | j ^ q g  |  j D] } | j ^ q; D]\ } y? y | | j |  7} Wn! t k
 r | | j   7} n XWqO t j k
 r qO XqO Wt j	 |  S(   s   
        Returns a list of lib directories that are needed by one
        or more Types or Ops.

        The return value will not contain duplicates.

        (
   R   R   RL   R~   RJ   t
   c_lib_dirsRX   R   R   R   (   R    Rf   R   R   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   lib_dirs-  s    $c         C` sr  d d d g } | d k r7 t d   |  j D  } n  | d k r i  } g  } x+ t |  j  D] \ } } | | | | <q_ WxA |  j D]3 } | | k r d g | | <n  | j | |  q Wn  t |  } t |  } |  j | | | | d | }	 |	 g  t |  j j |  D] \ }
 } t	 j
 |
 |  ^ qg  t |  j j |  D]! \ } } t	 j
 | | t  ^ qG| f S(   su  
        Compiles this linker's fgraph.

        Parameters
        ----------
        input_storage: list or None
            List of lists of length 1. In order to use the thunk returned
            by __compile__, the inputs must be put in that storage.
            If None, storage will be allocated.
        output_storage: list of lists of length 1
            The thunk returned by __compile__ will put the variables of the
            computation in these lists. If None, storage will be allocated.

        Returns
        -------
        object
            Thunk, input_storage, output_storage, error_storage.

        c         s` s   |  ] } d  g Vq d  S(   N(   R   (   R|   Rm   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pys	   <genexpr>Y  s    t	   keep_lockN(   R   Rd   R{   R   R}   R   t   cthunk_factoryR   Rs   R   t	   ContainerRN   (   R    t   input_storaget   output_storaget   storage_mapR   t   error_storaget   mapR   Rm   t   thunkt   inputt   storaget   output(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   __compile__B  s2    		47c         C` s   g  } g  } d } x` |  j  D]U } | |  j k r7 q n  | j | d | f  | j | d | d f  | d 7} q WxK |  j D]@ } | j | d | f  | j | d | d f  | d 7} q W| | f S(   Ni   R   R   i   R   (   R   R   R   R~   (   R    R   R   Ri   t   vR   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR   s  s    c         C` sg   |  j    \ } } |  j | | | d | \ } } }	 }
 t | | | |
  } |  j | _ | | |	 f S(   s  
        Compiles this linker's fgraph and returns a function to perform the
        computations, as well as lists of storage cells for both the inputs
        and outputs.

        Parameters
        ----------
        input_storage: list or None
            List of lists of length 1. In order to use
            the thunk returned by __compile__, the inputs must be put in
            that storage. If None, storage will be allocated.
        output_storage: list of lists of length 1.
            The thunk returned by __compile__ will put the variables
            of the computation in these lists. If None, storage will
            be allocated.
        storage_map: dict that map variables to storages.
            This is used when you need to customize the storage of
            this thunk
        keep_lock:
            If True, we won't release the lock on the compiledir
            at the end of this function call.
        Returns: thunk, input_storage, output_storage

        The return values can be used as follows:
          f, istor, ostor = clinker.make_thunk()
          istor[0].data = first_input
          istor[1].data = second_input
          f()
          first_output = ostor[0].data
        R   (   R   R   t   _CThunkR~   t   nodes(   R    R   R   R   R   R   R   t   cthunkt
   in_storaget   out_storageR   t   res(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt
   make_thunk  s     c         C` sF   |  j  |  j |  j d |  j   d |  j   d |  j   d |  j   S(   s  
        Return a complete hashable signature of the module we compiled.

        This function must have the property that no two programs that
        compute different things yield the same key.

        The key returned by this function is of the form (version, signature)
        The signature has the following form:
        {{{
            'CLinker.cmodule_key', compilation args, libraries,
            header_dirs, numpy ABI version, config md5,
            (op0, input_signature0, output_signature0),
            (op1, input_signature1, output_signature1),
            ...
            (opK, input_signatureK, output_signatureK),
        }}}

        The signature is a tuple, some elements of which are sub-tuples.

        The outer tuple has a brief header, containing the compilation options
        passed to the compiler, the libraries to link against, an md5 hash
        of theano.config (for all config options where "in_c_key" is True).
        It is followed by elements for every node in the topological ordering
        of `self.fgraph`.

        Input Signature
        ---------------

        Each input signature is a tuple with an element for each input
        to the corresponding Apply node. Each element identifies the
        type of the node input, and the nature of that input in the
        graph.

        The nature of a typical variable is encoded by integer pairs
        ``((a,b),c)``:
        ``a`` is the topological position of the input's owner
              (-1 for graph inputs),
        ``b`` is the index of the variable in the owner's output list.
        ``c`` is a flag indicating whether the variable is in the
              no_recycling set.

        If a variable is also a graph output, then its position in the
        outputs list is also bundled with this tuple (after the b).

        The nature of a Constant instance is defined as its signature,
        together with two integers: the topological position of the
        first Apply using that Constant instance, and the lowest index
        into that Apply's inputs that refers to that Constant.  (These
        two integers are a surrogate for the id() of the Constant.
        The integers are important because merge-able constants have
        the same signature, but require separate containers in C
        code.)  The membership in no_recycling is also included in the
        signature.

        Output Signature
        ----------------

        The outputs of a node are entirely determined by the node's Op
        and the nature of the inputs, but the set of outputs that may
        be re-used by the computation (the elements of
        self.no_recycling) can affect the code that is generated.

        The format of each Op's output signature is a (version, no_recycle)
        pair, where version is incremented if codegen() changes how it
        handles the outputs, and no_recycle is simply a list of
        booleans, indicating whether each output is in the
        no_recycling set. Older versions of compiled modules only have the
        no_recycle list.

        R   R   R   R   (   t   cmodule_key_Rs   Rw   R   R   R   R   (   R    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   cmodule_key  s
    Gc	         C` sA   d d d     Y}	 |	 | |  }
 |  j  |
 | | | | | |  S(   Nt   FakeFunctionGraphc           B` s   e  Z d    Z d   Z RS(   c         S` s   | |  _  | |  _ d  S(   N(   R{   R}   (   R    R{   R}   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR"     s    	c         S` s   t  j |  j |  j  S(   N(   R   t   io_toposortR{   R}   (   R    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   toposort  s    (   R#   R$   R"   R   (    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR     s   	(    (   R   (   R    R{   R}   Rw   R   R   R   t   insert_config_md5R   R   Rs   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   cmodule_key_variables  s
    		c         ` s  | d k r g  } n  | d k r* g  } n  | d k r? g  } n  |  j    t   } t d   t  j  D   t     i   d g }	 | d k	 r t |  }
 t |
  }
 |	 j |
  n  | d k	 r t |  }
 t |
  }
 |	 j |
  n  | d k	 r*t |  }
 t |
  }
 |	 j |
  n  |	 j d t	 j
 j j    | rg|	 j d | j    n  | r|	 j d t j j    n |	 j d  t g          f d    g  } xt   D]\  } t | j d  r| j | j j |   n  x' | j D] } | j | j j    qWx' | j D] } | j | j j    qBW|	 j | j t   f d	   t | j  D  d
 t  f d   | j D  f f   d rd S  | <| j | j  qWxv g  t  j  D]0 \ } } t t | d g    s| | f ^ qD]. \ } } |	 j | j  | d |  f  q/Wt |	  }	 t |  } x | D] } | sd |	 f SqW| |	 f S(   s   
        Do the actual computation of cmodule_key in a static method
        to allow it to be reused in scalar.Composite.__eq__.

        c         s` s'   |  ] \ } } | d  | f f Vq d S(   iN(    (   R|   t   posR   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pys	   <genexpr>(  s    s   CLinker.cmodule_keys   NPY_ABI_VERSION=0x%Xs   c_compiler_str=s   md5:s   md5: <omitted>c         ` s  t  |  t j  r t |     k r |  j   | | f } t | d d  rh | d j   | | f } n  y t |  Wn t k
 r t	  d <d  SX|   t |   <q  t |   } n |   k r  |  } n |  j d  k rEt d    D  s t  t d    j D  st  t d |  t |   |  j  f   n  |   j k r |  j |  j j j |    j j |   f } n"  |  j |  j j j |   f } | |   k f S(   Ni    t   theano_hashc         s` s(   |  ] } t  d    | j D  Vq d S(   c         s` s   |  ] } | d  k	 Vq d  S(   N(   R   (   R|   t   out(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pys	   <genexpr>w  s    N(   t   allR}   (   R|   t   o(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pys	   <genexpr>w  s   c         s` s   |  ] } | j  d  k Vq d  S(   N(   RK   R   (   R|   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pys	   <genexpr>y  s    s   what is this?(   RH   R   Rz   Ri   t	   signatureR   R   t   hashR   RN   R   RK   R   R   R{   RL   RG   R}   R   (   R   t   topological_post   i_idxt   isig(   t   constant_idst   error_on_playRs   t   fgraph_inputs_dictRw   t   op_post   order(    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   in_sigU  s4    
	
"t   c_code_cache_version_applyc         3` s0   |  ]& \ } } | j    |  |  f Vq d  S(   N(   RL   (   R|   t   iposR   (   R  t   node_pos(    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pys	   <genexpr>  s   i   c         3` s   |  ] } |   k Vq d  S(   N(    (   R|   R   (   Rw   (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pys	   <genexpr>  s    i    RG   iN(    (   R   Rt   R   R/   R   R{   t   sortedRd   R   t   npt   coret
   multiarrayt   _get_ndarray_c_versiont   version_strt   theanot   configparsert   get_config_md5RO   R   RJ   R  RL   t   c_code_cache_versionR}   R0   R   RI   (   R    Rs   Rw   R   R   R   R   R   t   fgraph_computed_sett   sigR2   t   versionR   R   R   R   R  R   (    (	   R   R   Rs   R   R  Rw   R  R  R  s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR     sz    									!0&


4&c         C` s   |  j    } | j   S(   N(   t   get_dynamic_moduleR   (   R    t   mod(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   get_src_code  s    c   	      C` s
  | d	 k r! t j t j  } n  |  j   } |  j   } |  j   } |  j   } | j	   } t
   z y_ t j d t |   | j d | j d | d | d |  j   d |  j   d | d |  } Wn1 t k
 r } | j t |  j  f 7_   n XWd	 t   X| S(
   se   
        This compiles the source code for this linker and returns a
        loaded module.

        s   LOCATION %st   module_namet   src_codet   locationt   include_dirsR   t   libst   preargsN(   R   R   t   dlimport_workdirR   R   R  R   R   R   R   R   R   t   debugR   t   compile_strt	   code_hashR   R   R   R2   Rs   R   (	   R    R  R  R   R  R  R  t   moduleRY   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   compile_cmodule  s0     		c         C` sG  t  |  d  s@|  j   t j   } |  j d t |  j   } t j d | d t j } t	 rz d j
 d |  j  } n d t d |  j  } x( |  j   |  j D] } | j |  q W| j |  j  | j |  | j |  x! |  j   D] } | j |  q Wx( |  j   |  j D] } | j |  qW| |  _ n  |  j S(   s   
        Return a cmodule.DynamicModule instance full of the code for our fgraph.

        This method is cached on the first call so it can be called
        multiple times without penalty.

        t   _modi   t   instantiatet   methods0  
        static int {struct_name}_executor({struct_name} *self) {{
            return self->run();
        }}

        static void {struct_name}_destructor(PyObject *capsule) {{
            {struct_name} *self = ({struct_name} *)PyCapsule_GetContext(capsule);
            delete self;
        }}
        R   s   
        static int %(struct_name)s_executor(%(struct_name)s* self) {
            return self->run();
        }

        static void %(struct_name)s_destructor(void* executor, void* self) {
            delete ((%(struct_name)s*)self);
        }
        (   R   R.   R   t   DynamicModulet   instantiate_codeR   R2   t   ExtFunctiont   METH_VARARGSR   t   formatR   R/   R   R   t   add_support_codeR@   t   add_functionR   t   add_includeR   R   t   add_init_codeR#  (   R    R  R   R$  t   staticR   t   headert   init_code_block(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR    s(    


c         C` s  y |  j    } Wn t k
 r) d } n X| d k rE |  j   } nN x* |  j D] } | j j | | d d  qO Wt   j d | d |  d |  } |  j	 |  j
 |  j }	 g  t |	  D]< \ }
 } |	 j |  d k r |	 j |  |
 k r |
 ^ q } g  t |  D]( \ }
 } |
 t |  | k r| ^ q} g  t |  D] \ }
 } |
 | k rA| ^ qA} | d k rg  |  j D] } | j g ^ q{} n  g  |  j D] } | | ^ q} | j | | | |  } | S(   s  
        Returns a thunk that points to an instance of a C struct that
        can carry on the computation of this linker's fgraph

        Parameters:
        ----------
        error_storage -> list of length 3
        in_storage -> list of lists of length 1, one per input
        out_storage -> list of lists of length 1, one per output

        Returns a thunk that points to an instance of a C struct that
        can carry on the computation of this linker's fgraph. That thunk,
        when executed, will fetch its inputs from in_storage, put its
        outputs in out_storage and if an error occurs will put the
        type, value and traceback of the exception in error_storage.
        RP   t   keyt   lnkR   i   N(   R   t   KeyErrorR   R"  R~   RJ   t   prepare_nodeR   t   module_from_keyR{   R}   R   R   R   R   R   R   R$  (   R    R   R   R   R   R   R2  R!  R   t   varsR   R   R   t   orphant   orphdRf   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR     s,    
6"1% 	c         C` sL  t    } |  j } t d d | t d d | t d t   d | t d t   d | t d d | t d d | t d t   d | t d	 d
 j d   t |  D  d d | t d d | t d d | t d d | t rt d j t     d | n t d t   d | t d d | | j   S(   NsD   static PyObject * instantiate(PyObject * self, PyObject *argtuple) {R   s"     assert(PyTuple_Check(argtuple));s-     if (%(n_args)i != PyTuple_Size(argtuple)){ s{        PyErr_Format(PyExc_TypeError, "Wrong number of arguments, expected %(n_args)i, got %%i", (int)PyTuple_Size(argtuple));s        return NULL;s     }s6     %(struct_name)s* struct_ptr = new %(struct_name)s();s     if (struct_ptr->init(t   ,c         s` s   |  ] } d  | Vq d S(   s   PyTuple_GET_ITEM(argtuple, %i)N(    (   R|   t   n(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pys	   <genexpr>Q  s    s	   ) != 0) {s       delete struct_ptr;s       return NULL;s       PyObject* thunk = PyCapsule_New((void*)(&{struct_name}_executor), NULL, {struct_name}_destructor);
    if (thunk != NULL && PyCapsule_SetContext(thunk, struct_ptr) != 0) {{
        PyErr_Clear();
        Py_DECREF(thunk);
        thunk = NULL;
    }}
s}     PyObject* thunk = PyCObject_FromVoidPtrAndDesc((void*)(&%(struct_name)s_executor), struct_ptr, %(struct_name)s_destructor);s     return thunk; }(	   R	   R   R   R1   R   R
   R   R*  t   getvalue(   R    t   n_argsR   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR'  G  s&    		/(   R#   R$   R%   R   R"   Ru   Rv   R.   R   R   R   R   R   R   R   R   RO   R   R   R   R   RN   R   R   R  R"  R  R   R'  (    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyRr     s>   
	8	 		:						0	(	O		 	<2R   c           B` s)   e  Z d  Z d   Z d   Z d   Z RS(   s   
    A thunk with a C implementation.

    Parameters
    ----------
    cthunk
        The CObject pointer used by run_cthunk.
    init_tasks
        WRITEME
    tasks
        WRITEME
    error_storage
        WRITEME

    c         C` sG   t  d  k r d d l m  a  n  | |  _ | |  _ | |  _ | |  _ d  S(   Ni    (   t
   run_cthunk(   R>  R   t   theano.gof.cutilsR   R   R   R   (   R    R   R   R   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR"   u  s    			c         C` s\   | d 8} t  |  j  } | d | k  rI |  j |  j g | d | d S|  j | | Sd S(   sL   
        Maps a failure code to the task that is associated to it.

        i   i   N(   R   R   R   (   R    R&   R;  (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt	   find_task  s    
c   
      C` s  t  |  j  } | r |  j |  \ } } } y | j } Wn t k
 rS d } n XyR |  j \ } } } | |  j k r |  j j |  |  _ n  | |  }	 | |	 _	 WnC t
 k
 r t d d d d t j t |  j d t j   n Xt | |	 |  n  d  S(   Ns?   ERROR retrieving error_storage.Was the error set in the c code?t   endt    R   (    (   R>  R   R@  t   tracet   AttributeErrorR   R   R   t   position_of_errort   __thunk_trace__R   R   R   R   R   (
   R    t   failuret   taskt   tasknameRi   RC  t   exc_typet
   _exc_valuet	   exc_tracet	   exc_value(    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   __call__  s&    
	(   R#   R$   R%   R"   R@  RN  (    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR   d  s   	
	t   OpWiseCLinkerc           B` sM   e  Z d  Z i  Z e d e d d  Z d d d  Z d d d d d  Z RS(   s  
    Uses CLinker on the individual Ops that comprise an fgraph and loops
    over them in Python. The variable is slower than a compiled version of
    the whole fgraph, but saves on compilation time because small changes
    in the computation graph won't necessarily trigger any recompilation,
    only local changes in the Variables or Ops that are used.

    If fallback_on_perform is True, OpWiseCLinker will use an op's
    perform method if no C version can be generated.

    no_recycling can contain a list of Variables that belong to the fgraph.
    If a Variable is in no_recycling, CLinker will clear the output storage
    associated to it prior to computation (to avoid reusing it).

    Notes
    -----
    This is in a sense the 'default' linker for Theano. The
    overhead of using the OpWiseCLinker as compared with the CLinker
    is only noticeable for graphs of very small tensors (such as 20
    elements or less).

    c         C` sR   | d  k r t j } n  d  |  _ | |  _ | |  _ | |  _ | rN | |  _ n  d  S(   N(   R   R   t   allow_gcRs   t   fallback_on_performt   nice_errorsRt   (   R    RQ  RP  RR  Rt   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR"     s    				c      	   C` s   | d k r g  } n  |  j d k	 rs |  j | k	 rs t |   d |  j d |  j d |  j d |  j  j | | |  S| |  _ | |  _ |  S(   s.   
        Associate linker with fgraph
        RQ  RP  RR  Rt   N(	   R   Rs   RL   RQ  RP  RR  Rt   Ru   Rw   (   R    Rs   Rw   Rx   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyRu     s    						c      	   C` s  t  t d d  } z+|  j } |  j |  } |  j } t j | | | | |  \ } } } |  j r t j |  \ }	 }
 g  } n d  } i  } x$ | D] } | j
 d  k g | | <q Wg  } x~ | D]v } | | j j | | | |  g 7} g  | j D] } | | ^ q | d _ g  | j D] } | | ^ q| d _ q Wxl | D]d } |  j rB| j g  | j D]; } | |	 k ra| | j k ra| |
 | k ra| | ^ qa qBqBW| t k rt | j    } t j | |  } n, g  | D] } | | j k r| | ^ q} t j | | | | d | d |  j } |  j | _ Wd  t  t d d  | k rwt   t j | k swt  n  X| g  t | j |  D] \ } } t j | |  ^ qg  t | j |  D]! \ } } t j | | t  ^ q| | f S(   Nt   n_locki    iRw   RR  (   RI   R   Rs   Rt   Rw   R   t   map_storageRP  t	   gc_helperR   RK   RJ   R   R{   R}   R   RN   Rc   t   valuesR   R   t
   streamlineRR  R   RS  R   R   R   (   R    t   profilerR   R   R   t   orig_n_lockRs   R  Rw   t   computedt	   last_usert   post_thunk_old_storaget   compute_mapt   kt   thunksR   R   R   RB   t   fR   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   make_all  sb    				'+	()14N(	   R#   R$   R%   t	   __cache__RN   R   R"   Ru   Ra  (    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyRO    s   
	c         C` s@   |  d | d k r< t  d i |  d d 6| d d 6  n  d S(   s   
    Default checker for DualLinker. This checks that the
    variables contain the same data using ==.


    Parameters:
    ----------
    x,y
        the variables to compare data
    i    s   Output mismatch.t   performlinkert   clinkerN(   R   (   R   R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   _default_checker)  s    t
   DualLinkerc           B` s5   e  Z d  Z e d d  Z d d d  Z d   Z RS(   s  
    Runs the fgraph in parallel using PerformLinker and CLinker.

    The thunk/function produced by DualLinker uses PerformLinker as the
    "main" implementation: the inputs and outputs are fed to/taken from
    the Ops' perform. However, DualLinker also instantiates a copy of
    the fgraph on which it runs OpWiseCLinker. At each step, the variables
    of perform and of the C implementation are verified using a checker
    function.

    c         C` s(   d |  _ | |  _ | r$ | |  _ n  d S(   s`  
        Initialize a DualLinker.

        The checker argument must be a function that takes two lists
        of length 1. The first one passed will contain the output
        computed by PerformLinker and the second one the output
        computed by OpWiseCLinker. The checker should compare the data
        fields of the two variables to see if they match. By default,
        DualLinker uses ==. A custom checker can be provided to
        compare up to a certain error tolerance.

        If a mismatch occurs, the checker should raise an exception to
        halt the computation. If it does not, the computation will
        carry on and errors will snowball. The checker can sidestep
        the problem by fiddling with the data, but it should be
        careful not to share data between the two outputs (or inplace
        operations that use them will interfere).

        no_recycling can contain a list of Variables that belong to the fgraph.
        If a Variable is in no_recycling, CLinker will clear the output storage
        associated to it during the computation (to avoid reusing it).

        N(   R   Rs   t   checkerRt   (   R    Rg  Rt   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR"   F  s    		c         C` sq   | d k r g  } n  |  j d k	 r[ |  j | k	 r[ t |   |  j |  j  j | | |  S| |  _ | |  _ |  S(   s-   
        Update/tie self with fgraph
        N(   R   Rs   RL   Rg  Rt   Ru   Rw   (   R    Rs   Rw   Rx   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyRu   c  s    			c         ` s    j  }  j  t j d  j  j | d  j |   \ }   }   | j d d  t	 d  j  j | d  j |   \ }  }            f d   } |   | f S(   sj   
        Compiles this linker's fgraph and returns a function to perform the
        computations
        Rt   Rw   R   c    
      ` sQ  x7 t      D]& \ }  } t |  j d  | j d <q Wxt       D] \ } } } } x< t  | j | j  D]% \ } } |  k rx d  | d <qx qx Wx< t  | j | j  D]% \ } } |  k r d  | d <q q WyH |   |   x3 t  | j | j  D] \ } }	  j | |	  qWWqP t k
 rHt j |  qP XqP Wd  S(   Ni    (	   R   R   R   R}   R   Rg  R   R   t   raise_with_op(
   t   input1t   input2t   thunk1t   thunk2t   node1t   node2R   R   t   output1t   output2(   t   i1t   i2Rw   t   order1t   order2R    t   thunks1t   thunks2(    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR`    s$    ""N(
   Rs   Rw   R   t   PerformLinkerRt   Ru   Ra  t   popR   RO  (   R    t   kwargsRs   t   _ft   o1t   o2R`  (    (   Rq  Rr  Rw   Rs  Rt  R    Ru  Rv  s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR   p  s    		''$N(   R#   R$   R%   Re  R   R"   Ru   R   (    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyRf  9  s   t   HideCc           B` s}   e  Z d    Z e Z e Z e Z e Z e Z e Z e Z	 e Z
 e Z e Z e Z e Z e Z e Z e Z d   Z d   Z RS(   c          G` s   t  j    d  S(   N(   R   R   (   R2   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   __hide  s    c         C` s   d S(   N(    (    (   R    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR    s    c         C` s
   |  j    S(   N(   R  (   R    R   (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR    s    (   R#   R$   t   _HideC__hideR   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R  R  (    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyR}    s$   		(>   R%   t
   __future__R    R   R   R   R   R   t   loggingt   numpyR  R  R   t   theano.compatR   R   t   sixR   R   t	   six.movesR	   R
   t
   theano.gofR   R   R   R   t   theano.gof.compilelockR   R   t   theano.gof.callcacheR   t	   getLoggerR   R   R>  R   R   R   R   R&   R'   R.   RA   RD   RS   RU   RZ   R\   R_   Rb   Rh   Rq   t   LinkerRr   t   objectR   t   LocalLinkerRO  Re  Rf  R}  (    (    (    s-   /tmp/pip-build-X4mzal/theano/theano/gof/cc.pyt   <module>   s^   	#			%					&	!				/    RA	a