U
    Kcи                  	   @   s>  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mZm	Z	m
Z
mZ d dlmZ d dlmZ dddd	d
ddddg	ZdeeeedddZdeeeedddZdd ZG dd dejjZG dd dejjZG dd	 d	eZG dd
 d
eZG dd dejjZG dd deZG dd deZG dd deZdS )     N)Tensor)TupleOptionalListUnionDict)PackedSequence)_quantize_weightpack_weight_biasPackedParameterRNNBaseLSTMGRURNNCellBaseRNNCellLSTMCellGRUCell   )tensorpermutationdimreturnc                 C   s   |  ||S N)Zindex_selectr   r   r    r   M/tmp/pip-unpacked-wheel-gikjz4vx/torch/ao/nn/quantized/dynamic/modules/rnn.py_apply_permutation   s    r   c                 C   s   t d t| ||S )NzYapply_permutation is deprecated, please use tensor.index_select(dim, permutation) instead)warningswarnr   r   r   r   r   apply_permutation   s    
r   c                 C   s6   |t jkrt jj| |}|S t jj| |}|S d S r   )torchqint8ops	quantizedlinear_prepacklinear_prepack_fp16)qweightbiasdtypepacked_weightr   r   r   r
      s    
 c                       s4   e Zd Z fddZ fddZ fddZ  ZS )r   c                    s   t t|   || _d S r   )superr   __init__param)selfr,   	__class__r   r   r+   +   s    zPackedParameter.__init__c                    s&   t t| ||| | j||d < d S )Nr,   )r*   r   _save_to_state_dictr,   r-   ZdestinationprefixZ	keep_varsr.   r   r   r0   /   s    z#PackedParameter._save_to_state_dictc              	      s.   ||d  | _ tt| |||d||| d S )Nr,   F)r,   r*   r   _load_from_state_dictr-   
state_dictr2   local_metadatastrictmissing_keysunexpected_keys
error_msgsr.   r   r   r3   3   s      z%PackedParameter._load_from_state_dict)__name__
__module____qualname__r+   r0   r3   __classcell__r   r   r.   r   r   *   s   c                       s
  e Zd ZejZdZdddddejf fdd	Z	dd	 Z
d
d Zdd Zeee ddddZeee eeeef dddZd*eeeeef eddddZeeee ddddZeee edddZ fddZd d! Zed"d# Zd$d% Zd&d' Zd(d) Z  ZS )+r      r   TFg        c
              	      sZ  t t|   || _|| _|| _|| _|| _|| _t	|| _
|| _|	| _d| _d| _|r\dnd}
t|tjrd|  krdkrn n
t|trtd|dkr|dkrtd|| |dkrd| }n|d	krd
| }ntd| g }t|D ]P}t|
D ]@}|dkr|n||
 }t||tj	}t||tj	}t|tj	}t|tj	}|	tjkrtj|ddtjd}tj|ddtjd}tjj||}tjj||}| jd ks| jdk rtjj ||||}ntjj ||||d}n0tjj!||}tjj!||}tjj"||}|#t$| qqtj%&|| _'d S )Nr?   Fr   r   zbdropout should be a number in range [0, 1] representing the probability of an element being zeroedzdropout option adds dropout after all but last recurrent layer, so non-zero dropout expects num_layers greater than 1, but got dropout={} and num_layers={}r      r      zUnrecognized RNN mode: g?ZscaleZ
zero_pointr(   T)(r*   r   r+   mode
input_sizehidden_size
num_layersr'   batch_firstfloatdropoutbidirectionalr(   versiontraining
isinstancenumbersNumberbool
ValueErrorr   r   formatranger    randntor!   quantize_per_tensorr"   r#   r$   "make_quantized_cell_params_dynamicr%   make_quantized_cell_params_fp16appendr   nn
ModuleList_all_weight_values)r-   rC   rD   rE   rF   r'   rG   rI   rJ   r(   num_directionsZ	gate_sizer\   layer	directionZlayer_input_sizew_ihw_hhb_ihb_hh	packed_ih	packed_hhcell_paramsr.   r   r   r+   ?   s    
 
 

        zRNNBase.__init__c                 C   s   dS )NZDynamicQuantizedRNNr   r-   r   r   r   	_get_name   s    zRNNBase._get_namec                 C   sl   d}| j dkr|d7 }| jdk	r(|d7 }| jdk	r:|d7 }| jdkrL|d	7 }| jdk	r^|d
