#include "fluxMat.h"


fluxMat::fluxMat()
{
}

fluxMat::fluxMat(vector<vector<double>> m_matrix, int m_time)
{
    matrix = m_matrix;
    time = m_time;
}

fluxMat::~fluxMat()
{
    //dtor
}

/* Returns a copy of line [receiver]
 * Simple boudaries check
 */
vector<double> fluxMat::get_donnors(int receiver)
{
    if(receiver < 0 || receiver >= matrix.size())
    {
        cout << "get_donnors: out of bounaries : " 
             << receiver  << " / " << matrix.size() << endl;
        exit(0);
    }

    return vector<double>(matrix[receiver]);
}


int fluxMat::get_time()
{
    return time;
}


/* Draws a pop id from the flux matrix ponderated by a weight vector
 * Cost: This function creates a copy of one line of flux matrix
 * Drawing consists of:  weighting, cumSum, norm and bin search vs random unif
 * Failure: returns -1 if sum(flux_matrix x weights) == 0
 * TODO : Potential optimization to avoid copy of the vector:
 *        As weights are often calculated for each individual (in assortMating)
 *        Weights should be written over, and flux matrix only read by reference
 *        Thus reallocation of a new vector is spared
 * Note: Weights are already disposable when using from select_pop_assortMating
 */


int fluxMat::draw(int receiver, vector<double> &weights)
{   
    // Copy of one ine of flux matrix
    vector<double> tempVect = get_donnors(receiver);
    if(tempVect.size() != weights.size())
    {
        fail("fluxMat::draw: Wrong size.");
    }
    // Weighting of flux matrix & cumuative sum
    tempVect[0] = tempVect[0] * weights[0]; //Fist step out of loop, can't add previous value in vect
    for(unsigned int i  = 1; i < tempVect.size(); i++) //Thus loop starts at 1
    {
        tempVect[i] = tempVect[i] * weights[i] + tempVect[i-1];
    }

    // Failure condition
    if(tempVect.back() == 0.0) return -1;

    // Divide by maximum (= last value)
    for(unsigned int i  = 0; i < tempVect.size(); i++)
            tempVect[i] /= tempVect.back();


    int lb = lower_bound(tempVect.begin(), tempVect.end(), Random()) - tempVect.begin();

    return(lb);
}

