int searchModelWithMEstimator(const Kernel &kernel,
                              int maxNbIterations,
                              typename Kernel::Model* bestModel,
                              double *RMS = 0,
                              double *sigmaMAD_p = 0)
{
    assert(bestModel);
    const int N = (int)kernel.NumSamples();
    const int m = (int)Kernel::MinimumSamples();
    
    // Test if we have sufficient points for the kernel.
    if (N < m) {
        return 0;
    } else if (N == m) {
        bool ok = searchModel_minimalSamples(kernel, bestModel, 0, RMS);
        return ok ? 1 : 0;
    }

    // Compute a first model on all samples with least squares
    int hasModel = kernel.ComputeModelFromAllSamples(bestModel);
    if (!hasModel) {
        return 0;
    }

    InliersVec isInlier(N, true);
    
    int nbSuccessfulIterations = kernel.MEstimator(*bestModel, isInlier, maxNbIterations, bestModel, RMS, sigmaMAD_p);
    if (RMS) {
        *RMS = kernel.ScalarUnormalize(*RMS);
    }
    kernel.Unnormalize(bestModel);
    return nbSuccessfulIterations;

} // searchModelWithMEstimator
bool searchModelLS(const Kernel &kernel,
                  typename Kernel::Model* bestModel,
                   double *RMS = 0)
{
    assert(bestModel);
    const int N = (int)kernel.NumSamples();
    const int m = (int)Kernel::MinimumSamples();
    
    // Test if we have sufficient points for the kernel.
    if (N < m) {
        return 0;
    } else if (N == m) {
        return searchModel_minimalSamples(kernel, bestModel, 0, RMS);
    }
    
    bool ok = kernel.ComputeModelFromAllSamples(bestModel);
    if (RMS) {
        InliersVec isInlier(N);
        int nInliers = kernel.ComputeInliersForModel(*bestModel, &isInlier, RMS);
        (void)nInliers;
    }
    if (RMS) {
        *RMS = kernel.ScalarUnormalize(*RMS);
    }
    
    kernel.Unnormalize(bestModel);
    return ok;
    
} // searchModelWithMEstimator