7 }|jf | jS )N{input_size}, {hidden_size}r   z, num_layers={num_layers}T, bias={bias}Fz, batch_first={batch_first}r   z, dropout={dropout}z, bidirectional={bidirectional})rF   r'   rG   rI   rJ   rR   __dict__r-   sr   r   r   
extra_repr   s    




zRNNBase.extra_reprc           	      C   s   g }|   }|r|d}g }| j D ]H\}}t|ttjfrBq(t|}tj	j
|d}|d| d |  q(|| }|  d }|rt|dkr|s||d 7 }n|dd| d 7 }|d7 }|S )	N
r?   (z): r   r   z
  ))rn   splitZ_modulesitemsrM   r   rZ   r[   reprmodulesmoduleZ
_addindentrY   rh   lenjoin)	r-   Zextra_linesrn   Zchild_lineskeyrv   Zmod_strlinesZmain_strr   r   r   __repr__   s&    
zRNNBase.__repr__N)inputbatch_sizesr   c                 C   s\   |d k	rdnd}|  |kr0td||  | j|dkrXtd| j|dd S )Nr?   rA   z%input must have {} dimensions, got {}z?input.size(-1) must be equal to input_size. Expected {}, got {})r   RuntimeErrorrR   rD   size)r-   r|   r}   Zexpected_input_dimr   r   r   check_input   s      zRNNBase.check_inputc                 C   sT   |d k	rt |d }n| jr&|dn|d}| jr:dnd}| j| || jf}|S )Nr   r   r?   )intrG   r   rJ   rF   rE   )r-   r|   r}   Z
mini_batchr]   expected_hidden_sizer   r   r   get_expected_hidden_size   s     z RNNBase.get_expected_hidden_sizeExpected hidden size {}, got {})hxr   msgr   c                 C   s(   |  |kr$t||t|  d S r   )r   r   rR   list)r-   r   r   r   r   r   r   check_hidden_size   s
     
zRNNBase.check_hidden_sizer|   hiddenr}   r   c                 C   s,   |  || | ||}| j||dd d S )Nr   )r   r   r   r   r-   r|   r   r}   r   r   r   r   check_forward_args   s
    zRNNBase.check_forward_argsr   r   r   c                 C   s   |d kr|S t ||S r   r   r-   r   r   r   r   r   permute_hidden   s    zRNNBase.permute_hiddenc           	   	      s2   | dd }|| _tt| |||d||| d S )NrK   F)getrK   r*   r   r3   )	r-   r5   r2   r6   r7   r8   r9   r:   rK   r.   r   r   r3      s      zRNNBase._load_from_state_dictc              	   C   sJ  dd }| j rdnd}g }t| jD ]}t|D ] }|dkrDdnd}|d||\}}	|d||\}
}|| }||	 }||
 }|| }|jtjkrtjj||}tjj||}| j	d ks| j	dk rtjj
||||}ntjj
||||d	}n0tjj||}tjj||}tjj||}|t| q2q$tj|| _d S )
Nc                 S   s$   d | ||}d | ||}||fS Nzweight_{}_l{}{}zbias_{}_l{}{})rR   )ihhhr^   suffixweight_name	bias_namer   r   r   weight_bias_name   s    z1RNNBase.set_weight_bias.<locals>.weight_bias_namer?   r   _reverse ihhhT)rJ   rS   rF   r(   r    r!   r"   r#   r$   rK   rW   r%   rX   rY   r   rZ   r[   r\   )r-   weight_bias_dictr   r]   r\   r^   r_   r   Z	w_ih_nameZ	b_ih_nameZ	w_hh_nameZ	b_hh_namer`   rb   ra   rc   rd   re   rf   r   r   r   set_weight_bias   sJ            zRNNBase.set_weight_biasc              	      sZ  t ttjjtjjgks$tdtds6tdjd k	rVjj	d k	rVjj	nddl
m} |j	 j}tjtjg}||krtd|jdkrtjjjjjjj|}n8jdkrtjjjjjjj|}ntd	jrd
nd}jstg }t|jD ]  t|D ]}|dkrFdnd fdd}	|	d\}
}|	d\}}|tjkrfdd}||
|}|||}|jd ks|jd
k rtjj||||}ntjj||||d}nN|tjkr*tjj|
  |}tjj|  |}tjj!||}ntd|"t#| q2q$tj$||_%|S )NzInn.quantized.dynamic.RNNBase.from_float only works for nn.LSTM and nn.GRUqconfig,Input float module must have qconfig definedr   default_dynamic_qconfig2Unsupported dtype for dynamic RNN quantization: {}r   r   z3Only LSTM/GRU is supported for QuantizedRNN for nowr?   r   r   r   c                    s8   d |  }d |  }t|}t|}||fS r   )rR   getattr)r   r   r   weightr'   )r^   modr   r   r   retrieve_weight_bias3  s
    

