U
    KcQ                     @   s  d dl Z d dlmZ d dl mZ ddlmZ ddlmZ d dl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gZdeeeedddZdd Zdd Zdd ZG dd	 d	ejZG dd
 d
eZG dd deZG dd deZG dd dejZG dd deZdS )    N)Tensor   )_quantize_and_dequantize_weight)_quantize_weight)OptionalDictAnyTuple)_VF)PackedSequenceRNNCellBaseRNNCellLSTMCellGRUCellRNNBaseLSTMget_quantized_weight)tensorpermutationdimreturnc                 C   s   |  ||S N)Zindex_select)r   r   r    r   O/tmp/pip-unpacked-wheel-gikjz4vx/torch/ao/nn/quantized/reference/modules/rnn.py_apply_permutation   s    r   c                    sP   t |  }|g} fdddD D ](}t| |r<t | |}nd }|| q"|S )Nc                    s   g | ]} | qS r   r   ).0nwnr   r   
<listcomp>   s     z7_get_weight_and_quantization_params.<locals>.<listcomp>)_qscheme_dtype_scale_zero_point_axis)getattrhasattrappend)moduler   weightparams
param_nameparamr   r   r   #_get_weight_and_quantization_params   s    

r-   c                 C   s$   t | |sd S t| |}t| }|S r   )r&   r-   r   r(   r   r*   r)   r   r   r   r      s
    

c                 C   s$   t | |sd S t| |}t| }|S r   )r&   r-   r   r.   r   r   r   $_get_quantize_and_dequantized_weight!   s
    

r/   c                       s\   e Zd Zdeeeedd fddZdd Zdd Zd	d
 Zdd Z	dd Z
dd Z  ZS )r   N)
input_sizehidden_sizebias
num_chunksr   c           	         s`   t  j||||||d |d kr<tjtjddd}||d}t|dksPtd| || d S )N)devicedtype      ?r   qschemer5   scale
zero_point)	weight_ih	weight_hh   zSExpected length for weight_qparams_dict to be 2 for QuantizedRNNCellBase(Reference))super__init__torchper_tensor_affinequint8lenAssertionError_init_weight_qparams_dict)	selfr0   r1   r2   r3   r4   r5   weight_qparams_dictweight_qparams	__class__r   r   r?   )   s    zRNNCellBase.__init__c              	   C   s~  |d k	st | D ]b\}}|d }|d }t| |d | t| |d | |d tjtjfks|t td| d|   |d k	r|d }t|tj	r|
  ntj|tj|d}| |d	 | |d
 }	t|	tj	r|	
  ntj|	tj|d}
| |d |
 |tjkrZ|d }t|tj	r6|
  ntj|tj|d}| |d | q| |d tjdtj|d qd S )Nr8   r5   r    r!   	qscheme:  is not support in r9   r5   r4   r"   r:   r#   axisr$   r   )rD   itemssetattrr@   rA   per_channel_affine	Exception	_get_name
isinstancer   clonedetachr   floatregister_bufferint)rF   rG   r4   keyrH   weight_qschemeweight_dtyper9   Zscale_tensorZzpZ	zp_tensorrN   Zaxis_tensorr   r   r   rE   :   sB    


 z%RNNCellBase._init_weight_qparams_dictc                 C   s   dS )NzQuantizedRNNCellBase(Reference)r   rF   r   r   r   rS   Z   s    zRNNCellBase._get_namec                 C   s
   t | dS Nr;   r   r]   r   r   r   get_quantized_weight_ih]   s    z#RNNCellBase.get_quantized_weight_ihc                 C   s
   t | dS Nr<   r_   r]   r   r   r   get_quantized_weight_hh`   s    z#RNNCellBase.get_quantized_weight_hhc                 C   s
   t | dS r^   r/   r]   r   r   r   get_weight_ihc   s    zRNNCellBase.get_weight_ihc                 C   s
   t | dS ra   rc   r]   r   r   r   get_weight_hhf   s    zRNNCellBase.get_weight_hh)NNN)__name__
