def compute_rotations_from_accumulators(A, mu, count, num_buckets):
    """
    Given accumulators computed on cluster residuals, compute the optimal
    rotation matrix. The A and mu variables are modified in place and returned to
    avoid memory allocation.

    :param ndarray A:
        a VxDxD array - total sum of outer products of residuals per cluster
    :param ndarray mu:
        a VxD array - total sum of residuals per cluster
    :param ndarray count:
        a Vx1 array - count of points for each cluster
    :param int num_buckets:
        the number of subvectors to balance variance across

    :returns ndarray A:
        a VxDxD array - per cluster local rotations of size DxD on the first dimension
    :returns ndarray mu:
        a VxD array of mean residuals per cluster
    """

    V, D = mu.shape

    # For each cluster, use accumulator variables to estimate covariance matrix
    # and compute rotation matrix
    for i in xrange(V):

        # Normalize
        num_points = count[i]
        mu[i] /= num_points

        # Compute covariance estimator
        cov = (A[i] + A[i].transpose()) / (2 * (num_points - 1)) - np.outer(mu[i], mu[i])

        # Compute eigenvalues, reuse A matrix
        if num_points > D:
            logger.warn('Fewer points (%d) than dimensions (%d) in rotation computation for cluster %d' % (num_points, D, i))
            eigenvalues = np.ones(D)
            A[i] = np.eye(D)
        else:
            eigenvalues, A[i] = np.linalg.eigh(cov)

        # Permute eigenvectors to balance variance in subquantizers
        permuted_inds = eigenvalue_allocation(num_buckets, eigenvalues)
        A[i] = A[i, :, permuted_inds]

    return A, mu
dataset/ETHPy150Open yahoo/lopq/python/lopq/model.py/compute_rotations_from_accumulators/operator `<` -> `>`