z0RNNBase.from_float.<locals>.retrieve_weight_biasr   r   c                    s0     }||  t |  |}tjj||}|S r   )r	   rH   r    r"   r#   r$   )wbweight_observerr&   r)   )weight_observer_methodr   r   quantize_and_pack>  s    z-RNNBase.from_float.<locals>.quantize_and_packTz7Unsupported dtype specified for dynamic quantized LSTM!)&typesetr    rZ   r   r   AssertionErrorhasattrr   r   torch.ao.quantization.qconfigr   r(   r!   float16r   rR   rC   rD   rE   rF   r'   rG   rI   rJ   NotImplementedErrorrS   rK   r"   r#   rW   r%   rH   rX   rY   r   r[   r\   )clsr   r   r(   supported_scalar_typesZqRNNBaser]   r\   r_   r   	weight_ihbias_ih	weight_hhbias_hhr   rd   re   rf   r   )r^   r   r   r   r   
from_float  s    

    
    

          zRNNBase.from_floatc           
      C   s  i i d}d}| j rdnd}t| jD ]}t|D ]}|dkrBdnd}dj||d}d	j||d}| j| j d d
 }	|	d  d d |d |< |	d  d d |d |< dj||d}dj||d}|	d  d d |d |< |	d  d d |d |< |d }q2q&|S )Nr   r'   r   r?   r   r   r   zweight_ih_l{layer_idx}{suffix})Z	layer_idxr   zweight_hh_l{layer_idx}{suffix}r@   r   zbias_ih_l{layer_idx}{suffix}zbias_hh_l{layer_idx}{suffix}r'   )rJ   rS   rF   rR   r\   r,   __getstate__)
r-   r   countr]   r^   r_   r   Z	key_name1Z	key_name2Zpacked_weight_biasr   r   r   _weight_bias_  s"    
zRNNBase._weight_biasc                 C   s   |   d S Nr   r   rg   r   r   r   
get_weightu  s    zRNNBase.get_weightc                 C   s   |   d S Nr'   r   rg   r   r   r   get_biasx  s    zRNNBase.get_bias)r   )r;   r<   r=   rZ   r   _FLOAT_MODULE_versionr    r!   r+   rh   rn   r{   r   r   r   r   r   r   strr   r   r   r3   r   classmethodr   r   r   r   r>   r   r   r.   r   r   9   s<       E   %
Wc                
       sZ  e Zd ZdZejZdddgiZ fddZdd Z	e
eee
e
f  ee
 eee
 ee
ee
e
f f d	d
dZejjde
eee
e
f  ee
ee
e
f f dddZejjdeeee
e
f  eeee
e
f f dddZee
e
f ee
 ee
e
f dddZe
ee
e
f ee
 ddddZejjd ddZe fddZedd Z  ZS )!r   a  
    A dynamic quantized LSTM module with floating point tensor as inputs and outputs.
    We adopt the same interface as `torch.nn.LSTM`, please see
    https://pytorch.org/docs/stable/nn.html#torch.nn.LSTM for documentation.

    Examples::

        >>> rnn = nn.LSTM(10, 20, 2)
        >>> input = torch.randn(5, 3, 10)
        >>> h0 = torch.randn(2, 3, 20)
        >>> c0 = torch.randn(2, 3, 20)
        >>> output, (hn, cn) = rnn(input, (h0, c0))
    forwardforward_packedforward_tensorc                    s   t t| jd|| d S )Nr   )r   )r*   r   r+   r-   argskwargsr.   r   r   r+     s    zLSTM.__init__c                 C   s   dS )NZDynamicQuantizedLSTMr   rg   r   r   r   rh     s    zLSTM._get_namer|   r   r}   max_batch_sizesorted_indicesr   c                 C   s   |d kr@| j rdnd}tj| j| || j|j|jd}||f}n| ||}| ||| dd | j	D }|d krtj
