U
    d0                     @   s   d dl mZ d dlZd dlmZ d dlm  mZ d dlm  m  m	Z
 d dlmZmZmZ d dlmZ d dlmZ d dlmZ G dd dejjZG d	d
 d
eZdS )    )IterableN)_quantize_weighthide_packed_params_reprWeightedQuantizedModule)fuse_linear_bn_weights)type_before_parametrizations)Optionalc                       s   e Zd ZdZejf fdd	Zejjej	e
ej	 ddddZejjdd	 Zd
d Z fddZ fddZdd Z  ZS )LinearPackedParams   c                    sf   t    || _| jtjkr6tjddgddtjd}n | jtjkrVtjddgtjd}| 	|d  d S )N         ?r   scale
zero_pointdtyper   )
super__init__r   torchqint8_empty_affine_quantizedfloat16zerosfloatset_weight_bias)selfr   Zwq	__class__ E/tmp/pip-unpacked-wheel-ua33x9lu/torch/nn/quantized/modules/linear.pyr      s    
zLinearPackedParams.__init__N)weightbiasreturnc                 C   sL   | j tjkr tjj||| _n(| j tjkr@tjj||| _nt	dd S Nz.Unsupported dtype on dynamic quantized linear!)
r   r   r   ops	quantizedZlinear_prepack_packed_paramsr   Zlinear_prepack_fp16RuntimeError)r   r    r!   r   r   r   r      s
    z"LinearPackedParams.set_weight_biasc                 C   sD   | j tjkrtjj| jS | j tjkr8tjj| jS t	dd S r#   )
r   r   r   r$   r%   Zlinear_unpackr&   r   Zlinear_unpack_fp16r'   r   r   r   r   _weight_bias"   s
    zLinearPackedParams._weight_biasc                 C   s   |S Nr   r   xr   r   r   forward+   s    zLinearPackedParams.forwardc                    s6   t t| ||| | j||d < |  ||d < d S )Nr   r&   )r   r	   _save_to_state_dictr   r)   r   ZdestinationprefixZ	keep_varsr   r   r   r.   >   s    z&LinearPackedParams._save_to_state_dictc              	      s   | dd }|d ks|dk r&tj| _n||d  | _||d  |d ksR|dk r| ||d  ||d   ||d  ||d  |dkr||d  \}	}
||d  | |	|
 tt| |||d||| d S )	Nversion   r   r
   r    r!   r&   F)	getr   r   r   popr   r   r	   _load_from_state_dictr   Z
state_dictr0   Zlocal_metadatastrictZmissing_keysZunexpected_keysZ
error_msgsr1   r    r!   r   r   r   r5   C   s$    
  z(LinearPackedParams._load_from_state_dictc                 C   s   |    S r*   )r)   __repr__r(   r   r   r   r8   Z   s    zLinearPackedParams.__repr__)__name__
__module____qualname___versionr   r   r   ZjitexportTensorr   r   r)   r-   r.   r5   r8   __classcell__r   r   r   r   r	      s   		
r	   c                       s   e Zd ZdZdZejejjj	fZ
dejf fdd	Zdd Zdd	 Zd
d ZejejdddZ fddZ fddZdd Zdd Zdd Zejeej ddddZedd Zedd  Z  ZS )!Lineara  
    A quantized linear module with quantized tensor as inputs and outputs.
    We adopt the same interface as `torch.nn.Linear`, please see
    https://pytorch.org/docs/stable/nn.html#torch.nn.Linear for documentation.

    Similar to :class:`~torch.nn.Linear`, attributes will be randomly
    initialized at module creation time and will be overwritten later

    Attributes:
        weight (Tensor): the non-learnable quantized weights of the module of
                         shape :math:`(\text{out\_features}, \text{in\_features})`.
        bias (Tensor): the non-learnable bias of the module of shape :math:`(\text{out\_features})`.
                If :attr:`bias` is ``True``, the values are initialized to zero.
        scale: `scale` parameter of output Quantized Tensor, type: double
        zero_point: `zero_point` parameter for output Quantized Tensor, type: long

    Examples::

        >>> m = nn.quantized.Linear(20, 30)
        >>> input = torch.randn(128, 20)
        >>> input = torch.quantize_per_tensor(input, 1.0, 0, torch.quint8)
        >>> output = m(input)
        >>> print(output.size())
        torch.Size([128, 30])
    r
   Tc                    s   t    || _|| _d }|r.tj|tjd}|tjkrRtj||gddtjd}n(|tj	krrtj||gtjd}nt
