docs: def _unpack_data(data, prior, svdcut, uncorrelated_data, add_svdnoise):
      """ Unpack data and prior into ``(x, y, prior, fdata)``.
  
      This routine unpacks ``data`` and ``prior`` into ``x, y, prior, fdata``
      where ``x`` is the independent data, ``y`` is the fit data,
      ``prior`` is the collection of priors for the fit, and ``fdata``
      contains the information about the data and prior needed for the
      fit function. Both ``y`` and ``prior`` are modified to account
      for SVD cuts if ``svdcut>0``.
  
      Allowed layouts for ``data`` are: ``x, y, ycov``, ``x, y, ysdev``,
      ``x, y``, and ``y``. In the last two case, ``y`` can be either an array
      of |GVar|\s or a dictionary whose values are |GVar|\s or arrays of
      |GVar|\s. In the last case it is assumed that the fit function is a
      function of only the parameters: ``fcn(p)`` --- no ``x``. (This is also
      assumed if ``x = False``.)
  
      Output data in ``fdata`` is: ``fdata.mean`` containing the mean values of
      ``y.flat`` and ``prior.flat`` (if there is a prior);
      ``fdata.svdcorrection``  containing the sum of the SVD corrections to
      ``y.flat`` and ``prior.flat``; ``fdata.logdet`` containing  the logarithm
      of the  determinant of the covariance matrix of ``y.flat`` and
      ``prior.flat``; and ``fdata.inv_wgts`` containing a representation of the
      inverse of the covariance matrix, after SVD cuts (see :func:`gvar.svd`
      for a description of the format).
      """
      # unpack data tuple
      if not isinstance(data, tuple):
          x = False                   # no x in fit fcn
          y = _unpack_gvars(data)
      elif len(data) == 3:
          x, ym, ycov = data
          ym = numpy.asarray(ym)
          ycov = numpy.asarray(ycov)
          y = _gvar.gvar(ym, ycov)
      elif len(data) == 2:
          x, y = data
          y = _unpack_gvars(y)
      else:
          raise ValueError("data tuple wrong length: "+str(len(data)))
  
      # clean up
      if prior is not None:
          prior = _unpack_gvars(prior)
  
      def _apply_svd(data, svdcut=svdcut):
          ans, inv_wgts = _gvar.svd(
              data, wgts=-1, svdcut=svdcut, add_svdnoise=add_svdnoise,
              )
          fdata = _FDATA(
              mean=_gvar.mean(ans.flat),
              inv_wgts=inv_wgts,
              svdcorrection=numpy.sum(ans.svdcorrection.flat),
              logdet=ans.logdet,
              nblocks=ans.nblocks,
              svdn=ans.nmod,
              )
          del ans.nblocks
          # del ans.svdcorrection
          return ans, fdata
  
      if uncorrelated_data:
          ysdev = _gvar.sdev(y.flat)
          if prior is None:
              pfdata = _FDATA(
                  mean=[], inv_wgts=[([],[])], svdcorrection=_gvar.gvar(0,0),
                  logdet=0.0, nblocks={1:0}, svdn=0,
                  )
          else:
              prior, pfdata = _apply_svd(prior)
          inv_wgts = [(numpy.arange(y.size, dtype=numpy.intp), 1. / ysdev)]
          i, wgt = pfdata.inv_wgts[0]
          if len(i) > 0:
              inv_wgts = [(
                  numpy.concatenate((inv_wgts[0][0], i + y.size)),
                  numpy.concatenate((inv_wgts[0][1], wgt))
                  )]
          for i, wgt in pfdata.inv_wgts[1:]:
              inv_wgts.append((
                  i + y.size, wgt
                  ))
          pfdata.nblocks[1] = pfdata.nblocks.get(1, 0) + y.size
          fdata = _FDATA(
              mean=numpy.concatenate((_gvar.mean(y.flat), pfdata.mean)),
              inv_wgts=inv_wgts,
              svdcorrection=pfdata.svdcorrection,
              logdet=2 * numpy.sum(numpy.log(ysdev)) + pfdata.logdet,
              nblocks=pfdata.nblocks,
              svdn=pfdata.svdn,
              )
      elif prior is None:
          y, fdata = _apply_svd(y)
      else:
          yp, fdata = _apply_svd(numpy.concatenate((y.flat, prior.flat)))
          y.flat = yp[:y.size]
          prior.flat = yp[y.size:]
      return x, y, prior, fdata