|||| j| jt| j| j| j | j| jdd}	n0tj
||||| j| jt| j| j| j | jdd}	|	d }
|	dd  }|
|fS )	Nr?   r   r(   devicec                 S   s   g | ]
}|j qS r   r,   .0mr   r   r   
<listcomp>  s     z%LSTM.forward_impl.<locals>.<listcomp>T)r(   Zuse_dynamicr   )rJ   r    zerosrF   rE   r(   r   r   r   r\   Zquantized_lstmr'   rH   rI   rL   rG   r-   r|   r   r}   r   r   r]   r   Z_all_paramsresultoutputr   r   r   r   forward_impl  s@      
        zLSTM.forward_implNr|   r   r   c           	      C   sL   d }| j r|dn|d}d }d }| |||||\}}|| ||fS Nr   r   rG   r   r   r   	r-   r|   r   r}   r   r   unsorted_indicesr   r   r   r   r   r     s        zLSTM.forward_tensorc                 C   sP   |\}}}}|d }t |}| |||||\}}	t||||}
|
| |	|fS Nr   r   r   r   r   r-   r|   r   Zinput_r}   r   r   r   Zoutput_r   r   r   r   r   r     s         zLSTM.forward_packedr   c                 C   s(   |d kr|S t |d |t |d |fS r   r   r   r   r   r   r     s    zLSTM.permute_hiddenr   c                 C   s@   |  || | ||}| |d |d | |d |d d S )Nr   z"Expected hidden[0] size {}, got {}r   z"Expected hidden[1] size {}, got {}r   r   r   r   r   r     s    zLSTM.check_forward_argsc                 C   s&   t |tr| ||S | ||S d S r   rM   r   r   r   r-   r|   r   r   r   r   r     s    
zLSTM.forwardc                    s   t t| |S r   )r*   r   r   r   r   r.   r   r   r     s    zLSTM.from_floatc              	   C   sJ   t |dstd| |j|j|j|j|j|j|j|j	}|
|  |S )Nweight_ih_l0_dtypezWe are assuming weight_ih_l0 )r   r   rD   rE   rF   r'   rG   rI   rJ   r   r   Zget_quantized_weight_bias_dict)r   ref_modqmodr   r   r   from_reference  s    zLSTM.from_reference)N)N)N)r;   r<   r=   __doc__rZ   r   r   __overloads__r+   rh   r   r   r   r   r   r    jitexportr   r   r   r   r   ignorer   r   r   r   r>   r   r   r.   r   r   {  sR          
 
	 
 c                       s  e Zd ZdZejZdddgiZ fddZdd Z	e
e
ee
 d	d
ddZe
ee
 ee
 eee
 ee
e
f dddZejjde
ee
 ee
e
f dddZejjdeee
 eee
f dddZe
ee
 e
