def fit_rscale(xy, uv, wxy=None, wuv=None):
    " Fits (non-iteratively and without sigma-clipping) a displacement,\n    rotation and scale transformations between input lists of positions\n    ``xy`` and ``uv``. When weights are provided, a weighted fit is performed.\n    Parameter descriptions and return values are identical to those\n    in `iter_linear_fit`, except returned ``fit`` dictionary does not contain\n    the following keys irrelevant to this function: ``'center'``,\n    ``'fitmask'``, and ``'eff_nclip'``.\n\n    "
    if (len(xy) < 2):
        raise NotEnoughPointsError('At least two points are required to find shifts, rotation, and scale.')
    x = np.array(xy[:, 0], dtype=np.longdouble)
    y = np.array(xy[:, 1], dtype=np.longdouble)
    u = np.array(uv[:, 0], dtype=np.longdouble)
    v = np.array(uv[:, 1], dtype=np.longdouble)
    if ((wxy is None) and (wuv is None)):
        w = None
        xm = np.mean(x)
        ym = np.mean(y)
        um = np.mean(u)
        vm = np.mean(v)
        x -= xm
        y -= ym
        u -= um
        v -= vm
        su2 = np.dot(u, u)
        sv2 = np.dot(v, v)
        sxv = np.dot(x, v)
        syu = np.dot(y, u)
        sxu = np.dot(x, u)
        syv = np.dot(y, v)
        su2v2 = (su2 + sv2)
    else:
        if (wxy is None):
            w = np.array(wuv, dtype=np.longdouble)
        elif (wuv is None):
            w = np.array(wxy, dtype=np.longdouble)
        else:
            wuv = np.array(wuv, dtype=np.longdouble)
            wxy = np.array(wxy, dtype=np.longdouble)
            m = np.logical_and((wuv > 0), (wxy > 0))
            w = np.zeros_like(wuv)
            w[m] = ((wxy[m] * wuv[m]) / (wxy[m] + wuv[m]))
        if np.any((w < 0.0)):
            raise ValueError('Invalid weights: weights must be non-negative.')
        if (np.sum((w > 0)) < 2):
            raise ValueError("Not enough valid data for 'rscale' fit: too many weights are zero!")
        w /= np.sum(w, dtype=np.longdouble)
        xm = np.dot(w, x)
        ym = np.dot(w, y)
        um = np.dot(w, u)
        vm = np.dot(w, v)
        x -= xm
        y -= ym
        u -= um
        v -= vm
        su2 = np.dot(w, (u ** 2))
        sv2 = np.dot(w, (v ** 2))
        sxv = np.dot(w, (x * v))
        syu = np.dot(w, (y * u))
        sxu = np.dot(w, (x * u))
        syv = np.dot(w, (y * v))
        su2v2 = (su2 + sv2)
    det = ((sxu * syv) - (sxv * syu))
    if (det < 0):
        rot_num = (sxv + syu)
        rot_denom = (sxu - syv)
    else:
        rot_num = (sxv - syu)
        rot_denom = (sxu + syv)
    if (rot_num == rot_denom):
        theta = 0.0
    else:
        theta = np.rad2deg(np.arctan2(rot_num, rot_denom))
        if (theta < 0):
            theta += 360.0
    ctheta = np.cos(np.deg2rad(theta))
    stheta = np.sin(np.deg2rad(theta))
    s_num = ((rot_denom * ctheta) + (rot_num * stheta))
    if (su2v2 > 0.0):
        mag = (s_num / su2v2)
    else:
        raise SingularMatrixError('Singular matrix: suspected colinear points.')
    if (det < 0):
        sthetax = ((- mag) * stheta)
        cthetay = ((- mag) * ctheta)
    else:
        sthetax = (mag * stheta)
        cthetay = (mag * ctheta)
    cthetax = (mag * ctheta)
    sthetay = (mag * stheta)
    sdet = np.sign(det)
    xshift = ((xm - (um * cthetax)) - ((sdet * vm) * sthetax))
    yshift = ((ym + ((sdet * um) * sthetay)) - (vm * cthetay))
    p = np.array([cthetax, sthetay, xshift], dtype=np.longdouble)
    q = np.array([(- sthetax), cthetay, yshift], dtype=np.longdouble)
    fit = _build_fit(p, q, fitgeom='rscale')
    resids = ((xy - np.dot(uv, fit['matrix_ld'].T)) - fit['shift_ld'])
    fit['resids'] = resids.astype(np.double)
    _compute_stat(fit, residuals=resids, weights=w)
    return fit
