// Copyright (C) 2017 EDF
// All Rights Reserved
// This code is published under the GNU Lesser General Public License (GNU LGPL)
#include "StOpt/regression/LocalSameSizeRegression.h"

using namespace std;
using namespace Eigen;

namespace StOpt
{
LocalSameSizeRegression:: LocalSameSizeRegression(const ArrayXd &p_lowValues,
        const ArrayXd &p_step,
        const  ArrayXi &p_nbStep):
    BaseRegression(), m_lowValues(p_lowValues), m_step(p_step), m_nbStep(p_nbStep), m_nbMeshTotal(p_nbStep.prod()) {}

LocalSameSizeRegression::LocalSameSizeRegression(const bool &p_bZeroDate,
        const ArrayXXd  &p_particles,
        const ArrayXd &p_lowValues,
        const ArrayXd &p_step,
        const ArrayXi &p_nbStep):
    BaseRegression(p_bZeroDate, p_particles, false),
    m_lowValues(p_lowValues), m_step(p_step), m_nbStep(p_nbStep),
    m_nbMeshTotal(p_nbStep.prod()),
    m_simToCell(p_particles.cols())
{
    if (!m_bZeroDate)
    {
        fillInSimCell(m_particles);
    }
}

LocalSameSizeRegression::LocalSameSizeRegression(const bool &p_bZeroDate,
        const ArrayXd &p_lowValues,
        const ArrayXd &p_step,
        const ArrayXi &p_nbStep):
    BaseRegression(p_bZeroDate, false),
    m_lowValues(p_lowValues), m_step(p_step),
    m_nbStep(p_nbStep),
    m_nbMeshTotal(p_nbStep.prod())
{
}


LocalSameSizeRegression::LocalSameSizeRegression(const LocalSameSizeRegression   &p_object) : BaseRegression(p_object),
    m_lowValues(p_object.getLowValues()), m_step(p_object.getStep()),
    m_nbStep(p_object.getNbStep()), m_nbMeshTotal(p_object.getNbMeshTotal()),
    m_simAndCell(p_object.getSimAndCell()), m_simToCell(p_object.getSimToCell())
{}


void LocalSameSizeRegression:: fillInSimCell(const ArrayXXd  &p_particles)
{
    if (p_particles.cols() != m_simToCell.size())
        m_simToCell.resize(p_particles.cols());
    m_simAndCell.clear();
    m_simAndCell.reserve(p_particles.cols());
    // utilitary
    ArrayXi idec(p_particles.rows());
    idec(0) = 1.;
    for (int id = 1; id < p_particles.rows(); ++id)
        idec(id) = idec(id - 1) * m_nbStep(id - 1);
    ArrayXi iposition(p_particles.rows());
    for (int is = 0; is < p_particles.cols(); ++is)
    {
        bool bAdd = true;
        for (int id = 0; id < iposition.size(); ++id)
        {
            double position = (p_particles(id, is) - m_lowValues(id)) / m_step(id);
            if ((position < m_nbStep(id)) && (position >= 0.))
                iposition(id) = position ;
            else
            {
                bAdd = false ;
                break;
            }
        }
        if (bAdd)
        {
            int ipos = 0 ;
            for (int id = 0; id < iposition.size(); ++id)
                ipos += iposition(id) * idec(id);
            m_simAndCell.push_back(Array2i(is, ipos));
            m_simToCell(is) = ipos;
        }
        else
            m_simToCell(is) = -1;
    }
}

}