dddZejjdddZe fddZ  ZS )r   a  Applies a multi-layer gated recurrent unit (GRU) RNN to an input sequence.


    For each element in the input sequence, each layer computes the following
    function:

    .. math::
        \begin{array}{ll}
            r_t = \sigma(W_{ir} x_t + b_{ir} + W_{hr} h_{(t-1)} + b_{hr}) \\
            z_t = \sigma(W_{iz} x_t + b_{iz} + W_{hz} h_{(t-1)} + b_{hz}) \\
            n_t = \tanh(W_{in} x_t + b_{in} + r_t * (W_{hn} h_{(t-1)}+ b_{hn})) \\
            h_t = (1 - z_t) * n_t + z_t * h_{(t-1)}
        \end{array}

    where :math:`h_t` is the hidden state at time `t`, :math:`x_t` is the input
    at time `t`, :math:`h_{(t-1)}` is the hidden state of the layer
    at time `t-1` or the initial hidden state at time `0`, and :math:`r_t`,
    :math:`z_t`, :math:`n_t` are the reset, update, and new gates, respectively.
    :math:`\sigma` is the sigmoid function, and :math:`*` is the Hadamard product.

    In a multilayer GRU, the input :math:`x^{(l)}_t` of the :math:`l` -th layer
    (:math:`l >= 2`) is the hidden state :math:`h^{(l-1)}_t` of the previous layer multiplied by
    dropout :math:`\delta^{(l-1)}_t` where each :math:`\delta^{(l-1)}_t` is a Bernoulli random
    variable which is :math:`0` with probability :attr:`dropout`.

    Args:
        input_size: The number of expected features in the input `x`
        hidden_size: The number of features in the hidden state `h`
        num_layers: Number of recurrent layers. E.g., setting ``num_layers=2``
            would mean stacking two GRUs together to form a `stacked GRU`,
            with the second GRU taking in outputs of the first GRU and
            computing the final results. Default: 1
        bias: If ``False``, then the layer does not use bias weights `b_ih` and `b_hh`.
            Default: ``True``
        batch_first: If ``True``, then the input and output tensors are provided
            as (batch, seq, feature). Default: ``False``
        dropout: If non-zero, introduces a `Dropout` layer on the outputs of each
            GRU layer except the last layer, with dropout probability equal to
            :attr:`dropout`. Default: 0
        bidirectional: If ``True``, becomes a bidirectional GRU. Default: ``False``

    Inputs: input, h_0
        - **input** of shape `(seq_len, batch, input_size)`: tensor containing the features
          of the input sequence. The input can also be a packed variable length
          sequence. See :func:`torch.nn.utils.rnn.pack_padded_sequence`
          for details.
        - **h_0** of shape `(num_layers * num_directions, batch, hidden_size)`: tensor
          containing the initial hidden state for each element in the batch.
          Defaults to zero if not provided. If the RNN is bidirectional,
          num_directions should be 2, else it should be 1.

    Outputs: output, h_n
        - **output** of shape `(seq_len, batch, num_directions * hidden_size)`: tensor
          containing the output features h_t from the last layer of the GRU,
          for each `t`. If a :class:`torch.nn.utils.rnn.PackedSequence` has been
          given as the input, the output will also be a packed sequence.
          For the unpacked case, the directions can be separated
          using ``output.view(seq_len, batch, num_directions, hidden_size)``,
          with forward and backward being direction `0` and `1` respectively.

          Similarly, the directions can be separated in the packed case.
        - **h_n** of shape `(num_layers * num_directions, batch, hidden_size)`: tensor
          containing the hidden state for `t = seq_len`

          Like *output*, the layers can be separated using
          ``h_n.view(num_layers, num_directions, batch, hidden_size)``.

    Shape:
        - Input1: :math:`(L, N, H_{in})` tensor containing input features where
          :math:`H_{in}=\text{input\_size}` and `L` represents a sequence length.
        - Input2: :math:`(S, N, H_{out})` tensor
          containing the initial hidden state for each element in the batch.
          :math:`H_{out}=\text{hidden\_size}`
          Defaults to zero if not provided. where :math:`S=\text{num\_layers} * \text{num\_directions}`
          If the RNN is bidirectional, num_directions should be 2, else it should be 1.
        - Output1: :math:`(L, N, H_{all})` where :math:`H_{all}=\text{num\_directions} * \text{hidden\_size}`
        - Output2: :math:`(S, N, H_{out})` tensor containing the next hidden state
          for each element in the batch

    Attributes:
        weight_ih_l[k] : the learnable input-hidden weights of the :math:`\text{k}^{th}` layer
            (W_ir|W_iz|W_in), of shape `(3*hidden_size, input_size)` for `k = 0`.
            Otherwise, the shape is `(3*hidden_size, num_directions * hidden_size)`
        weight_hh_l[k] : the learnable hidden-hidden weights of the :math:`\text{k}^{th}` layer
            (W_hr|W_hz|W_hn), of shape `(3*hidden_size, hidden_size)`
        bias_ih_l[k] : the learnable input-hidden bias of the :math:`\text{k}^{th}` layer
            (b_ir|b_iz|b_in), of shape `(3*hidden_size)`
        bias_hh_l[k] : the learnable hidden-hidden bias of the :math:`\text{k}^{th}` layer
            (b_hr|b_hz|b_hn), of shape `(3*hidden_size)`

    .. note::
        All the weights and biases are initialized from :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})`
        where :math:`k = \frac{1}{\text{hidden\_size}}`

    .. include:: ../cudnn_persistent_rnn.rst

    Examples::

        >>> rnn = nn.GRU(10, 20, 2)
        >>> input = torch.randn(5, 3, 10)
        >>> h0 = torch.randn(2, 3, 20)
        >>> output, hn = rnn(input, h0)
    r   r   r   c                    s   t t| jd|| d S )Nr   )r   )r*   r   r+   r   r.   r   r   r+   n  s    zGRU.__init__c                 C   s   dS )NZDynamicQuantizedGRUr   rg   r   r   r   rh   q  s    zGRU._get_nameNr   c                 C   s*   |  || | ||}| ||d d S )Nr   r   r   r   r   r   r   t  s
    zGRU.check_forward_argsr   c                 C   s   |d kr<| j rdnd}tj| j| || j|j|jd}|}n| ||}| ||| dd | j	D }|d krt
|||| j| j| j| j| j | j	}	n$t
||||| j| j| j| j| j 	}	|	d }
|	d }|
|fS )Nr?   r   r   c                 S   s   g | ]
}|j qS r   r   r   r   r   r   r     s     z$GRU.forward_impl.<locals>.<listcomp>r   )rJ   r    r   rF   rE   r(   r   r   r   r\   Zquantized_grur'   rI   rL   rG   r   r   r   r   r   {  sH      
	zGRU.forward_implr   c           	      C   sL   d }| j r|dn|d}d }d }| |||||\}}|| ||fS r   r   r   r   r   r   r     s        zGRU.forward_tensorc                 C   sP   |\}}}}|d }t |}| |||||\}}	t||||}
|
| |	|fS r   r   r   r   r   r   r     s         zGRU.forward_packedr   c                 C   s   |d kr|S t ||S r   r   r   r   r   r   r     s    zGRU.permute_hiddenc                 C   s&   t |tr| ||S | ||S d S r   r   r   r   r   r   r     s    
zGRU.forwardc                    s   t t| |S r   )r*   r   r   r   r.   r   r   r     s    zGRU.from_float)N)N)N)r;   r<   r=   r   rZ   r   r   r   r+   rh   r   r   r   r   r   r   r    r   r   r   r   r   r   r   r   r   r   r>   r   r   r.   r   r     sF   g  
-  
  
 c                       s   e Zd ZdddgZddejf fdd	Zdd	 Zd
d Zdd Z	d#e
e
eddddZedd Zedd Zdd Zdd Zdd Zdd Z fdd Z fd!d"Z  ZS )$r   rD   rE   r'   Tr@   c           
         s@  t t|   || _|| _|| _|| _|r`t|| j	tj
