code: def test_quant_act(self):
      def _test_range():
          act = QuantAct(
              activation_bit, act_range_momentum, quant_mode=True
          )
  
          # First pass
          x = torch.tensor(
              [[-1.0, -2.0, -3.0, -4.0], [5.0, 6.0, 7.0, 8.0]]
          )
          x_scaling_factor = torch.tensor(1.0)
          y, y_scaling_factor = act(x, x_scaling_factor)
          y_int = y / y_scaling_factor
  
          # After the first pass, x_min and x_max should be initialized with x.min() and x.max()
          expected_x_min, expected_x_max = x.min(), x.max()
          self.assertTrue(
              torch.allclose(act.x_min, expected_x_min, atol=1e-4)
          )
          self.assertTrue(
              torch.allclose(act.x_max, expected_x_max, atol=1e-4)
          )
  
          # scaling factor should follow the symmetric quantization rule
          expected_range = torch.max(
              expected_x_min.abs(), expected_x_max.abs()
          )
          expected_scaling_factor = expected_range / (
              2 ** (activation_bit - 1) - 1
          )
          self.assertTrue(
              torch.allclose(
                  y_scaling_factor, expected_scaling_factor, atol=1e-4
              )
          )
  
          # quantization error should not exceed the scaling factor
          self.assertTrue(
              torch.allclose(x, y, atol=expected_scaling_factor)
          )
  
          # output should be integer
          self.assertTrue(
              torch.allclose(y_int, y_int.round(), atol=1e-4)
          )
  
          # Second Pass
          x = (
              torch.tensor(
                  [[-1.0, -2.0, -3.0, -4.0], [5.0, 6.0, 7.0, 8.0]]
              )
              * 2
          )
          x_scaling_factor = torch.tensor(1.0)
          y, y_scaling_factor = act(x, x_scaling_factor)
          y_int = y / y_scaling_factor
  
          # From the second pass, x_min and x_max should be updated with moving average
          expected_x_min = (
              expected_x_min * act_range_momentum
              + x.min() * (1 - act_range_momentum)
          )
          expected_x_max = (
              expected_x_max * act_range_momentum
              + x.max() * (1 - act_range_momentum)
          )
          self.assertTrue(
              torch.allclose(act.x_min, expected_x_min, atol=1e-4)
          )
          self.assertTrue(
              torch.allclose(act.x_max, expected_x_max, atol=1e-4)
          )
  
          # scaling factor should follow the symmetric quantization rule
          expected_range = torch.max(
              expected_x_min.abs(), expected_x_max.abs()
          )
          expected_scaling_factor = expected_range / (
              2 ** (activation_bit - 1) - 1
          )
          self.assertTrue(
              torch.allclose(
                  y_scaling_factor, expected_scaling_factor, atol=1e-4
              )
          )
  
          # quantization error should not exceed the scaling factor
          x = x.clamp(min=-expected_range, max=expected_range)
          self.assertTrue(
              torch.allclose(x, y, atol=expected_scaling_factor)
          )
  
          # output should be integer
          self.assertTrue(
              torch.allclose(y_int, y_int.round(), atol=1e-4)
          )
  
          # Third pass, with eval()
          act.eval()
          x = (
              torch.tensor(
                  [[-1.0, -2.0, -3.0, -4.0], [5.0, 6.0, 7.0, 8.0]]
              )
              * 3
          )
  
          # In eval mode, min/max and scaling factor must be fixed
          self.assertTrue(
              torch.allclose(act.x_min, expected_x_min, atol=1e-4)
          )
          self.assertTrue(
              torch.allclose(act.x_max, expected_x_max, atol=1e-4)
          )
          self.assertTrue(
              torch.allclose(
                  y_scaling_factor, expected_scaling_factor, atol=1e-4
              )
          )
  
      def _test_identity():
          # test if identity and identity_scaling_factor are given
          # should add the input values
          act = QuantAct(
              activation_bit, act_range_momentum, quant_mode=True
          )
          x = torch.tensor(
              [[-1.0, -2.0, -3.0, -4.0], [5.0, 6.0, 7.0, 8.0]]
          )
          y = torch.tensor(
              [[6.0, -7.0, 1.0, -2.0], [3.0, -4.0, -8.0, 5.0]]
          )
          x_scaling_factor = torch.tensor(1.0)
          y_scaling_factor = torch.tensor(0.5)
          z, z_scaling_factor = act(
              x, x_scaling_factor, y, y_scaling_factor
          )
          z_int = z / z_scaling_factor
          self.assertTrue(torch.allclose(x + y, z, atol=0.1))
          self.assertTrue(
              torch.allclose(z_int, z_int.round(), atol=1e-4)
          )
  
      activation_bit = 8
      act_range_momentum = 0.95
      _test_range()
      _test_identity()
  
imports: import copy
  import unittest
  from transformers import IBertConfig, is_torch_available
  from transformers.testing_utils import require_torch, slow, torch_device
  from ...test_configuration_common import ConfigTester
  from ...test_modeling_common import ModelTesterMixin, ids_tensor, random_attention_mask
label_desc: Use image node_id 2 for calling the IBertModelIntegrationTest obj's underlying member method code with example usage: obj.test_quant_act() without return types