title: Reproducing arithmetic with pytorch's quantized tensors with numpy operations
body: <p>I would like to know what exact arithmetic operations I have to do to reproduce results of quantized operations in pytorch.</p>
  <p>This is almost duplicate question to:
  <a href="https://stackoverflow.com/questions/68904210/i-want-to-use-numpy-to-simulate-the-inference-process-of-a-quantized-mobilenet-v/70650181#70650181">I want to use Numpy to simulate the inference process of a quantized MobileNet V2 network, but the outcome is different with pytorch realized one</a></p>
  <p>But I would even simplify it with the example of adding two quantized tensors.
  For example for addition of two quantized tensors in Resnet architecture I use nn.quantized.FloatFunctional().</p>
  <pre><code>self.skip_add = nn.quantized.FloatFunctional()
  </code></pre>
  <p>And during inference I can add two tensors via</p>
  <pre><code>out1 = self.skip_add.add(x1, x2)
  </code></pre>
  <p>where x1 and x2 are tensors of torch.Tensor type, quantized with fbgemm backend during post training quantization procedure.</p>
  <p>I expected <code>out2_int = x1.int_repr() + x2.int_repr()</code> should be the same as <code>out1.int_repr()</code> (with probably need of clamping in the needed range).
  However that is not the case.
  Below I dump the example outputs.</p>
  <p>So I wonder how can I  get out1 with integer operations?</p>
  <pre><code>&gt;print(x1)
  </code></pre>
  <blockquote>
  <pre><code>      ...,
        [-0.0596, -0.0496, -0.1390,  ..., -0.0596, -0.0695, -0.0099],
        [-0.0893,  0.0000, -0.0695,  ...,  0.0596, -0.0893, -0.0298],
        [-0.1092,  0.0099,  0.0000,  ..., -0.0397, -0.0794, -0.0199]]]],
     size=(1, 256, 14, 14), dtype=torch.quint8,
     quantization_scheme=torch.per_tensor_affine, scale=0.009925744496285915,
     zero_point=75)
  </code></pre>
  </blockquote>
  <pre><code>print(x2)
  </code></pre>
  <blockquote>
  <pre><code>      ...,
        [ 0.1390, -0.1669, -0.0278,  ..., -0.2225, -0.0556, -0.1112],
        [ 0.0000, -0.1669, -0.0556,  ...,  0.0556,  0.1112, -0.2781],
        [ 0.1390,  0.1669,  0.0278,  ...,  0.2225,  0.4171,  0.0834]]]],
     size=(1, 256, 14, 14), dtype=torch.quint8,
     quantization_scheme=torch.per_tensor_affine, scale=0.02780967578291893,
     zero_point=61)
  </code></pre>
  </blockquote>
  <pre><code>print(x1.int_repr())
  </code></pre>
  <blockquote>
  <pre><code>      ...,
        [69, 70, 61,  ..., 69, 68, 74],
        [66, 75, 68,  ..., 81, 66, 72],
        [64, 76, 75,  ..., 71, 67, 73]]]], dtype=torch.uint8)
  </code></pre>
  </blockquote>
  <pre><code>print(x2.int_repr())
  </code></pre>
  <blockquote>
  <pre><code>      ...,
        [66, 55, 60,  ..., 53, 59, 57],
        [61, 55, 59,  ..., 63, 65, 51],
        [66, 67, 62,  ..., 69, 76, 64]]]], dtype=torch.uint8)
  </code></pre>
  </blockquote>
  <p>print(out1)</p>
  <blockquote>
  <pre><code>      ...,
        [ 0.0904, -0.2109, -0.1808,  ..., -0.2712, -0.1205, -0.1205],
        [-0.0904, -0.1808, -0.1205,  ...,  0.1205,  0.0301, -0.3013],
        [ 0.0301,  0.1808,  0.0301,  ...,  0.1808,  0.3314,  0.0603]]]],
     size=(1, 256, 14, 14), dtype=torch.quint8,
     quantization_scheme=torch.per_tensor_affine, scale=0.03012925386428833,
     zero_point=56)
  </code></pre>
  </blockquote>
  <pre><code>print(out1.int_repr())
  </code></pre>
  <blockquote>
  <pre><code>      ...,
        [59, 49, 50,  ..., 47, 52, 52],
        [53, 50, 52,  ..., 60, 57, 46],
        [57, 62, 57,  ..., 62, 67, 58]]]], dtype=torch.uint8)
  </code></pre>
  </blockquote>
  <pre><code> print(out2_int)
  </code></pre>
  <blockquote>
  <pre><code>      [135, 125, 121,  ..., 122, 127, 131],
        [127, 130, 127,  ..., 144, 131, 123],
        [130, 143, 137,  ..., 140, 143, 137]]]], dtype=torch.uint8)
  </code></pre>
  </blockquote>