d| _t|| j	tj
d| _n| dd  | dd  t|| |	tj
}t|| |	tj
}|tjkrtj|ddtjd}tj|ddtjd}|tjkrtjj|| j}tjj|| j}	n$tjj|| j}tjj|| j}	|| _|	| _d S )Nr(   r   r   r   r   rB   )r*   r   r+   rD   rE   r'   weight_dtyper    rT   rU   rH   r   r   Zregister_parameterr!   rV   r"   r#   r$   r%   _packed_weight_ih_packed_weight_hh)
r-   rD   rE   r'   
num_chunksr(   r   r   Zpacked_weight_ihZpacked_weight_hhr.   r   r   r+     s<    
  zRNNCellBase.__init__c                 C   s   dS )NZDynamicQuantizedRNNBaser   rg   r   r   r   rh     s    zRNNCellBase._get_namec                 C   sJ   d}d| j kr | jdk	r |d7 }d| j kr<| jdkr<|d7 }|jf | j S )Nri   r'   Trj   nonlinearitytanhz, nonlinearity={nonlinearity})rk   r'   r   rR   rl   r   r   r   rn     s    zRNNCellBase.extra_reprc                 C   s,   | d| jkr(td| d| jd S )Nr   z6input has inconsistent input_size: got {}, expected {})r   rD   r   rR   )r-   r|   r   r   r   check_forward_input  s     zRNNCellBase.check_forward_inputr   N)r|   r   hidden_labelr   c                 C   s`   | d| dkr2td| d|| d| d| jkr\td|| d| jd S )Nr   z8Input batch size {} doesn't match hidden{} batch size {}r   z:hidden{} has inconsistent hidden_size: got {}, expected {})r   r   rR   rE   )r-   r|   r   r   r   r   r   check_forward_hidden  s         z RNNCellBase.check_forward_hiddenc                    sh  t |ttjjtjjtjjgks*tdt|ds<td|j	d k	r\|j	j
d k	r\|j	j
nddlm} |j
 j tjtjg} |krtd t |tjjkrt|j|j|j d}n^t |tjjkrt|j|j|j d}n6t |tjjkrt|j|j|j|j d}ntd	|js*t fd
d}t||j|j |_t||j|j |_|S )Nznn.quantized.dynamic.RNNCellBase.from_float                                  only works for nn.LSTMCell, nn.GRUCell and nn.RNNCellr   r   r   r   r   )r'   r(   )r'   r   r(   zUOnly LSTMCell, GRUCell and RNNCell             are supported for QuantizedRNN for nowc                    s6    t jkr* }||  t|  |}|S |  S d S r   )r    r!   r	   rH   )r   r   r&   r(   r   r   r   _observe_and_quantize_weightE  s    
z<RNNCellBase.from_float.<locals>._observe_and_quantize_weight)r   r   r    rZ   r   r   r   r   r   r   r   r   r   r(   r!   r   r   rR   rD   rE   r'   r   r   r
   r   r   r   r   r   r   )r   r   r   r   ZqRNNCellBaser   r   r   r   r      s@    
 
	zRNNCellBase.from_floatc                 C   s   t |dstdt |dr:| |j|j|j|j|jd}n| |j|j|j|jd}| | d|j	|j
dd}|| |S )Nweight_ih_dtypezWe are assuming weight_ih r   r   )r   r   )r   r   r   )r   r   rD   rE   r'   r   r   Zget_quantized_weight_ihZget_quantized_weight_hhr   r   r   )r   r   r   r   r   r   r   r   R  s0    


zRNNCellBase.from_referencec                 C   sb   i i d}| j  d \}}| j d \}}||d d< ||d d< ||d d< ||d d< |S )	Nr   r   r   r   r   r'   r   r   )r   r   r   )r-   r   Zw1Zb1Zw2Zb2r   r   r   r   r  s    
zRNNCellBase._weight_biasc                 C   s   |   d S r   r   rg   r   r   r   r     s    zRNNCellBase.get_weightc                 C   s   |   d S r   r   rg   r   r   r   r     s    zRNNCellBase.get_biasc                 C   sD   t |d d |d d | j| _t |d d |d d | j| _d S )Nr   r   r'   r   r   r   )r
   r   r   r   )r-   r   r   r   r   r     s    



zRNNCellBase.set_weight_biasc                    s4   t t| ||| | j||d < | j||d < d S )Nr   r   )r*   r   r0   r   r   r1   r.   r   r   r0     s    zRNNCellBase._save_to_state_dictc              	      s@   | |d | _| |d | _tt| |||d||| d S )Nr   r   F)popr   r   r*   r   r3   r4   r.   r   r   r3     s      z!RNNCellBase._load_from_state_dict)r   )r;   r<   r=   __constants__r    r!   r+   rh   rn   r   r   r   r   r   r   r   r   r   r   r   r0   r3   r>   r   r   r.   r   r     s    
)
1
c                       sf   e Zd ZdZddddgZddejf fdd		Zd
d Zde	e
e	 e	dddZe fddZ  ZS )r   aG  An Elman RNN cell with tanh or ReLU non-linearity.
    A dynamic quantized RNNCell module with floating point tensor as inputs and outputs.
    Weights are quantized to 8 bits. We adopt the same interface as `torch.nn.RNNCell`,
    please see https://pytorch.org/docs/stable/nn.html#torch.nn.RNNCell for documentation.

    Examples::

        >>> rnn = nn.RNNCell(10, 20)
        >>> input = torch.randn(6, 3, 10)
        >>> hx = torch.randn(3, 20)
        >>> output = []
        >>> for i in range(6):
        ...     hx = rnn(input[i], hx)
        ...     output.append(hx)
    rD   rE   r'   r   Tr   c                    s$   t t| j|||d|d || _d S )Nr   r   r(   )r*   r   r+   r   )r-   rD   rE   r'   r   r(   r.   r   r   r+     s    zRNNCell.__init__c                 C   s   dS )NZDynamicQuantizedRNNCellr   rg   r   r   r   rh     s    zRNNCell._get_nameNr   c                 C   s   |  | |d kr0tj|d| j|j|jd}| ||d | jdkrjtj	j
||| j| j| j| j}n@| jdkrtj	j
||| j| j| j| j}n|}td| j|S )Nr   r   r   r   ZreluzUnknown nonlinearity: {})r   r    r   r   rE   r(   r   r   r   r"   r#   Zquantized_rnn_tanh_cell_dynamicr   r   r   r   Zquantized_rnn_relu_cell_dynamicr   rR   )r-   r|   r   retr   r   r   r     s6    

   
   
zRNNCell.forwardc                    s   t t| |S r   )r*   r   r   r   r.   r   r   r     s    zRNNCell.from_float)N)r;   r<   r=   r   r   r    r!   r+   rh   r   r   r   r   r   r>   r   r   r.   r   r     s   c                       s`   e Zd ZdZ fddZdd Zdeeeeef  eeef ddd	Z	e
 fd
