def _analyse_operator(operator, param_name='operator'):
  """Checks the properties of an operator and extracts the number of qubits.

  Args:
    operator: the operator to be analysed.
    param_name: the parameter name as displayed in potential error messages.

  Returns:
    returns: number of qubits.

  Raises:
      ValueError: if operator does not have a valid shape or if it is not
          unitary.
  """

  if operator.ndim != 2:
    raise ValueError(
        '%s must be a 2D array (found: ndim=%d)'
        %(param_name, operator.ndim)
    )

  rows, cols = operator.shape

  if rows != cols:
    raise ValueError(
        '%s must be a square matrix [found: shape=(%d, %d)]'
        %(param_name, rows, cols)
    )

  num_qubits = rows.bit_length()-1

  if rows != 2 ** num_qubits:
    raise ValueError(
        'dimension of %s must be a power of 2 (found: dim=%d)'
        %(param_name, rows)
    )

  return num_qubits