docs: def check_packed_data(self, ds):
          """
          8.1 Simple packing may be achieved through the use of the optional NUG defined attributes scale_factor and
          add_offset. After the data values of a variable have been read, they are to be multiplied by the scale_factor,
          and have add_offset added to them.
  
          The units of a variable should be representative of the unpacked data.
  
          If the scale_factor and add_offset attributes are of the same data type as the associated variable, the unpacked
          data is assumed to be of the same data type as the packed data. However, if the scale_factor and add_offset
          attributes are of a different data type from the variable (containing the packed data) then the unpacked data
          should match the type of these attributes, which must both be of type float or both be of type double. An additional
          restriction in this case is that the variable containing the packed data must be of type byte, short or int. It is
          not advised to unpack an int into a float as there is a potential precision loss.
  
          When data to be packed contains missing values the attributes that indicate missing values (_FillValue, valid_min,
          valid_max, valid_range) must be of the same data type as the packed data.
  
          :param netCDF4.Dataset ds: An open netCDF dataset
          :rtype: list
          :return: List of results
          """
          ret_val = []
          for name, var in ds.variables.items():
  
              add_offset = getattr(var, 'add_offset', None)
              scale_factor = getattr(var, 'scale_factor', None)
              if not (add_offset or scale_factor):
                  continue
  
              valid = True
              reasoning = []
  
              # if only one of these attributes is defined, assume they
              # are the same type (value doesn't matter here)
              if not add_offset:
                  add_offset = scale_factor
              if not scale_factor:
                  scale_factor = add_offset
  
              if type(add_offset) != type(scale_factor):
                  valid = False
                  reasoning.append("Attributes add_offset and scale_factor have different data type.")
              elif type(scale_factor) != var.dtype.type:
                  # Check both attributes are type float or double
                  if not isinstance(scale_factor, (float, np.floating)):
                      valid = False
                      reasoning.append("Attributes add_offset and scale_factor are not of type float or double.")
                  else:
                      # Check variable type is byte, short or int
                      if var.dtype.type not in [np.int, np.int8, np.int16, np.int32, np.int64]:
                          valid = False
                          reasoning.append("Variable is not of type byte, short, or int.")
  
              result = Result(BaseCheck.MEDIUM, valid, self.section_titles['8.1'], reasoning)
              ret_val.append(result)
              reasoning = []
  
              valid = True
              # test further with  _FillValue , valid_min , valid_max , valid_range
              if hasattr(var, "_FillValue"):
                  if var._FillValue.dtype.type != var.dtype.type:
                      valid = False
                      reasoning.append("Type of %s:_FillValue attribute (%s) does not match variable type (%s)" %
                                       (name, var._FillValue.dtype.type, var.dtype.type))
              if hasattr(var, "valid_min"):
                  if var.valid_min.dtype.type != var.dtype.type:
                      valid = False
                      reasoning.append("Type of %svalid_min attribute (%s) does not match variable type (%s)" %
                                       (name, var.valid_min.dtype.type, var.dtype.type))
              if hasattr(var, "valid_max"):
                  if var.valid_max.dtype.type != var.dtype.type:
                      valid = False
                      reasoning.append("Type of %s:valid_max attribute (%s) does not match variable type (%s)" %
                                       (name, var.valid_max.dtype.type, var.dtype.type))
              if hasattr(var, "valid_range"):
                  if var.valid_range.dtype.type != var.dtype.type:
                      valid = False
                      reasoning.append("Type of %s:valid_range attribute (%s) does not match variable type (%s)" %
                                       (name, var.valid_range.dtype.type, var.dtype.type))
  
              result = Result(BaseCheck.MEDIUM,
                              valid,
                              self.section_titles['8.1'],
                              reasoning)
              ret_val.append(result)
  
          return ret_val