dZ  ZS )r   am  A long short-term memory (LSTM) cell.

    A dynamic quantized LSTMCell module with floating point tensor as inputs and outputs.
    Weights are quantized to 8 bits. We adopt the same interface as `torch.nn.LSTMCell`,
    please see https://pytorch.org/docs/stable/nn.html#torch.nn.LSTMCell for documentation.

    Examples::

        >>> rnn = nn.LSTMCell(10, 20)
        >>> input = torch.randn(6, 3, 10)
        >>> hx = torch.randn(3, 20)
        >>> cx = torch.randn(3, 20)
        >>> output = []
        >>> for i in range(6):
        ...     hx, cx = rnn(input[i], (hx, cx))
        ...     output.append(hx)
    c                    s   t t| j|ddi| d S )Nr   r@   )r*   r   r+   r   r.   r   r   r+     s    zLSTMCell.__init__c                 C   s   dS )NZDynamicQuantizedLSTMCellr   rg   r   r   r   rh     s    zLSTMCell._get_nameNr   c                 C   s|   |  | |d kr8tj|d| j|j|jd}||f}| ||d d | ||d d tjj	
||| j| j| j| jS )Nr   r   z[0]r   z[1])r   r    r   r   rE   r(   r   r   r"   r#   Zquantized_lstm_cell_dynamicr   r   r   r   )r-   r|   r   r   r   r   r   r     s    
   zLSTMCell.forwardc                    s   t t| |S r   )r*   r   r   r   r.   r   r   r     s    zLSTMCell.from_float)N)r;   r<   r=   r   r+   rh   r   r   r   r   r   r   r>   r   r   r.   r   r     s   (c                       sX   e Zd ZdZdejf fdd	Zdd Zdee	e edd	d
Z
e fddZ  ZS )r   a7  A gated recurrent unit (GRU) cell

    A dynamic quantized GRUCell module with floating point tensor as inputs and outputs.
    Weights are quantized to 8 bits. We adopt the same interface as `torch.nn.GRUCell`,
    please see https://pytorch.org/docs/stable/nn.html#torch.nn.GRUCell for documentation.

    Examples::

        >>> rnn = nn.GRUCell(10, 20)
        >>> input = torch.randn(6, 3, 10)
        >>> hx = torch.randn(3, 20)
        >>> output = []
        >>> for i in range(6):
        ...     hx = rnn(input[i], hx)
        ...     output.append(hx)
    Tc                    s   t t| j|||d|d d S )NrA   r  )r*   r   r+   )r-   rD   rE   r'   r(   r.   r   r   r+     s    zGRUCell.__init__c                 C   s   dS )NZDynamicQuantizedGRUCellr   rg   r   r   r   rh     s    zGRUCell._get_nameNr   c                 C   s^   |  | |d kr0tj|d| j|j|jd}| ||d tjj	
||| j| j| j| jS )Nr   r   r   )r   r    r   r   rE   r(   r   r   r"   r#   Zquantized_gru_cell_dynamicr   r   r   r   r   r   r   r   r     s    
   zGRUCell.forwardc                    s   t t| |S r   )r*   r   r   r   r.   r   r   r     s    zGRUCell.from_float)N)r;   r<   r=   r   r    r!   r+   rh   r   r   r   r   r   r>   r   r   r.   r   r     s   )r   )r   )rN   r   r    Ztorch.nnrZ   r   Ztorch._jit_internalr   r   r   r   r   Ztorch.nn.utils.rnnr   Z#torch.ao.nn.quantized.modules.utilsr	   __all__r   r   r   r
   Moduler   r   r   r   r   r   r   r   r   r   r   r   <module>   s4     D  V G3)