def calculate_qparams(self):
        """
        Compute the quantization parameters using the min_val and max_val buffers.
        Return the scale and zero-point quantization parameters.
        """

        if self.synchronize:
            self.min_val.data = _sync_tensor(self.min_val, _torch.distributed.ReduceOp.MIN).data
            self.max_val.data = _sync_tensor(self.max_val, _torch.distributed.ReduceOp.MAX).data

        scale, zero_point = self._calculate_qparams(self.min_val, self.max_val)

        if self.synchronize:
            scale.data = _sync_tensor(scale).data
            zero_point.data = _sync_tensor(zero_point).data

        # scale and zero-point are required to be 1-dimensional for export
        if self.ch_axis != -1:
            scale = _torch.squeeze(scale)
            zero_point = _torch.squeeze(zero_point)

        # See https://pytorch.org/docs/stable/generated/torch.ao.quantization.observer.MinMaxObserver.html
        # for information on how scale and zp are computed in PyTorch
        if _is_symmetric_quant(self.qscheme):
            if self.dtype == _torch.quint8 and not self.has_customized_qrange:
                zero_point.data.fill_(128.0)
            elif self.dtype == _torch.quint8:
                assert self.has_customized_qrange
                zero_point.data.fill_(float((self.quant_min + self.quant_max) // 2))
            else:
                assert self.dtype == _torch.qint8
                zero_point.data.zero_()
        else:
            zero_point.data.round_().clamp_(self.quant_min, self.quant_max)
            zero_point.data = zero_point.float().data

        zero_point = zero_point.int()

        return scale, zero_point

        Compute the quantization parameters using the min_val and max_val buffers.
        Return the scale and zero-point quantization parameters.
        
coremltools/optimize/torch/quantization/modules/observers.py