Fits (non-iteratively and without sigma-clipping) a displacement,
rotation and scale transformations between input lists of positions
``xy`` and ``uv``. When weights are provided, a weighted fit is performed.
Parameter descriptions and return values are identical to those
in `iter_linear_fit`, except returned ``fit`` dictionary does not contain
the following keys irrelevant to this function: ``'center'``,
``'fitmask'``, and ``'eff_nclip'``.
def fit_rscale(xy, uv, wxy=None, wuv=None):
    " Fits (non-iteratively and without sigma-clipping) a displacement,\n    rotation and scale transformations between input lists of positions\n    ``xy`` and ``uv``. When weights are provided, a weighted fit is performed.\n    Parameter descriptions and return values are identical to those\n    in `iter_linear_fit`, except returned ``fit`` dictionary does not contain\n    the following keys irrelevant to this function: ``'center'``,\n    ``'fitmask'``, and ``'eff_nclip'``.\n\n    "
    if (len(xy) < 2):
        raise NotEnoughPointsError('At least two points are required to find shifts, rotation, and scale.')
    x = np.array(xy[:, 0], dtype=np.longdouble)
    y = np.array(xy[:, 1], dtype=np.longdouble)
    u = np.array(uv[:, 0], dtype=np.longdouble)
    v = np.array(uv[:, 1], dtype=np.longdouble)
    if ((wxy is None) and (wuv is None)):
        w = None
        xm = np.mean(x)
        ym = np.mean(y)
        um = np.mean(u)
        vm = np.mean(v)
        x -= xm
        y -= ym
        u -= um
        v -= vm
        su2 = np.dot(u, u)
        sv2 = np.dot(v, v)
        sxv = np.dot(x, v)
        syu = np.dot(y, u)
        sxu = np.dot(x, u)
        syv = np.dot(y, v)
        su2v2 = (su2 + sv2)
    else:
        if (wxy is None):
            w = np.array(wuv, dtype=np.longdouble)
        elif (wuv is None):
            w = np.array(wxy, dtype=np.longdouble)
        else:
            wuv = np.array(wuv, dtype=np.longdouble)
            wxy = np.array(wxy, dtype=np.longdouble)
            m = np.logical_and((wuv > 0), (wxy > 0))
            w = np.zeros_like(wuv)
            w[m] = ((wxy[m] * wuv[m]) / (wxy[m] + wuv[m]))
        if np.any((w < 0.0)):
            raise ValueError('Invalid weights: weights must be non-negative.')
        if (np.sum((w > 0)) < 2):
            raise ValueError("Not enough valid data for 'rscale' fit: too many weights are zero!")
        w /= np.sum(w, dtype=np.longdouble)
        xm = np.dot(w, x)
        ym = np.dot(w, y)
        um = np.dot(w, u)
        vm = np.dot(w, v)
        x -= xm
        y -= ym
        u -= um
        v -= vm
        su2 = np.dot(w, (u ** 2))
        sv2 = np.dot(w, (v ** 2))
        sxv = np.dot(w, (x * v))
        syu = np.dot(w, (y * u))
        sxu = np.dot(w, (x * u))
        syv = np.dot(w, (y * v))
        su2v2 = (su2 + sv2)
    det = ((sxu * syv) - (sxv * syu))
    if (det < 0):
        rot_num = (sxv + syu)
        rot_denom = (sxu - syv)
    else:
        rot_num = (sxv - syu)
        rot_denom = (sxu + syv)
    if (rot_num == rot_denom):
        theta = 0.0
    else:
        theta = np.rad2deg(np.arctan2(rot_num, rot_denom))
        if (theta < 0):
            theta += 360.0
    ctheta = np.cos(np.deg2rad(theta))
    stheta = np.sin(np.deg2rad(theta))
    s_num = ((rot_denom * ctheta) + (rot_num * stheta))
    if (su2v2 > 0.0):
        mag = (s_num / su2v2)
    else:
        raise SingularMatrixError('Singular matrix: suspected colinear points.')
    if (det < 0):
        sthetax = ((- mag) * stheta)
        cthetay = ((- mag) * ctheta)
    else:
        sthetax = (mag * stheta)
        cthetay = (mag * ctheta)
    cthetax = (mag * ctheta)
    sthetay = (mag * stheta)
    sdet = np.sign(det)
    xshift = ((xm - (um * cthetax)) - ((sdet * vm) * sthetax))
    yshift = ((ym + ((sdet * um) * sthetay)) - (vm * cthetay))
    p = np.array([cthetax, sthetay, xshift], dtype=np.longdouble)
    q = np.array([(- sthetax), cthetay, yshift], dtype=np.longdouble)
    fit = _build_fit(p, q, fitgeom='rscale')
    resids = ((xy - np.dot(uv, fit['matrix_ld'].T)) - fit['shift_ld'])
    fit['resids'] = resids.astype(np.double)
    _compute_stat(fit, residuals=resids, weights=w)
    return fit