dt|| _| j|| d| _d| _d S )Nr   r   r   r   z1Unsupported dtype specified for quantized Linear!r   )r   r   in_featuresout_featuresr   r   r   r   r   r   r'   r	   r&   r   r   r   )r   rA   rB   Zbias_r   r!   qweightr   r   r   r   {   s(    

   

zLinear.__init__c                 C   s   dS )NZQuantizedLinearr   r(   r   r   r   	_get_name   s    zLinear._get_namec                 C   s"   d | j| j| j| j|   S )NzDin_features={}, out_features={}, scale={}, zero_point={}, qscheme={})formatrA   rB   r   r   r    Zqschemer(   r   r   r   
extra_repr   s        
zLinear.extra_reprc                 C   s
   t | tS r*   )r   r	   r(   r   r   r   r8      s    zLinear.__repr__)r,   r"   c                 C   s   t jj|| jj| j| jS r*   )r   r$   r%   linearr&   r   r   r+   r   r   r   r-      s       zLinear.forwardc                    s<   t  ||| t| j||d < t| j||d < d S )Nr   r   )r   r.   r   Ztensorr   r   r/   r   r   r   r.      s    zLinear._save_to_state_dictc              	      s   t ||d  | _||d  t||d  | _||d  |dd }|d ks\|dkr||d }	||d }
||d |	|d |
i t |||d	||| d S )
Nr   r   r1   r   r    r!   z_packed_params.weightz_packed_params.biasF)	r   r   r4   intr   r3   updater   r5   r6   r   r   r   r5      s*          zLinear._load_from_state_dictc                 C   s
   | j  S r*   )r&   r)   r(   r   r   r   r)      s    zLinear._weight_biasc                 C   s   |   d S )Nr   r)   r(   r   r   r   r       s    zLinear.weightc                 C   s   |   d S )Nr   rJ   r(   r   r   r   r!      s    zLinear.biasN)wbr"   c                 C   s   | j || d S r*   )r&   r   )r   rK   rL   r   r   r   r      s    zLinear.set_weight_biasc                 C   sd  t |drZt|tjkrLt|j|j|jj|jj	|jj
|jj|jj\|_|_|j}|j}nt| jtsp| jg| _ddd | jD }d| j|t|}t|| jkst| t |dstd|j}t|tjkr|d }|j }||j |j}| \}}|tjkstd	t|j |}	| |j|j|d
}
|
 |	|j t||
_!t"||
_#|
S )zCreate a quantized module from an observed float module

        Args:
            mod (Module): a float module, either produced by torch.ao.quantization
                          utilities or provided by the user
        weight_fake_quantz, c                 S   s   g | ]
}|j qS r   )r9   ).0Z	float_modr   r   r   
<listcomp>  s     z%Linear.from_float.<locals>.<listcomp>z0nnq.{}.from_float only works for {}, but got: {}qconfigz,Input float module must have qconfig definedr   z+Weight observer must have dtype torch.qint8r   )$hasattrr   nniqatZ
LinearBn1dr   r    r!   ZbnZrunning_meanZrunning_varZepsrM   activation_post_process
isinstance_FLOAT_MODULEr   joinrE   r9   typeAssertionErrornniZ
LinearReLUrP   r   Zcalculate_qparamsr   r   r   r   rA   rB   r   r   rH   r   )clsmodZweight_post_processrS   Zsupported_modules	error_msgr   Z	act_scaleZact_zprC   qlinearr   r   r   
from_float   sH    
     




zLinear.from_floatc                 C   s<   | |j |j}| }|||j t||_t||_|S )a  Create a (fbgemm/qnnpack) quantized module from a reference quantized module

        Args:
            ref_qlinear (Module): a reference quantized linear module, either produced by torch.ao.quantization
                          utilities or provided by the user
            output_scale (float): scale for output Tensor
            zero_point (int): zero point for output Tensor
        )	rA   rB   Zget_quantized_weightr   r!   r   r   rH   r   )rZ   Zref_qlinearZoutput_scaleZoutput_zero_pointr]   rC   r   r   r   from_reference  s    


zLinear.from_reference)r9   r:   r;   __doc__r<   nnr@   modulesrG   ZNonDynamicallyQuantizableLinearrU   r   r   r   rD   rF   r8   r>   r-   r.   r5   r)   r    r!   r   r   classmethodr^   r_   r?   r   r   r   r   r@   ^   s(   !
)r@   )collections.abcr   r   Ztorch.nnra   Ztorch.nn.intrinsicZ	intrinsicrY   Ztorch.nn.intrinsic.qatZqatrR   Z torch.nn.quantized.modules.utilsr   r   r   Ztorch.nn.utils.fusionr   Ztorch.nn.utils.parametrizer   typingr   Moduler	   r@   r   r   r   r   <module>   s   R