__module____qualname__rY   boolr?   rE   rS   r`   rb   rd   re   __classcell__r   r   rI   r   r   (   s        
 c                       sr   e Zd ZdZdeeeeeeeeee	f f  dd fddZ
dd	 Zdeee ed
ddZedd Z  ZS )r   
    We'll store weight_qparams for all the weights (weight_ih and weight_hh),
    we need to pass in a `weight_qparams_dict` that maps from weight name,
    e.g. weight_ih, to the weight_qparams for that weight
    TtanhN)r0   r1   r2   nonlinearityrG   r   c           	         s2   |||d}t  j|||fddi| || _d S )Nr4   r5   rG   r3   r   )r>   r?   rm   )	rF   r0   r1   r2   rm   r4   r5   rG   factory_kwargsrI   r   r   r?   o   s    zRNNCell.__init__c                 C   s   dS )NzQuantizedRNNCell(Reference)r   r]   r   r   r   rS   u   s    zRNNCell._get_nameinputhxr   c                 C   s   |  dks td|   d|  dk}|s:|d}|d krbtj|d| j|j|jd}n|sp|dn|}| j	dkrt
|||  |  | j| j}n@| j	dkrt
|||  |  | j| j}n|}td	| j	|s|d}|S )
Nr   r=   z6RNNCell: Expected input to be 1-D or 2-D but received 	-D tensorr=   r   rM   rl   ZreluzUnknown nonlinearity: {})r   rD   	unsqueezer@   zerossizer1   r5   r4   rm   r
   Zrnn_tanh_cellrd   re   bias_ihbias_hhZrnn_relu_cellRuntimeErrorformatsqueezerF   rq   rr   
is_batchedretr   r   r   forwardz   sD    
 
   
   

zRNNCell.forwardc                 C   sH   | |j |j|j|j|jj|jj|}|j|_|j|_|j|_|j	|_	|S r   )
r0   r1   r2   rm   r;   r4   r5   r<   rx   ry   clsmodrG   ref_modr   r   r   
from_float   s    zRNNCell.from_float)Trl   NNN)N)rf   rg   rh   __doc__rY   ri   strr   r   r   r?   rS   r   r   classmethodr   rj   r   r   rI   r   r   i   s         
 "c                
       s   e Zd ZdZdeeeeeeeee	f f  dd fddZ
dd Zdeeeeef  eeef d	d
dZedd Z  ZS )r   rk   TNr0   r1   r2   rG   r   c                    s,   |||d}t  j|||fddi| d S )Nrn   r3      r>   r?   rF   r0   r1   r2   r4   r5   rG   ro   rI   r   r   r?      s    zLSTMCell.__init__c                 C   s   dS )NzQuantizedLSTMCell(Reference)r   r]   r   r   r   rS      s    zLSTMCell._get_namerp   c                 C   s   |  dks td|   d|  dk}|s:|d}|d krjtj|d| j|j|jd}||f}n$|s|d d|d dfn|}t	
|||  |  | j| j}|s|d d|d df}|S )Nrs   z7LSTMCell: Expected input to be 1-D or 2-D but received rt   r=   r   rM   r   )r   rD   ru   r@   rv   rw   r1   r5   r4   r
   Z	lstm_cellrd   re   rx   ry   r|   )rF   rq   rr   r~   rv   r   r   r   r   r      s*    

$   zLSTMCell.forwardc                 C   sD   | |j |j|j|jj|jj|}|j|_|j|_|j|_|j|_|S r   	r0   r1   r2   r;   r4   r5   r<   rx   ry   r   r   r   r   r      s    zLSTMCell.from_float)TNNN)N)rf   rg   rh   r   rY   ri   r   r   r   r   r?   rS   r   r	   r   r   r   rj   r   r   rI   r   r      s          (c                
       sp   e Zd ZdZdeeeeeeeee	f f  dd fddZ
dd Zdeee ed	d
dZedd Z  ZS )r   rk   TNr   c                    s,   |||d}t  j|||fddi| d S )Nrn   r3      r   r   rI   r   r   r?      s    zGRUCell.__init__c                 C   s   dS )NzQuantizedGRUCell(Reference)r   r]   r   r   r   rS      s    zGRUCell._get_namerp   c                 C   s   |  dks td|   d|  dk}|s:|d}|d krbtj|d| j|j|jd}n|sp|dn|}t	
|||  |  | j| j}|s|d}|S )Nrs   z6GRUCell: Expected input to be 1-D or 2-D but received rt   r=   r   rM   )r   rD   ru   r@   rv   rw   r1   r5   r4   r
   Zgru_cellrd   re   rx   ry   r|   r}   r   r   r   r      s(    
    
zGRUCell.forwardc                 C   sD   | |j |j|j|jj|jj|}|j|_|j|_|j|_|j|_|S r   r   r   r   r   r   r     s    zGRUCell.from_float)TNNN)N)rf   rg   rh   r   rY   ri   r   r   r   r   r?   rS   r   r   r   r   rj   r   r   rI   r   r      s          c                       sT   e Zd Zdeeeeeeeeeeeeeee	f f  dd fdd	Z
d
d Z  ZS )r   r   TF        r   N)moder0   r1   
num_layersr2   batch_firstdropoutbidirectional	proj_sizerG   r   c                    sl   t  |||||||||	|
| |d kr\tjtjddd}i }| jD ]}|drD|||< qD| ||
 d S )Nr6   r   r7   r)   )r>   r?   r@   rA   rB   _flat_weights_names
startswithrE   )rF   r   r0   r1   r   r2   r   r   r   r   r4   r5   rG   rH   r   rI   r   r   r?     s0             


zRNNBase.__init__c              	   C   s  |  D  ]\}}|d }|d }t| |d | t| |d | |d tjtjfkspttd| d|   |d k	r| |d tj	|d tj
|d	 | |d
 tj	|d tj|d	 |tjkr| |d tj	|d tj|d	 q| |d tj	dtj|d	 qd S )Nr8   r5   r    r!   rK   rL   r"   r9   rM   r#   r:   r$   rN   r   )rO   rP   r@   rA   rQ   rD   rR   rS   rX   r   rW   rY   )rF   rG   r4   rZ   rH   r[   r\   r   r   r   rE   +  s4    
 z!RNNBase._init_weight_qparams_dict)	r   TFr   Fr   NNN)rf   rg   rh   r   rY   ri   rW   r   r   r   r?   rE   rj   r   r   rI   r   r     s(                      c                       s   e Zd ZdZ fddZeeef ee eeef dddZeee ee	e	e	f ddd	Z
eeeef ee d
ddZdd Zdd ZdddZdd Zedd Z  ZS )r   z Reference Quantized LSTM Module
    We'll store weight_qparams for all the weights in _flat_weights, we need to pass in
    a `weight_qparams_dict` that maps from weight name, e.g. weight_ih_l0,
    to the weight_qparams for that weight
    c                    s   t  jd|| d S )Nr   )r   r   )rF   argskwargsrI   r   r   r?   I  s    zLSTM.__init__)rr   r   r   c                 C   s(   |d kr|S t |d |t |d |fS )Nr   r   )r   )rF   rr   r   r   r   r   permute_hiddenM  s    zLSTM.permute_hidden)rq   batch_sizesr   c                 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=   )rY   r   rw   r   r   r1   )rF   rq   r   Z
mini_batchnum_directionsZexpected_hidden_sizer   r   r   get_expected_cell_sizeU  s     zLSTM.get_expected_cell_size)rq   hiddenr   c                 C   sD   |  || | |d | ||d | |d | ||d d S )Nr   z"Expected hidden[0] size {}, got {}r   z"Expected hidden[1] size {}, got {})Zcheck_inputZcheck_hidden_sizeZget_expected_hidden_sizer   )rF   rq   r   r   r   r   r   check_forward_argsa  s    zLSTM.check_forward_argsc                 C   sL   i }| j D ]<}t| |r:|dr.t| |}q>t| |}nd}|||< q
|S )z dictionary from flat_weight_name to quantized weight or (unquantized) bias
        e.g.
        {
          "weight_ih_l0": quantized_weight,
          "bias_ih_l0": unquantized_bias,
          ...
        }
        r)   N)r   r&   r   r   r%   )rF   Zquantized_weight_bias_dictr   Zweight_or_biasr   r   r   get_quantized_weight_bias_dictl  s    	



z#LSTM.get_quantized_weight_bias_dictc                 C   sT   g }| j D ]D}t| |r@t| |}|drDt| |}t| }nd }|| q
|S )Nr)   )r   r&   r%   r   r-   r   r'   )rF   Zflat_weightsr   r)   r*   r   r   r   get_flat_weights  s    





zLSTM.get_flat_weightsNc                 C   s  |}d }t |tr0|\}}}}|d }t|}nNd }| dk}| jrJdnd}	|s\||	}| jrl|dn|d}d }d }|d kr| jrdnd}
| jdkr| jn| j	}t
j| j|
 |||j|jd}t
j| j|
 || j	|j|jd}||f}n|d kr|rR|d  dks&|d  dkrd|d   d|d   d}t|nj|d  dksv|d  dkrd	|d   d|d   d}t||d d|d df}| ||}| ||| |d krt|||  | j| j| j| j| j| j	}n(t||||  | j| j| j| j| j	}|d }|dd  }t |trrt||||}|| ||fS |s||	}|d d|d df}|| ||fS d S )
Nr   r   r   r=   rM   z=For batched 3-D input, hx and cx should also be 3-D but got (z-D, z-D) tensorsz?For unbatched 2-D input, hx and cx should also be 2-D but got ()rT   r   rY   r   r   ru   rw   r   r   r1   r@   rv   r   r5   r4   rz   r   r   r
   Zlstmr   r2   r   Ztrainingr|   )rF   rq   rr   Z
orig_inputr   Zsorted_indicesZunsorted_indicesZmax_batch_sizer~   Z	batch_dimr   Zreal_hidden_sizeZh_zerosZc_zerosmsgresultoutputr   Zoutput_packedr   r   r   r     s~    


    

$"
$"
      
zLSTM.forwardc                 C   s   dS )NzQuantizedLSTM(Reference)r   r]   r   r   r   rS     s    zLSTM._get_namec              
   C   sH   | |j |j|j|j|j|j|j|d}|jD ]}t||t	|| q,|S )N)rG   )
r0   r1   r   r2   r   r   r   r   rP   r%   )r   r   rG   r   r   r   r   r   r     s    	
zLSTM.from_float)N)rf   rg   rh   r   r?   r	   r   r   r   rY   r   r   r   r   r   rS   r   r   rj   r   r   rI   r   r   C  s"   

 

A)r   )r@   Ztorch.nnnnr   utilsr   r   typingr   r   r   r	   r
   Ztorch.nn.utils.rnnr   __all__rY   r   r-   r   r/   r   r   r   r   r   r   r   r   r   r   <module>   s$   AC44/