
/***************************************************************************
                          distgnt.cpp -  Librairie d'objets permettant de manipuler
                          des distances entre populations
                             -------------------
    begin                : ven sep 01 10:25:55 CEST 2000
    copyright            : (C) 2000 by Olivier Langella CNRS UPR9034
    email                : Olivier.Langella@pge.cnrs-gif.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#include "distgnt.h"
#include "arbreplus.h"


vector<string> DistancesGnt::_tab_noms_methodes;

DistancesGnt::DistancesGnt(int methode, bool square_distance, Jeupop * Pjeupop, unsigned int niveau) {
//cerr << "DistancesGnt::DistancesGnt debut" << endl;
	unsigned long j;

	_methode = methode;
	_Pjeupop = Pjeupop;

	if ((niveau == 100) & (Pjeupop->_VcalcStrucPop.size() >0)) {
		//stuct pop level is already defined
	}
	else {Pjeupop->f_rempliVcalcStrucPop(niveau);
	}

	_tabPstrucpop = Pjeupop->_VcalcStrucPop;

	_tabPloc = Pjeupop->_tabPloc;
	_nbpop = Pjeupop->get_nbstrucpopVcalc();
	_PtabFreq = 0;
	_PtabMu = 0;
	_tabEviteLocus = 0;
 	_squareDistance = square_distance;
	_pi = ((long double) acos((double)-1));
//	_tabNbAll = 0;

	_nbloc = Pjeupop->get_nbloc();
	_tabNbAll = new unsigned long [_nbloc];

	_bootind = false;

	for (j=0; j < _nbloc; j++) {
		_tabNbAll[j] = _tabPloc[j]->get_nball();
	}
//cerr << "DistancesGnt::DistancesGnt fin" << endl;
}

DistancesGnt::~DistancesGnt() {
	if (_tabNbAll != 0)	delete[] _tabNbAll;
	if (_PtabFreq != 0) {
		delete[] _PtabFreq[0];
		delete[] _PtabFreq;
	}
	if (_PtabMu != 0) {
		delete[] _PtabMu;
	}
	if (_tabEviteLocus != 0) delete[] _tabEviteLocus;

//	_nbloc = Pjeupop->get_nbloc();
}

long double DistancesGnt::r_allsimilnul(Individu * pind1, Individu * pind2) const{
	//Calcul de la similarit� entre deux individus
	//valable pour nploides
	Vecteur<Allele*> tabPall1;//, tabPallNuls;
	long pos;//, nballnuls(0);
	unsigned long allele, taille, nb_all_communs(0);
	unsigned long j, i;
	unsigned long nploidie(_Pjeupop->get_nploidie());
	unsigned long nb_all_comparables(0);
	unsigned long nblocus(_VcalcLocus.size());

	taille = nblocus * nploidie;

	for (j = 0 ; j < nblocus; j++) {
		i = pind1->get_nballnuls(_VcalcLocus[j]);
		if (pind2->get_nballnuls(_VcalcLocus[j]) > i) i = pind2->get_nballnuls(_VcalcLocus[j]);
		nb_all_comparables += nploidie - i;
	}
	if (nb_all_comparables == 0) {	
		throw Jeupop::Anomalie(6);
		return (0);
	}

//cerr << nb_all_comparables << " ";

	for (j = 0 ; j < nblocus; j++) {
		for (i = 0; i < nploidie; i++) {
			allele = (_VcalcLocus[j] * nploidie) + i;
			if (pind1->_tabPall[allele]->_miss) {}
			else tabPall1.push_back(pind1->_tabPall[allele]);
		}
	}

//cerr << pind1->get_nom() << " " << pind2->get_nom() << endl;
	for (j = 0 ; j < nblocus; j++) {
		for (i = 0; i < nploidie; i++) {
			allele = (_VcalcLocus[j] * nploidie) + i;
			if (pind2->_tabPall[allele]->_miss) {}
			else {
				pos = tabPall1.Position(pind2->_tabPall[allele]);
				if (pos != -1) {
//					cerr << pind2->_tabPall[allele]->get_Nom() << " " << tabPall1[pos]->get_Nom() << endl;

					nb_all_communs++;
					tabPall1.Suppr(pos);	
				}
			}
		}
	}
//cerr << nb_all_communs << " " << nb_all_comparables << endl;
	return ((long double) nb_all_communs / (long double) nb_all_comparables);
}

long double DistancesGnt::r_dist2ind(unsigned long nbind1, unsigned long nbind2) const {
	//renvoi de la distance
	long double resultat(0);
//	int Smoy(get_nbloc()), nball;
//	int nbloc(get_nbloc());
//	long i;

	switch (_methode) {
	case 5:
		//methode simple correct: moyenne de ressemblance
		//sur population nploide
		// 0 allele en commun => 1
		// 1 allele en commun => 0.5
		// 2 alleles en commun => 0
		// ne fait pas de calcul sur les all�les 00 && 00
		// applique 0.5 pour 0001 avec 0101 ou 0103
		//     et  0 pour 0001 avec 0302
// ATTENTION pour les donn�es manquantes: la similitude est maximisee
		resultat = (double) 1 - (double) r_allsimilnul(_tabPind[nbind1], _tabPind[nbind2]);
//cerr << r_allsimilnul(pind1, pind2) << endl;
		break;
	default:
		resultat = r_dist2pop(nbind1, nbind2);
		break;
	}

	return resultat;
}

long double DistancesGnt::r_distDasPsAi(unsigned long nbind1, unsigned long nbind2) const {
	return (r_distDasPsAi(_tabPind[nbind1], _tabPind[nbind2]));
}

long double DistancesGnt::r_distDasPsAi(const Individu * Pind1, const Individu * Pind2) const {
	//Calcul de la similarit� entre deux individus (Das)
	//valable pour nploides
	Vecteur<Allele*> tabPall1;//, tabPallNuls;
	long pos;//, nballnuls(0);
	unsigned long allele, taille, nb_all_communs(0);
	unsigned long j, i;
	unsigned long nploidie(_Pjeupop->get_nploidie());
	unsigned long nb_all_comparables(0);
	unsigned long nblocus(_VcalcLocus.size());

	taille = nblocus * nploidie;

	for (j = 0 ; j < nblocus; j++) {
		i = Pind1->get_nballnuls(_VcalcLocus[j]);
		if (Pind2->get_nballnuls(_VcalcLocus[j]) > i) i = Pind2->get_nballnuls(_VcalcLocus[j]);
		nb_all_comparables += nploidie - i;
	}
	if (nb_all_comparables == 0) {	
		throw Jeupop::Anomalie(6);
		return (0);
	}

//cerr << nb_all_comparables << " ";

	for (j = 0 ; j < nblocus; j++) {
		for (i = 0; i < nploidie; i++) {
			allele = (_VcalcLocus[j] * nploidie) + i;
			if (Pind1->_tabPall[allele]->_miss) {}
			else tabPall1.push_back(Pind1->_tabPall[allele]);
		}
	}

//cerr << pind1->get_nom() << " " << pind2->get_nom() << endl;
	for (j = 0 ; j < nblocus; j++) {
		for (i = 0; i < nploidie; i++) {
			allele = (_VcalcLocus[j] * nploidie) + i;
			if (Pind2->_tabPall[allele]->_miss) {}
			else {
				pos = tabPall1.Position(Pind2->_tabPall[allele]);
				if (pos != -1) {
//					cerr << pind2->_tabPall[allele]->get_Nom() << " " << tabPall1[pos]->get_Nom() << endl;

					nb_all_communs++;
					tabPall1.Suppr(pos);	
				}
			}
		}
	}
//cerr << nb_all_communs << " " << nb_all_comparables << endl;
	return ((long double) nb_all_communs / (long double) nb_all_comparables);
}


long double DistancesGnt::r_dist2ind(Individu* Pind1, Individu* Pind2) const {
	//renvoi de la distance
	long double resultat(0);

	switch (_methode) {
	case 5:
		//methode simple correct: moyenne de ressemblance
		//sur population nploide
		// 0 allele en commun => 1
		// 1 allele en commun => 0.5
		// 2 alleles en commun => 0
		// ne fait pas de calcul sur les all�les 00 && 00
		// applique 0.5 pour 0001 avec 0101 ou 0103
		//     et  0 pour 0001 avec 0302
// ATTENTION pour les donn�es manquantes: la similitude est maximisee
		resultat = (double) 1 - (double) r_allsimilnul(Pind1,Pind2);
//cerr << r_allsimilnul(pind1, pind2) << endl;
		break;
	}

	return resultat;
}

void DistancesGnt::newTabFreq() {
	//calcul et stockage des frequences alleliques
	// tabPfreq contient les adresses de tableaux de frequences
	// tabNbAll contient le nombre d'alleles a chaque locus
	// _tabEviteLocus contient les locus � �viter (qui ne contiennent que des all�les nuls)

	unsigned long i, j;
	unsigned long indice(0);

//cerr << "coucou newTabFreq" <<endl ;
	if (_PtabFreq != 0) {
		delete[] _PtabFreq[0];
		delete[] _PtabFreq;
		_PtabFreq = 0;
	}
	if (_tabEviteLocus != 0) {
		delete[] _tabEviteLocus;
		_tabEviteLocus = 0;
	}

	_PtabFreq = new long double * [_nbloc * _nbpop];
	_tabEviteLocus = new bool [_nbloc * _nbpop];

	for (j=0; j < _nbloc; j++) {
		indice += _tabNbAll[j];
	}
	
	long double* adresse;
	adresse = new long double[_nbloc * _nbpop * indice];

	indice = 0;
	for (i=0; i < _nbpop; i++) {
		for (j=0; j < _nbloc; j++) {
 			_tabEviteLocus[indice] = false;

			_PtabFreq[indice] = adresse;
			adresse += _tabNbAll[j];
			indice++;
		}
	}
}

void DistancesGnt::newTabFreqTot() {
	//fr�quence des all�les � chaque locus sur toutes les pops
	//�a ne sert pas pour l'instant (26/02/2002)
	unsigned long i;
	unsigned long nballtot(0);
	
	newTabFreq();

	for (i=0; i < _nbloc; i++) {
		nballtot += _tabNbAll[i];
	}

	if (_PtabFreqTot != 0) {
		delete[] _PtabFreqTot;
		_PtabFreqTot = 0;
	}
	/*
	if (_tabEviteLocus != 0) {
		delete[] _tabEviteLocus;
		_tabEviteLocus = 0;
	}
	*/
	_PtabFreqTot = new long double [nballtot];
	//_tabEviteLocus = new (bool [_nbloc * _nbpop]);
	//for (i=0; i < (_nbloc * _nbpop); i++) _tabEviteLocus[i] = false;
}

void DistancesGnt::newTabMu() {
	unsigned long i;

	if (_PtabMu != 0) {
		delete[] _PtabMu;
		_PtabMu = 0;
	}
	if (_tabEviteLocus != 0) {
		delete[] _tabEviteLocus;
		_tabEviteLocus = 0;
	}

	_PtabMu = new long double [_nbloc * _nbpop];
	_tabEviteLocus = new bool [_nbloc * _nbpop];
	for (i=0; i < (_nbloc * _nbpop); i++) _tabEviteLocus[i] = false;
}

void DistancesGnt::newTabMuInd() {
	unsigned long i;

	if (_PtabMu != 0) {
		delete[] _PtabMu;
		_PtabMu = 0;
	}
	if (_tabEviteLocus != 0) {
		delete[] _tabEviteLocus;
		_tabEviteLocus = 0;
	}

	_PtabMu = new long double [_nbloc * _tabPind.size()];
	_tabEviteLocus = new bool [_nbloc * _tabPind.size()];
	for (i=0; i < (_nbloc * _tabPind.size()); i++) _tabEviteLocus[i] = false;
}

void DistancesGnt::newTabFreqInd() {
	//calcul et stockage des frequences alleliques
	//pour chaque individus
	// tabPfreq contient les adresses de tableaux de frequences
	// tabNbAll contient le nombre d'alleles a chaque locus
	// _tabEviteLocus contient les locus � �viter (qui ne contiennent que des all�les nuls)

	unsigned long nbind(_tabPind.size());
	unsigned long i, j, indice(0);

	if (_PtabFreq != 0) {
		delete[] _PtabFreq[0];
		delete[] _PtabFreq;
		_PtabFreq = 0;
	}
	if (_tabEviteLocus != 0) {
		delete[] _tabEviteLocus;
		_tabEviteLocus = 0;
	}

//cerr << "coucou newTabFreq" <<endl ;
	_PtabFreq = new long double * [_nbloc * nbind];
	_tabEviteLocus = new bool [_nbloc * nbind];

	for (j=0; j < _nbloc; j++) {
		indice += _tabNbAll[j];
	}
	
	long double * adresse;
	adresse = new long double[_nbloc * nbind * indice];

	indice = 0;
	for (i=0; i < nbind; i++) {
		for (j=0; j < _nbloc; j++) {
			_tabEviteLocus[indice] = false;

			_PtabFreq[indice] = adresse;
			adresse += _tabNbAll[j];
			indice++;
		}
	}
}

void DistancesGnt::f_bootstrapLocus(Arbre &arbreRef, int methodeArbre, unsigned int nbrepet, Vecteur<unsigned int> * PVcalcLocusRef, bool sur_ind) {
	// Boostrap sur les locus
	// ********creer des exceptions pour v�rifier l'arbreRef *********
	unsigned long i, j;
	unsigned int tirage;
	MatriceLD distancesRef;
	unsigned long nbLocus(PVcalcLocusRef->size());
	Arbre bootArbre;
	MatriceLD distancesBoot;
	unsigned long taillemat;

// calcul de l'arbre de r�f�rence arbreRef
//	arbreRef => arbre vide !!!
//ofstream sortie_test;
//sortie_test.open("test_boot", ios::out);


cerr << "distances ref:";
	if (sur_ind) f_distgntInd(distancesRef, PVcalcLocusRef);
	else f_distgntpop(distancesRef, PVcalcLocusRef);
cerr << "+"<< endl;

cerr << "arbre ref:";
	arbreRef.f_forceiDistances(distancesRef,methodeArbre);
//	arbreRef.iDistances(distancesRef,methodeArbre);
cerr << "+"<< endl;
	//_tabPOtu de arbre est cree avec les titres des lignes 
	//    de la matrice, dans le meme ordre
//cerr << "sortie du fichier" << endl;
//sortie_test << arbreRef << endl;


	srand ((unsigned) time( NULL ) );

	taillemat = distancesRef.GetNC();
	distancesBoot.resize(taillemat, taillemat);
	distancesBoot.SetType(2);
	distancesBoot.SetFlag(1);
	for (j = 0; j < taillemat; j++) {
		distancesBoot._tcol[j] = distancesBoot._tlig[j] = distancesRef._tcol[j];
	}
//cerr << distancesBoot._tcol[1] << endl;
//cerr << distancesRef._tcol[1] << endl;

//	arbreRef.fRempliTabNumOtusNoeuds();
//	arbreRef.f_load_vectind();
	arbreRef.f_load_vect_id_ind();

	for (i = 0; i < nbrepet; i ++ ) { //boucle du bootstrap

cerr <<endl;		// tirage des locus
		for (j = 0; j < nbLocus; j ++ ) {
			tirage = (unsigned int) (nbLocus * ((long double)rand() / ((long double) RAND_MAX)));
			_VcalcLocus[j] = PVcalcLocusRef->operator[](tirage);
		}

cerr <<endl;
cerr <<  "tirage: " << i+1 << " sur: " << nbrepet << endl;
cerr << "distances:";
		// calcul de distances
		if (sur_ind) f_distgntIndVcalc(distancesBoot._tab);
		else f_distgntpopVcalc(distancesBoot._tab);

cerr << "+"<< endl;
cerr << "arbre:";

		// construction de l'arbre � examiner
		bootArbre.f_forceiDistances(distancesBoot,100 + methodeArbre);
//		bootArbre.iDistances(distancesBoot,100 + methodeArbre);
cerr << "+"<< endl;
cerr << "ajboot:";

//cout << endl << bootArbre << endl;
//cerr << "sortie du fichier" << endl;
//sortie_test << bootArbre << endl;


		// comparaison avec l'arbre de r�f�rence
		arbreRef.AjBootstrap(bootArbre);
cerr << "+"<< endl;
//cerr << "sortie du fichier" << endl;
//sortie_test << arbreRef << endl;

	}// fin de boucle du bootstrap
//sortie_test.close();

	arbreRef.fCalcValBootstrap();
}

void DistancesGnt::f_bootstrapIndividus(Arbre &arbreRef, int methodeArbre, unsigned int nbrepet, Vecteur<unsigned int> * PVcalcLocusRef) {
	// Boostrap sur les individus
	// ********creer des exceptions pour v�rifier l'arbreRef *********
	unsigned long i, j;
	MatriceLD distancesRef;
	Arbre bootArbre;
	MatriceLD distancesBoot;

// calcul de l'arbre de r�f�rence arbreRef
//	arbreRef => arbre vide !!!
	_bootind = false;

cerr << "distances ref:";
	f_distgntpop(distancesRef, PVcalcLocusRef);
cerr << "+"<< endl;

cerr << "arbre ref:";
	arbreRef.f_forceiDistances(distancesRef,methodeArbre);
//	bootArbre.iDistances(distancesRef,methodeArbre);
cerr << "+"<< endl;
	//_tabPOtu de arbre est cree avec les titres des lignes
	//    de la matrice, dans le meme ordre


	srand ((unsigned) time( NULL ) );
	_bootind = true;

	distancesBoot.resize(_nbpop, _nbpop);
	distancesBoot.SetType(2);
	distancesBoot.SetFlag(1);
	for (j = 0; j < _nbpop; j++) {
		distancesBoot._tcol[j] = distancesBoot._tlig[j] = _tabPstrucpop[j]->get_nom();
	}
//cerr << distancesBoot._tcol[1] << endl;
//cerr << distancesRef._tcol[1] << endl;

//	arbreRef.fRempliTabNumOtusNoeuds();
//cerr << "DistancesGnt::f_bootstrapIndividus top1" <<endl;
//	arbreRef.f_load_vectind();
	arbreRef.f_load_vect_id_ind();
//cerr << "DistancesGnt::f_bootstrapIndividus top2" <<endl;

	for (i = 0; i < nbrepet; i ++ ) { //boucle du bootstrap

cerr <<endl;

cerr <<endl;
cerr <<  "tirage: " << i+1 << " sur: " << nbrepet << endl;
cerr << "distances:";
		// calcul de distances
		f_distgntpopVcalc(distancesBoot._tab);

cerr << "+"<< endl;
cerr << "arbre:";

		// construction de l'arbre � examiner
		bootArbre.f_forceiDistances(distancesBoot,100 + methodeArbre);
//		bootArbre.iDistances(distancesBoot,100 + methodeArbre);
cerr << "+"<< endl;
cerr << "ajboot: ";

//cout << endl << bootArbre << endl;

		// comparaison avec l'arbre de r�f�rence
		arbreRef.AjBootstrap(bootArbre);
cerr << "+"<< endl;

	}// fin de boucle du bootstrap

	arbreRef.fCalcValBootstrap();
}

void DistancesGnt::f_distgntpop (MatriceLD &resultat, Vecteur<unsigned int> *PVcalcLocus) {
	//distances G�n�tiques entre Populations
	unsigned long i;
// pr�paration de _VcalcLoc:
	_VcalcLocus = *PVcalcLocus;

	biolib::vecteurs::ChaineCar mot;

	resultat.resize(_nbpop, _nbpop);
	resultat._titre.push_back(_("Genetic distances on "));
	mot.AjEntier(_nbpop);
	
	resultat._titre[resultat._titre.size() - 1] += mot;
	resultat._titre[resultat._titre.size() - 1] += " populations";

	resultat._titre.push_back(get_nom_methode(_methode));
	if (_squareDistance) resultat._titre[resultat._titre.size() - 1] += _(" (squared distances)");

	switch (_methode) {
	case 5:
		break;
	case 101:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 102:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 103:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 104:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 106:
		// stockage des Mu
		newTabMu();
		f_calcTabMu();
		break;
	case 107:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 108:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 109:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 110:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 111:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 112:
		// stockage des Mu
		newTabMu();
		f_calcTabMu();
		break;
	case 113:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 114:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	case 115:
		// stockage des fr�quences
		newTabFreq();
		f_calcTabFreq();
		break;
	default:
		break;
	}
	resultat.SetType(2);
	resultat.SetFlag(1); //titres sur les lignes

	for (i = 0; i < _nbpop; i++) {
		resultat._tcol[i] = resultat._tlig[i] = _tabPstrucpop[i]->get_nom();
	}

	f_distgntpopVcalc (resultat._tab);
//	try {
//		f_distgntpopVcalc (resultat._tab);
//	}
//	catch (Anomalie lepb) {
//		cerr << endl << lepb.fmessage(lepb.le_pb) << endl;
//	}
}

void DistancesGnt::f_distgntInd (MatriceLD &resultat, Vecteur<unsigned int> *PVcalcLocus) {
//	_VcalcLocus.resize(PVcalcLocus->size());
	_VcalcLocus = *PVcalcLocus;

//cerr << "f_distgntIndVcalc deb" << endl;

	unsigned long i, k, nbind; //(_Pjeupop->get_nbind());
	unsigned long j;
	biolib::vecteurs::ChaineCar mot;
	//vector<Individu*> tabPind;
	nbind = get_nbind();

	_tabPind.resize(nbind);
	
	resultat.resize(nbind, nbind);
	resultat._titre.push_back(_("Genetic distances on "));
	resultat._titre[resultat._titre.size() - 1].AjEntier(nbind); // += mot;
	resultat._titre[resultat._titre.size() - 1] += _(" individuals");

	resultat._titre.push_back(get_nom_methode(_methode));
	if (_squareDistance) resultat._titre[resultat._titre.size() - 1] += _(" (squared distances)");
	
 	resultat.SetType(2);
	resultat.SetFlag(1); //titres sur les lignes

	k=0;
	for (i = 0; i < _nbpop; i++) {
		for (j = 0; j < _tabPstrucpop[i]->get_nbind(); j++) {
			mot.assign(_tabPstrucpop[i]->_tabPind[j]->_nom);
//			mot.AjEntier(i+1);
//			mot += '_';
//			mot += _tabPstrucpop[i]->_tabPind[j]->_nom;
			resultat._tlig[k] = mot;
			resultat._tcol[k] = mot;
			_tabPind[k] = _tabPstrucpop[i]->_tabPind[j];
			k++;
		}
	}

	resultat._titre.push_back(get_nom_methode(_methode));
	switch (_methode) {
	case 5:
		break;
	case 101:
		// stockage des fr�quences
		newTabFreqInd();
		f_calcTabFreqInd();
		break;
	case 102:
		// stockage des fr�quences
		newTabFreqInd();
		f_calcTabFreqInd();
		break;
	case 103:
		// stockage des fr�quences
		newTabFreqInd();
		f_calcTabFreqInd();
		break;
	case 104:
		// stockage des fr�quences
		newTabFreqInd();
		f_calcTabFreqInd();
		break;
	case 106:
		// stockage des Mu
		newTabMuInd();
		f_calcTabMuInd();
		break;
	case 107:
		// stockage des fr�quences
		newTabFreqInd();
		f_calcTabFreqInd();
		break;
	case 108:
		// stockage des fr�quences
		newTabFreqInd();
		f_calcTabFreqInd();
		break;
	case 109:
		// stockage des fr�quences
		newTabFreqInd();
		f_calcTabFreqInd();
		break;
	case 110:
		// stockage des fr�quences
		newTabFreqInd();
		f_calcTabFreqInd();
		break;
	case 111:
		// stockage des fr�quences
		newTabFreqInd();
		f_calcTabFreqInd();
		break;
	case 112:
		// stockage des Mu
		newTabMuInd();
		f_calcTabMuInd();
		break;
	case 113:
		throw Anomalie(4, get_nom_methode(13));
		break;
	case 114:
		throw Anomalie(4, get_nom_methode(14));
		break;
	case 115:
		throw Anomalie(4, get_nom_methode(15));
		break;
	default:
		break;
	}
	resultat.SetType(2);
	resultat.SetFlag(1); //titres sur les lignes

	f_distgntIndVcalc (resultat._tab);
}

void DistancesGnt::f_distgntpopDas(long double * Ptab) const {
	// calcul de distance g�n�tique avec la Das entre Populations
	// combinaison des individus entre les 2 pops (moyPsAB),
	//   combinaison des individus dans la pop1 (moyPsA1),
	//   combinaison des individus dans la pop2 (moyPsA2)

	long double moyPsAB(0);
	long double moyPsA1(0);
	long double moyPsA2(0);
	unsigned long i,j;
	
	if (_bootind) {
		for (j = 0; j < _nbpop; j++) {
			_tabPstrucpop[j]->f_bootstrap();
		}
	}

	for (j = 0; j < _nbpop; j++) {
		for (i = 0; i < j; i++) {
			moyPsAB = r_distDasMoyPsAB(_tabPstrucpop[i], _tabPstrucpop[j]);
			moyPsA1 = r_distDasMoyPsA(_tabPstrucpop[i]);
			moyPsA2 = r_distDasMoyPsA(_tabPstrucpop[j]);

			Ptab[(i * _nbpop) + j] = Ptab[(j * _nbpop) + i] = (long double)1 - (((long double) 2 * moyPsAB)/(moyPsA1 + moyPsA2));
		}
	}	
}

long double DistancesGnt::r_distDasMoyPsA(const StrucPop * Ppop) const {
	//n�cessaire au calcul de distance � l'int�rieur d'une population pour la Das

	long double somme(0);
	unsigned long calcsomme(0);
	unsigned long k,l, nbind;

								
	if (_bootind) {
		nbind = (Ppop->_VcalcInd.size());

		if (nbind < 2) throw Anomalie(2, Ppop->get_nom() );

		for (k=0; k < nbind; k++) {	//scan des individus de la pop	
			for (l=(k+1); l < nbind; l++) {	//scan des individus de la pop
				calcsomme++;
				try {
					somme += r_distDasPsAi(Ppop->_VcalcInd[k], Ppop->_VcalcInd[l]);
				}
				catch (Jeupop::Anomalie erreur) {
					if (erreur.le_pb == 6) calcsomme--;
				}
			}
		}
	}
	else {
		nbind = (Ppop->get_nbind());

		if (nbind < 2) throw Anomalie(2, Ppop->get_nom());

		for (k=0; k < nbind; k++) {	//scan des individus de la pop	
			for (l=(k+1); l < nbind; l++) {	//scan des individus de la pop
				calcsomme++;
				try {
					somme += r_distDasPsAi(Ppop->get_Pind(k), Ppop->get_Pind(l));
				}
				catch (Jeupop::Anomalie erreur) {
					if (erreur.le_pb == 6) calcsomme--;
				}
			}
		}
	}

	return (somme / ((long double) calcsomme));
}

long double DistancesGnt::r_distDasMoyPsAB(const StrucPop * Ppop1, const StrucPop * Ppop2) const {
	//n�cessaire au calcul de distance entre 2 pops pour la Das

	long double somme(0);
	unsigned long calcsomme;
	unsigned long k,l, nbind1(0), nbind2(0);

								
	if (_bootind) {
		nbind1 = (Ppop1->_VcalcInd.size());
		nbind2 = (Ppop2->_VcalcInd.size());
		calcsomme = nbind1 * nbind2;

		for (k=0; k < nbind1; k++) {	//scan des individus de la pop1	
			for (l=0; l < nbind2; l++) {	//scan des individus de la pop2
				try {
					somme += r_distDasPsAi(Ppop1->_VcalcInd[k], Ppop2->_VcalcInd[l]);
				}
				catch (Jeupop::Anomalie erreur) {
					if (erreur.le_pb == 6) calcsomme--;
				}
			}
		}
	}
	else {
		nbind1 = (Ppop1->get_nbind());
		nbind2 = (Ppop2->get_nbind());
		calcsomme = nbind1 * nbind2;

		for (k=0; k < nbind1; k++) {	//scan des individus de la pop1	
			for (l=0; l < nbind2; l++) {	//scan des individus de la pop2
				try {
					somme += r_distDasPsAi(Ppop1->get_Pind(k), Ppop2->get_Pind(l));
				}
				catch (Jeupop::Anomalie erreur) {
					if (erreur.le_pb == 6) calcsomme--;
				}
			}
		}
	}

	return (somme / ((long double) calcsomme));
}

void DistancesGnt::f_distgntpopVcalc(long double * Ptab) const {
	unsigned long i,j;


	if (_methode == 5) f_distgntpopDas(Ptab);
	else {
		if (_bootind) f_calcTabBootInd();

		for (j = 0; j < _nbpop; j++) {
			for (i = 0; i < j; i++) {
				Ptab[(i * _nbpop) + j] = Ptab[(j * _nbpop) + i] = r_dist2pop(i, j);
			}
		}
	}
}

long double DistancesGnt::r_dist2pop(unsigned long pop1, unsigned long pop2) const{
  	long double result(0);
	//renvoi de la distance entre 2 Populations
		switch (_methode) {
		case 101:
			// Nei's minimum genetic distance (1972)	
     	result = r_dpopNei(pop1, pop2, false);
//			return(r_dpopNei(pop1, pop2, false));
			break;
		case 102:
				// Nei's standard genetic distance (1972)			
     	result = r_dpopNei(pop1, pop2, true);
//			return(r_dpopNei(pop1, pop2, true));
			break;
		case 103:
			// Cavalli-Sforza and Edwards' (1967)		
     	result = r_dpopCavalli(pop1, pop2);
			break;
		case 104:
			// Nei et al's, Da (1983)
     	result = r_dpopNeiDa(pop1, pop2);
//			return(r_dpopNeiDa(pop1,pop2));
			break;
		case 106:
			// Goldstein et al. (1995a)
     	result = r_dpopGoldsteinMu(pop1, pop2);
//			return(r_dpopGoldsteinMu(pop1,pop2));
			break;
		case 107:
			// Latter's Fst (1972)
     	result = r_dpopFst(pop1, pop2);
//			return(r_dpopFst(pop1, pop2));
			break;
		case 108:
			// Prevosti et al.'s, Cp (1975)
     	result = r_dpopPrevosti(pop1, pop2);
//			return(r_dpopPrevosti(pop1, pop2));
			break;
		case 109:
			// Rogers', Dr (1972)
     	result = r_dpopRoger(pop1, pop2);
//			return(r_dpopRoger(pop1, pop2));
			break;
		case 110:
			// Goldstein et al. (1995b) Slatkin 1995
     	result = r_dpopGoldsteinASD(pop1, pop2);
//			return(r_dpopGoldsteinASD(pop1, pop2));
			break;
		case 111:
			// Shriver et al's, Dsw (1995)
     	result = r_dpopShriver(pop1, pop2);
//			return(r_dpopShriver(pop1, pop2));
			break;
		case 112:
			// Zhivotovsky , DR (1999)
     	result = r_dpopZhivotovsky(pop1, pop2);
		//	return(r_dpopZhivotovsky(pop1, pop2));
			break;
		case 113:
			// Reynolds unweighted (1983)
     	result = r_dpopReynoldsUnweighted(pop1, pop2);
//			return(r_dpopReynoldsUnweighted(pop1, pop2));
			break;
		case 114:
			// Reynolds weighted (1983)
     	result = r_dpopReynoldsWeighted(pop1, pop2);
//			return(r_dpopReynoldsWeighted(pop1, pop2));
			break;
		case 115:
			// Reynolds least squares (1983)
     	result = r_dpopReynoldsLeast(pop1, pop2);
//			return(r_dpopReynoldsLeast(pop1, pop2));
			break;
			
		}
  if (_squareDistance) return (result * result);
	else return (result);

	throw Anomalie(1);
	return(0);
}


long double DistancesGnt::r_dpopCavalli(unsigned long pop1,unsigned long pop2) const {

	//distances de Cavalli-Sforza and Edwards' (1967) entre 2 populations
	// tir� de Naoko Takezaki and Masatoshi Nei
	// "Genetic Distances and Reconstruction of Phylogenetic
	//        Trees From Microsatellite DNA"
	// Genetics society of America 144: 389-399.1996.

	long double Sracinelocus(0);
	long double Sracinealleles;
	unsigned long i, l, locus;
	unsigned long nblocus(_VcalcLocus.size()); // soit r
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = ( _PtabFreq + (pop1 * _nbloc));
	tabfreq2 = ( _PtabFreq + (pop2 * _nbloc));

	nblocusdivise = nblocus;


	for (l = 0; l < nblocus; l++) {
		// l numero du locus 
//cerr << "DistancesGnt::r_dpopCavalli entre " << l << endl;
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}
//cerr << "DistancesGnt::r_dpopCavalli sort " << l << endl;

		Sracinealleles = 0;
		for (i = 0; i < _tabNbAll[locus]; i++) {
			//i numero de l'allele
			//Pall = _tabPloc[locus]->getPall(i);
			//if (_Pjeupop->_tabPloc[locus]->getPall(i)->_nul) continue;
			
			Sracinealleles += (long double) sqrt(*(tabfreq1[locus] + i) * *(tabfreq2[locus] + i));
		}

		//necessaire: racine carree de zero ne fonctionne pas.
		if (Sracinealleles < 1) Sracinelocus += (long double)sqrt ((long double)2 * ((long double)1 - Sracinealleles));
	}

	if (nblocusdivise < 1) throw Anomalie(3);
	return (((long double)2 * Sracinelocus) / (_pi * (long double)nblocusdivise));
}

long double DistancesGnt::r_dpopFst(unsigned long pop1,unsigned long pop2) const {

	//Latter's Fst (1972) entre 2 populations
	// tir� de Naoko Takezaki and Masatoshi Nei
	// "Genetic Distances and Reconstruction of Phylogenetic
	//        Trees From Microsatellite DNA"
	// Genetics society of America 144: 389-399.1996.

	long double resultat(0), inter;
	long double Jx(0), Jy(0), Jxy(0);
	unsigned long i, l, locus;
	unsigned long nblocus(_VcalcLocus.size());
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));

	nblocusdivise = nblocus;

	for (l = 0; l < nblocus; l++) {
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		for (i = 0; i < _tabNbAll[locus]; i++) {
			//Pall = _tabPloc[locus]->getPall(i);
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;

			//frequence de l'allele  i dans la population 1
			inter = *(tabfreq1[locus] + i);
			//inter = ((long double) ppop1->r_nbcopall(Pall) / (long double) nballpop1);
			resultat = inter * inter;
	//		resultat /= nblocus;
			Jx += resultat;

			//frequence de l'allele  i dans la population 2
			resultat = *(tabfreq2[locus] + i);
			//resultat = ((long double) ppop2->r_nbcopall(Pall) / (long double) nballpop2);
			inter = inter * resultat;
			resultat = resultat * resultat;
	//		resultat /= nblocus;
			Jy += resultat;

	//		inter /= nblocus;
			Jxy += inter;
		}
	}

	if (nblocusdivise < 1) throw Anomalie(3);
	Jx /= (long double)nblocusdivise;
	Jy /= (long double)nblocusdivise;
	Jxy /= (long double)nblocusdivise;

	//distance de Nei classique:
	resultat = ((Jx + Jy) / (long double)2 ) - Jxy;

	// Fst :
	resultat /= ((long double)1 - Jxy);


	return (resultat);
}

/*
long double DistancesGnt::r_dpopFstClassique(long double ** tabfreq1,long double ** tabfreq2) const {

	//Fst entre 2 populations

	long double somme;
	long double HT, moyHS;
	unsigned long i, l, locus;
	long double nblocus((long double) _VcalcLocus.size());


	for (l = 0; l < nblocus; l++) {
		locus = _VcalcLocus[l];

		for (i = 0; i < _tabNbAll[locus]; i++) {
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_nul) continue;

			//pour chaque locus, chaque allele
			//calcul de HT
			somme = (*(tabfreq1[locus] + i) * nbind1)
		}
	}

	// Fst :
	resultat /= ((long double)1 - Jxy);


	return (resultat);
}
*/

long double DistancesGnt::r_dpopGoldsteinASD(unsigned long pop1,unsigned long pop2) const {

	//distances de Goldstein et al., ASD (1995b; Slatkin 1995) entre 2 populations
	// Average Square Distance
	// tir� de Naoko Takezaki and Masatoshi Nei
	// "Genetic Distances and Reconstruction of Phylogenetic
	//        Trees From Microsatellite DNA"
	// Genetics society of America 144: 389-399.1996.

	long double freqxil;
	long double freqyjl;
	long double Slocus(0);
	long double DblSommeij(0);
	unsigned long i,j, l, locus;
	unsigned long nblocus(_VcalcLocus.size()); // soit r
	unsigned long nballdiff;
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));

	nblocusdivise = nblocus;

	for (l = 0; l < nblocus; l++) {
		// l numero du locus 
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
//cerr << "DistancesGnt::r_dpopGoldsteinASD" << nblocusdivise << endl;
			continue;
		}

		nballdiff = _tabNbAll[locus];
		DblSommeij = 0;
		for (i = 0; i < nballdiff; i++) {
			//Palli = _tabPloc[locus]->getPall(i);
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;

			//frequence de l'allele  i dans la population 1
			freqxil = *(tabfreq1[locus] + i);
			//freqxil = ((long double) ppop1->r_nbcopall(Palli) / (long double) nballpop1);
//cerr << "DistancesGnt::r_dpopGoldsteinASD freqxil" << freqxil << endl;
			if (freqxil == 0) continue;
			
			for (j = 0; j < nballdiff; j++) {
				//double somme
				if (i == j) continue;
				//Pallj = _tabPloc[locus]->getPall(j);
				if (_Pjeupop->_tabPloc[locus]->getPall(j)->_miss) continue;
				
				
//cerr << "DistancesGnt::r_dpopGoldsteinASD nbrepet1" << _tabPloc[locus]->getPall(i)->_nbrepet << endl;
//cerr << "DistancesGnt::r_dpopGoldsteinASD nbrepet2" << _tabPloc[locus]->getPall(j)->_nbrepet << endl;
				freqyjl =  ((long double)_tabPloc[locus]->getPall(i)->_nbrepet - (long double)_tabPloc[locus]->getPall(j)->_nbrepet);
//cerr << "DistancesGnt::r_dpopGoldsteinASD freqyjl" << freqyjl << endl;
				freqyjl = freqyjl * freqyjl;
//cerr << "DistancesGnt::r_dpopGoldsteinASD freqyjl" << freqyjl << endl;
				//frequence de l'allele  j dans la population 2
				freqyjl = freqyjl * (*(tabfreq2[locus] + j));
//cerr << "DistancesGnt::r_dpopGoldsteinASD freqyjl" << freqyjl << endl;
				//freqyjl *= ((long double) ppop2->r_nbcopall(Pallj) / (long double) nballpop2);

				DblSommeij += (freqxil * freqyjl);
//cerr << "DistancesGnt::r_dpopGoldsteinASD DblSommeij" << DblSommeij << endl;
			}
		}

		//Slocus += (DblSommeij / nblocus);
		Slocus += DblSommeij;
//cerr << "DistancesGnt::r_dpopGoldsteinASD Slocus" << Slocus << endl;
	}

//	resultat = (long double)1 - (Sracinelocus * ((long double)1 / nblocus));
	if (nblocusdivise == 0) throw Anomalie(3);
	Slocus /= (long double) nblocusdivise;

	return (Slocus);
}


long double DistancesGnt::r_dpopGoldsteinMu(unsigned long pop1,unsigned long pop2) const {

	//distances de Goldstein et al. (1995a) entre 2 populations
	// deltaMu carre
	// tir� de Naoko Takezaki and Masatoshi Nei
	// "Genetic Distances and Reconstruction of Phylogenetic
	//        Trees From Microsatellite DNA"
	// Genetics society of America 144: 389-399.1996.

	long double Slocus(0);
	long double Mu2;
	unsigned long l, locus;
	unsigned long nblocus(_VcalcLocus.size()); // soit r
	unsigned long nblocusdivise;
	long double * tabmu1(_PtabMu + (pop1 * _nbloc));
	long double * tabmu2(_PtabMu + (pop2 * _nbloc));

	nblocusdivise = nblocus;

	for (l = 0; l < nblocus; l++) {
		// l numero du locus 
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		//Muxj = Muxj - Muyj;
		Mu2 = tabmu1[locus] - tabmu2[locus];
		Mu2 *= Mu2;

		//Slocus += (Muxj / nblocus);
		Slocus += Mu2;
	}

	if (nblocusdivise < 1) throw Anomalie(3);
	Slocus /= (long double) nblocusdivise;

//	resultat = (long double)1 - (Sracinelocus * ((long double)1 / nblocus));

	return (Slocus);
}


long double DistancesGnt::r_dpopZhivotovsky(unsigned long pop1,unsigned long pop2) const {

	//distances de Lev A. Zhivotovsky (1999) entre 2 populations
	// tir� de Lev A. Zhivotovsky
	// "A new Genetic Distance with Application to constrained 
	//       Variation at Microsatellite Loci"
	// Mol. Biol. Evol. 16(4) 144: 389-399.1996.

	long double Cab(0);
	long double MoyRa(0), MoyRb(0);
	long double SRa2(0), SRb2(0);
	unsigned long l, locus;
	unsigned long nblocus(_VcalcLocus.size());
	unsigned long nblocusdivise;
	long double * tabmu1(_PtabMu + (pop1 * _nbloc));
	long double * tabmu2(_PtabMu + (pop2 * _nbloc));

	nblocusdivise = nblocus;

//cerr << "zhivotovski deb" << endl;
	//ce calcul peut �tre externalis�
	for (l = 0; l < nblocus; l++) {
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		MoyRa += tabmu1[locus];
		MoyRb += tabmu2[locus];
		SRa2 += (tabmu1[locus] * tabmu1[locus]);
		SRb2 += (tabmu2[locus] * tabmu2[locus]);
		Cab += (tabmu1[locus] * tabmu2[locus]);
	}

	if (nblocusdivise < 1) throw Anomalie(3);

	MoyRa /= (long double) nblocusdivise;
	MoyRb /= (long double) nblocusdivise;
	//--------------

//cerr << Cab << " - " << (((long double) nblocus) * MoyRa * MoyRb) << endl;
	Cab -= (((long double) nblocusdivise) * MoyRa * MoyRb);
	Cab /= (long double)(nblocusdivise - 1);
	// c'est bon pour Cab
	// pour Va et Vb, utilisons respectivement SRa2 et SRb2
	SRa2 -= (((long double) nblocusdivise) * MoyRa * MoyRa);
	SRb2 -= (((long double) nblocusdivise) * MoyRb * MoyRb);
	SRa2 /= (long double)(nblocusdivise - 1);
	SRb2 /= (long double)(nblocusdivise - 1);

	SRa2 += SRb2;
	SRa2 /= (long double) 2;

//cerr << Cab << " " <<  SRa2 << endl;
	//Attention a l'approximation:
	if (Cab < 1) Cab = 1; //sans ca, ca risque de planter...
	Cab = ((long double) log(Cab / SRa2) * (long double)-1);

//cerr << "zhivotovski fin " << Cab << endl;
	return (Cab);

}

long double DistancesGnt::r_dpopNei(unsigned long pop1,unsigned long pop2, bool standard) const {
	//distances de Nei (1972) entre 2 populations (standard et minimum)
	// Ds et Dm
	// tir� de Jin et Chakraborty
	// mol.Biol. Evol. 11(1): 120-127.1994.
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));

//	long double * tabfreq1( _PtabFreq[(pop1 * _nbloc)]);
//	long double * tabfreq2( _PtabFreq[(pop2 * _nbloc)]);
//	tabfreq1 = *tabfreq1 + (pop1 * _nbloc);

	long double resultat(0), inter;
	long double Jx(0), Jy(0), Jxy(0);
	unsigned long i, l, locus;
	unsigned long nblocus(_VcalcLocus.size());
	unsigned long nblocusdivise;

	nblocusdivise = nblocus;
//	long nballdiff, nballpop1, nballpop2;
//	Allele * Pall;

	for (l = 0; l < nblocus; l++) {
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}
//		nballdiff = tabNbAll[locus];
		for (i = 0; i < _tabNbAll[locus]; i++) {
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;

			//frequence de l'allele  i dans la population 1
			inter = *(tabfreq1[locus] + i);
			resultat = inter * inter;
			Jx += resultat;

			//frequence de l'allele  i dans la population 2
			resultat = *(tabfreq2[locus] + i);
			inter = inter * resultat;
			resultat = resultat * resultat;
			Jy += resultat;

			Jxy += inter;
		}
	}
	if (nblocusdivise == 0) throw Anomalie(3);

	Jx /= (long double)nblocusdivise;
	Jy /= (long double)nblocusdivise;
	Jxy /= (long double)nblocusdivise;

	if (standard) {
		//resultat = ((log(Jx) + log(Jy)) / 2 ) - log(Jxy);
		//cerr << "Ds Nei " << endl;
		resultat = ( - log (Jxy/(sqrt(Jx * Jy))));
	}
	else {
		resultat = ((Jx + Jy) / 2 ) - Jxy;
	}

	return (resultat);
}


long double DistancesGnt::r_dpopNeiDa(unsigned long pop1,unsigned long pop2) const {

	//distances de Nei et al's, Da (1983) entre 2 populations
	// tir� de Naoko Takezaki and Masatoshi Nei
	// "Genetic Distances and Reconstruction of Phylogenetic
	//        Trees From Microsatellite DNA"
	// Genetics society of America 144: 389-399.1996.

	long double resultat(0);
	long double freqil;
	long double Sracinelocus(0);
	long double Sracinealleles(0);
//	long double pi(acos(-1));
	unsigned long i, l, locus;
	unsigned long nblocus(_VcalcLocus.size()); // soit r
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));


	nblocusdivise = nblocus;

	for (l = 0; l < nblocus; l++) {
		// l numero du locus 
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		Sracinealleles = 0;
		for (i = 0; i < _tabNbAll[locus]; i++) {
			//i numero de l'allele
			//Pall = _tabPloc[locus]->getPall(i);
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;

			//frequence de l'allele  i dans la population 1
			freqil = *(tabfreq1[locus] + i);
			//freqil = ((long double) ppop1->r_nbcopall(Pall) / (long double) nballpop1);

			//frequence de l'allele  i dans la population 2
			freqil *= *(tabfreq2[locus] + i);
			//freqil *= ((long double) ppop2->r_nbcopall(Pall) / (long double) nballpop2);

			Sracinealleles += (long double) sqrt(freqil);
		}

		Sracinelocus += Sracinealleles;
	}

	if (nblocusdivise < 1) throw Anomalie(3);
	resultat = (long double)1 - (Sracinelocus / (long double)nblocusdivise);

	return (resultat);
}

long double DistancesGnt::r_dpopPrevosti(unsigned long pop1,unsigned long pop2) const {

	//distances de Prevosti et al.'s, Cp (1975) entre 2 populations
	// tir� de Naoko Takezaki and Masatoshi Nei
	// "Genetic Distances and Reconstruction of Phylogenetic
	//        Trees From Microsatellite DNA"
	// Genetics society of America 144: 389-399.1996.

	long double freqil;
	long double Sracinelocus(0);
	long double Salleles(0);
	unsigned long i, l, locus;
	unsigned long nblocus(_VcalcLocus.size()); // soit r
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));

	nblocusdivise = nblocus;
	
	for (l = 0; l < nblocus; l++) {
		// l numero du locus 
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		Salleles = 0;
		for (i = 0; i < _tabNbAll[locus]; i++) {
			//i numero de l'allele
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;
			//frequence de l'allele  i dans la population 1
			freqil = *(tabfreq1[locus] + i);

			//frequence de l'allele  i dans la population 2
			freqil -= *(tabfreq2[locus] + i);

			Salleles += (freqil < 0)?((long double)-1 * freqil):(freqil);
		}

		//Sracinelocus += (Salleles / ((long double)2 * nblocus));
		Sracinelocus += Salleles;
	}

	if (nblocusdivise < 1) throw Anomalie(3);
	Sracinelocus /= (((long double)2 * (long double)nblocusdivise));

	return (Sracinelocus);
}


long double DistancesGnt::r_dpopRoger(unsigned long pop1,unsigned long pop2) const {

	//distances de Rogers', Dr (1972) entre 2 populations
	// tir� de Naoko Takezaki and Masatoshi Nei
	// "Genetic Distances and Reconstruction of Phylogenetic
	//        Trees From Microsatellite DNA"
	// Genetics society of America 144: 389-399.1996.

	long double freqil;
	long double Sracinelocus(0);
	long double Salleles(0);
	unsigned long i, l, locus;
	unsigned long nblocus(_VcalcLocus.size()); // soit r
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));


	nblocusdivise = nblocus;


	for (l = 0; l < nblocus; l++) {
		// l numero du locus 
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		Salleles = 0;
		for (i = 0; i < _tabNbAll[locus]; i++) {
			//i numero de l'allele
			//Pall = _tabPloc[locus]->getPall(i);
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;
			//frequence de l'allele  i dans la population 1
			freqil = *(tabfreq1[locus] + i);
			//freqil = ((long double) ppop1->r_nbcopall(Pall) / (long double) nballpop1);

			//frequence de l'allele  i dans la population 2
			freqil -= *(tabfreq2[locus] + i);
			//freqil -= ((long double) ppop2->r_nbcopall(Pall) / (long double) nballpop2);

			Salleles += freqil * freqil;
		}

		Sracinelocus += (long double)sqrt (Salleles / (long double)2);
	}

//	resultat = Sracinelocus * ((long double)2 / (pi * nblocus));

	if (nblocusdivise < 1) throw Anomalie(3);
	return (Sracinelocus / (long double) nblocusdivise);
}

long double DistancesGnt::r_dpopShriver(unsigned long pop1,unsigned long pop2) const {

	// Dsw Shriver et al's(1995)
	//distances de Shriver (1995) entre 2 populations
	// "A novel Measure of Genetic Distance for Highly Polymorphic Tandem Repeat Loci"
	// Mark D. Shriver, Li Jin, Eric Boerwinkle, Ranjan Deka, Robert E. Ferrell and Ranajit Chakraborty
	// Mol. Bio. Evol. 12(5):914-920. 1995.

	long double freqxil;
	long double freqxjl;
	long double freqyil;
	long double freqyjl;
	long double Resultat(0);
	int Absdiffij(0);
//	long double Wxy(0);
//	long double Wx(0);
//	long double Wy(0);
	long double SWxy(0);
	long double SWx(0);
	long double SWy(0);
//	long double pi(acos(-1));
	unsigned long i,j, l, locus;
	unsigned long nblocus(_VcalcLocus.size()); // soit r
//	long nploidie(get_nploidie());
//	long nballdiff, nballpop1, nballpop2;
	unsigned long nballdiff;
	unsigned long nbrepet;
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));

	nblocusdivise = nblocus;

	for (l = 0; l < nblocus; l++) {
		// l numero du locus 
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		nballdiff = _tabNbAll[locus];
		//SWxy = 0;
		//SWy = 0;
		//SWx = 0;
		for (i = 0; i < nballdiff; i++) {
			//Palli = _tabPloc[locus]->getPall(i);
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;

			//frequence de l'allele  i dans la population 1
			freqxil = *(tabfreq1[locus] + i);
			//freqxil = ((long double) ppop1->r_nbcopall(Palli) / (long double) nballpop1);
			//frequence de l'allele  i dans la population 2
			freqyil = *(tabfreq2[locus] + i);
			//freqyil = ((long double) ppop2->r_nbcopall(Palli) / (long double) nballpop2);

			nbrepet = _tabPloc[locus]->getPall(i)->_nbrepet;
			for (j = 0; j < nballdiff; j++) {
				//double somme
				if (i == j) continue;
				//Pallj = _tabPloc[locus]->getPall(j);
				if (_tabPloc[locus]->getPall(j)->_miss) continue;
				
//cerr << Palli->_nom << " " << Pallj->_nom << endl;
				Absdiffij = (int)nbrepet - (int)_tabPloc[locus]->getPall(j)->_nbrepet;
				Absdiffij = (Absdiffij < 0)?(-1 * Absdiffij):(Absdiffij);

				//frequence de l'allele  j dans la population 2
				freqyjl = *(tabfreq2[locus] + j);
				//freqyjl = ((long double) ppop2->r_nbcopall(Pallj) / (long double) nballpop2);
				//frequence de l'allele  j dans la population 1
				freqxjl = *(tabfreq1[locus] + j);
				//freqxjl = ((long double) ppop1->r_nbcopall(Pallj) / (long double) nballpop1);


				SWxy += freqxil * freqyjl * (long double)Absdiffij;
				SWx += freqxil * freqxjl * (long double)Absdiffij;
				SWy += freqyil * freqyjl * (long double)Absdiffij;
//cerr << SWxy << " " << SWx  << " " << SWy << endl;
			}
		}

		//Wxy += (SWxy / nblocus);
		//Wx += (SWx / nblocus);
		//Wy += (SWy / nblocus);
	}
//cin >> Resultat;

	if (nblocusdivise < 1) throw Anomalie(3);
	SWxy /= (long double) nblocusdivise;
	SWx /= (long double) nblocusdivise;
	SWy /= (long double) nblocusdivise;

	Resultat = SWxy - ((SWx + SWy)/(long double)2);

//	cerr << SWxy << " " << SWx  << " " << SWy  << " " << Resultat << endl;
//cin >> SWxy;

	return (Resultat);
}


inline void DistancesGnt::f_calcTabFreq() const{
	//calcul des frequences alleliques
	// tabPfreq contient les adresses de tableaux de frequences
	// tabNbAll contient le nombre d'alleles a chaque locus

	unsigned long nball, nballnonnuls;
	unsigned long i, j, k;

	long double* adresse(_PtabFreq[0]);

	for (i=0; i < _nbpop; i++) {
		for (j=0; j < _nbloc; j++) {
			nball = _tabNbAll[j];
			nballnonnuls = _tabPstrucpop[i]->r_nballnonnuls(j);
			if (nballnonnuls == 0) {
				_tabEviteLocus[(i*_nbloc)+j] = true; // calculs de fr�quences impossible sur ce locus

				for (k=0; k < nball; k++, adresse++) *adresse = 0;
				continue;
//				throw Anomalie(3, _tabPstrucpop[i]->get_nom());
			}

			for (k=0; k < nball; k++) {
				if (_tabPloc[j]->getPall(k)->_miss) *adresse = 0;
				else *adresse = (long double) _tabPstrucpop[i]->r_nbcopall(_tabPloc[j]->getPall(k)) / (long double) nballnonnuls;
				adresse++;
			}
		}
	}
}

void DistancesGnt::f_calcTabFreqTot() const{
	//calcul des frequences alleliques moyennes � chaque locus pour toutes les pops
	//�a ne sert pas pour l'instant (26/02/2002)
	unsigned long j,k,nball, nballnonnuls;
	MetaPop * Pracinepop(_Pjeupop->get_Pracinepop());
	long double* adresse(_PtabFreqTot);
	
	f_calcTabFreq();
	
	for (j=0; j < _nbloc; j++) {
		nball = _tabNbAll[j];
		nballnonnuls = Pracinepop->r_nballnonnuls(j);
		if (nballnonnuls == 0) {
			// calculs impossibles non trait�
			
			//_tabEviteLocus[(i*_nbloc)+j] = true; // calculs de fr�quences impossible sur ce locus
			
			//for (k=0; k < nball; k++, adresse++) *adresse = 0;
			//continue;
//				throw Anomalie(3, _tabPstrucpop[i]->get_nom());
		}

		for (k=0; k < nball; k++) {
			if (_tabPloc[j]->getPall(k)->_miss) *adresse = 0;
			else *adresse = (long double) Pracinepop->r_nbcopall(_tabPloc[j]->getPall(k)) / (long double) nballnonnuls;
			adresse++;
		}
	}
	
	
}

void DistancesGnt::f_calcTabFreqInd() const{
	//calcul des frequences alleliques
	// pour chaque individu
	// tabPfreq contient les adresses de tableaux de frequences
	// tabNbAll contient le nombre d'alleles a chaque locus
	// _tabEviteLocus contient les locus � �viter (qui ne contiennent que des all�les nuls)

	unsigned long nball, nballnonnuls;
	unsigned long nbind(_tabPind.size());
	unsigned int nploidie(_Pjeupop->get_nploidie());
	unsigned long i, j, k;

	long double* adresse(_PtabFreq[0]);

	for (i=0; i < nbind; i++) {
		for (j=0; j < _nbloc; j++) {
			nball = _tabNbAll[j];
			nballnonnuls = _tabPind[i]->r_nballnonnuls(j, nploidie);

			if (nballnonnuls == 0) {
				_tabEviteLocus[(i*_nbloc)+j] = true; // calculs de fr�quences impossible sur ce locus

				for (k=0; k < nball; k++, adresse++) *adresse = 0;
				continue;
			}

			for (k=0; k < nball; k++) {
				if (_tabPloc[j]->getPall(k)->_miss) *adresse = 0;
				else *adresse = (long double) _tabPind[i]->r_nbcopall(_tabPloc[j]->getPall(k)) / (long double) nballnonnuls;
				adresse++;
			}
		}
	}
}

void DistancesGnt::f_calcTabFreqBootInd() const{
	//calcul des frequences alleliques
	// tabPfreq contient les adresses de tableaux de frequences
	// tabNbAll contient le nombre d'alleles a chaque locus
	// sp�cifique aux calculs avec des bootstrap sur les individus

	unsigned long nball, nballnonnuls;
	unsigned long i, j, k;

	long double* adresse(_PtabFreq[0]);

//cerr << "f_calcTabFreqBootInd deb" << endl;
	for (i=0; i < _nbpop; i++) {
		_tabPstrucpop[i]->f_bootstrap();
		for (j=0; j < _nbloc; j++) {
			nball = _tabNbAll[j];
			nballnonnuls = _tabPstrucpop[i]->r_nballnonnulsBootInd(j);

			if (nballnonnuls == 0) {
				_tabEviteLocus[(i*_nbloc)+j] = true; // calculs de fr�quences impossible sur ce locus
				for (k=0; k < nball; k++, adresse++) *adresse = 0;
//cerr << "f_calcTabFreqBootInd" << endl;
				continue;
			}

			for (k=0; k < nball; k++) {
				if (_tabPloc[j]->getPall(k)->_miss) *adresse = 0;
				else *adresse = (long double) _tabPstrucpop[i]->r_nbcopallBootInd(_tabPloc[j]->getPall(k)) / (long double) nballnonnuls;
				adresse++;
			}
		}
	}
//cerr << "f_calcTabFreqBootInd fin" << endl;

}

inline void DistancesGnt::f_calcTabBootInd() const{
	//recalcul des tableaux
	switch (_methode) {
	case 106:
		// calculs des Mu
		f_calcTabMuBootInd();
		break;
	case 112:
		// calculs des Mu
		f_calcTabMuBootInd();
		break;

	default:
		// calculs des fr�quences
		f_calcTabFreqBootInd();
		break;
	}
}

void DistancesGnt::f_calcTabMu() const{
	//calcul des Mu (moyenne du nombre de repetitions (au sens
	//    microsat) pond�r�e par la frequence allelique pour chaque locus)
	// tabNbAll contient le nombre d'alleles a chaque locus

	unsigned long nball;
	long double nballnonnuls;
	unsigned long i, j, k;

	long double* adresse(_PtabMu);

	for (i=0; i < _nbpop; i++) {
		for (j=0; j < _nbloc; j++) {
			nball = _tabNbAll[j];
			nballnonnuls = (long double)  _tabPstrucpop[i]->r_nballnonnuls(j);
			if (nballnonnuls == 0) {
				_tabEviteLocus[(i*_nbloc)+j] = true; // calculs de fr�quences impossible sur ce locus

				for (k=0; k < nball; k++, adresse++) *adresse = 0;
				continue;
//				throw Anomalie(3, _tabPstrucpop[i]->get_nom());
			}
			*adresse = 0;

			for (k=0; k < nball; k++) {
				if (_tabPloc[j]->getPall(k)->_miss) continue;
				*adresse += (long double) _tabPloc[j]->getPall(k)->_nbrepet * ((long double) _tabPstrucpop[i]->r_nbcopall(_tabPloc[j]->getPall(k)) / nballnonnuls);
			}
			adresse++;
		}
	}
}

void DistancesGnt::f_calcTabMuInd() const{
	//calcul des Mu (moyenne du nombre de repetitions (au sens
	//    microsat) pond�r�e par la frequence allelique pour chaque locus)
	// tabNbAll contient le nombre d'alleles a chaque locus

	//pour chaque individu

	unsigned long nball;
	long double nballnonnuls;
	unsigned long nbind(_tabPind.size());
	unsigned int nploidie(_Pjeupop->get_nploidie());
	unsigned long i, j, k;

	long double* adresse(_PtabMu);

	for (i=0; i < nbind; i++) {
		for (j=0; j < _nbloc; j++) {
			nball = _tabNbAll[j];
			nballnonnuls = (long double) _tabPind[i]->r_nballnonnuls(j, nploidie);
			if (nballnonnuls == 0) {
				_tabEviteLocus[(i*_nbloc)+j] = true; // calculs de fr�quences impossible sur ce locus
				for (k=0; k < nball; k++, adresse++) *adresse = 0;
				continue;
			}

			*adresse = 0;

			for (k=0; k < nball; k++) {
				if (_tabPloc[j]->getPall(k)->_miss) continue;
				*adresse += (long double) _tabPloc[j]->getPall(k)->_nbrepet * ((long double) _tabPind[i]->r_nbcopall(_tabPloc[j]->getPall(k)) / nballnonnuls);
			}
			adresse++;
		}
	}
}

void DistancesGnt::f_calcTabMuBootInd() const{
	//calcul des Mu (moyenne du nombre de repetitions (au sens
	//    microsat) pond�r�e par la frequence allelique pour chaque locus)
	// tabNbAll contient le nombre d'alleles a chaque locus
	// sp�cifique aux calculs avec des bootstrap sur les individus


	unsigned long nball;
	long double nballnonnuls;
	unsigned long i, j, k;

	long double* adresse(_PtabMu);

	for (i=0; i < _nbpop; i++) {
		_tabPstrucpop[i]->f_bootstrap();
		for (j=0; j < _nbloc; j++) {
			nball = _tabNbAll[j];
			nballnonnuls = (long double) _tabPstrucpop[i]->r_nballnonnulsBootInd(j);
			if (nballnonnuls == 0) {
				_tabEviteLocus[(i*_nbloc)+j] = true; // calculs de fr�quences impossible sur ce locus
				for (k=0; k < nball; k++, adresse++) *adresse = 0;
				continue;
			}

			*adresse = 0;

			for (k=0; k < nball; k++) {
				if (_tabPloc[j]->getPall(k)->_miss) continue;
				*adresse += (long double) _tabPloc[j]->getPall(k)->_nbrepet * ((long double) _tabPstrucpop[i]->r_nbcopallBootInd(_tabPloc[j]->getPall(k)) / nballnonnuls);
			}
			adresse++;
		}
	}
}

void DistancesGnt::f_distgntIndVcalc (long double * Ptab) const{
	//distances G�n�tiques entre individus
	long nbind (_tabPind.size());
	long j,i;

	for (j = 0; j < nbind; j++) {
		for (i = 0; i < j; i++) {
			try {
				Ptab[(j * nbind) + i] = r_dist2ind(i, j);
				Ptab[(i * nbind) + j] = Ptab[(j * nbind) + i];
			}
			catch (Jeupop::Anomalie erreur) {
				if (erreur.le_pb == 6) {
					Ptab[(j * nbind) + i] = -1;
					Ptab[(i * nbind) + j] = Ptab[(j * nbind) + i];
				}
			}
		}
	}
//cerr << "f_distgntIndVcalc fin" << endl;

}

unsigned long DistancesGnt::get_nbind() const {
	unsigned long i, res(0);

	for (i = 0; i < _nbpop; i++) {
		res += _tabPstrucpop[i]->get_nbind();
	}
	return (res);
}


unsigned int DistancesGnt::get_nb_methodes() {
	if (_tab_noms_methodes.size() == 0) f_rempli_tab_noms_methodes();
	return(_tab_noms_methodes.size());
}

const string & DistancesGnt::get_nom_methode(unsigned int methode) {
	if (_tab_noms_methodes.size() == 0) f_rempli_tab_noms_methodes();
	if (methode > 100) methode -= 100;
	if (methode < _tab_noms_methodes.size()) return (_tab_noms_methodes[methode]);
	else throw Anomalie(6);
}

void DistancesGnt::f_rempli_tab_noms_methodes() {
//	_map_noms_methodes.resize(0);
	
/*	_map_noms_methodes[1] = string("Nei's minimum genetic distance, Dm (1972)");
	_map_noms_methodes[2] = string("Nei's standard genetic distance, Ds (1972)");
	_map_noms_methodes[3] = string("Cavalli-Sforza and Edwards, Dc (1967)"); //3
	//_map_noms_methodes[16] = string("Cavalli-Sforza and Edwards, Dc (1967)"); //3
	_map_noms_methodes[4] = string("Nei et al's, Da (1983)"); //4
	_map_noms_methodes[5] = string("DAS"); //5
	_map_noms_methodes[6] = string("Goldstein et al. , dmu2 (1995a)"); //6
	_map_noms_methodes[7] = string("Latter, Fst (1972)"); //7
	_map_noms_methodes[8] = string("Prevosti et al.'s, Cp (1975)"); //8
	_map_noms_methodes[9] = string("Rogers', Dr (1972)"); //9
	_map_noms_methodes[10] = string("Goldstein et al. (1995b) Slatkin, ASD (1995)"); //10
	_map_noms_methodes[11] = string("Shriver et al's, Dsw (1995)"); //11
	_map_noms_methodes[12] = string("Lev A. Zhivotovsky, DR (1999)"); //12
	_map_noms_methodes[13] = string("Reynolds J., unweighted (1983)"); //13
	_map_noms_methodes[14] = string("Reynolds J., weighted (1983)"); //14
	_map_noms_methodes[15] = string("Reynolds J., least squares (1983)"); //15

*/ 	_tab_noms_methodes.resize(0);
//	_tab_numeros_methodes.resize(0);
	_tab_noms_methodes.push_back(""); //0
	_tab_noms_methodes.push_back("Nei's minimum genetic distance, Dm (1972)"); //1
	_tab_noms_methodes.push_back("Nei's standard genetic distance, Ds (1972)"); //2
	_tab_noms_methodes.push_back("Cavalli-Sforza and Edwards, Dc (1967)"); //3
	_tab_noms_methodes.push_back("Nei et al's, Da (1983)"); //4
	_tab_noms_methodes.push_back("DAS"); //5
	_tab_noms_methodes.push_back("Goldstein et al. , dmu2 (1995a)"); //6
	_tab_noms_methodes.push_back("Latter, Fst (1972)"); //7
	_tab_noms_methodes.push_back("Prevosti et al.'s, Cp (1975)"); //8
	_tab_noms_methodes.push_back("Rogers', Dr (1972)"); //9
	_tab_noms_methodes.push_back("Goldstein et al. (1995b) Slatkin, ASD (1995)"); //10
	_tab_noms_methodes.push_back("Shriver et al's, Dsw (1995)"); //11
	_tab_noms_methodes.push_back("Lev A. Zhivotovsky, DR (1999)"); //12
	_tab_noms_methodes.push_back("Reynolds J., unweighted (1983)"); //13
	_tab_noms_methodes.push_back("Reynolds J., weighted (1983)"); //14
	_tab_noms_methodes.push_back("Reynolds J., least squares (1983)"); //15

}

long double DistancesGnt::r_dpopReynoldsUnweighted(unsigned long pop1,unsigned long pop2) const {

	//distance de Reynolds (1983) entre 2 populations
	// tir� de {Reynolds, J.} and {Weir, B.S.} and {Cockerham, C.}
	// "Estimation of the coancestry coefficient: basis for a short-term genetic distance"
	// Genetics society of America
	// 105: 767-779.1983.

	long double al, alpbl;
	long double sommeu(0);
	long double sommetheta(0);
	long double alpha1(0), alpha2(0);
	long double intermediaire;
	long double effpop1(_tabPstrucpop[pop1]->get_nbind()), effpop2(_tabPstrucpop[pop2]->get_nbind());
	// _nbpop => nombre de populations
	
	unsigned long i, l, locus;
	unsigned long nblocus(_VcalcLocus.size());
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));

	nblocusdivise = nblocus;
	
	for (l = 0; l < nblocus; l++) {
		// l numero du locus
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		sommeu = 0;
		alpha1 = 0;
		alpha2 = 0;
		
		for (i = 0; i < _tabNbAll[locus]; i++) {
			//i numero de l'allele
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;
			//frequence de l'allele  i dans la population 1
			alpha1 += ( (*(tabfreq1[locus] + i)) * (*(tabfreq1[locus] + i)) );

			//frequence de l'allele  i dans la population 2
			alpha2 += ( (*(tabfreq2[locus] + i)) * (*(tabfreq2[locus] + i)) );

			intermediaire = ((*(tabfreq1[locus] + i)) - (*(tabfreq2[locus] + i)));
			intermediaire *= intermediaire;
			sommeu += intermediaire;
		}
		sommeu /= ((long double) 2);
		
		alpha1 = (long double)1 - alpha1;
		alpha2 = (long double)1 - alpha2;
		
		al = (effpop1 * alpha1);
		al += (effpop2 * alpha2);
		al /= (((long double)4 * effpop1 * effpop2) * (effpop1 + effpop2 - (long double)1));
		
		alpbl = (((long double)4 * effpop1 * effpop2) - effpop1 - effpop2);
		alpbl *= al;
		
		al *= (effpop1 + effpop2);
		al *= (- (long double)1);
		
		al += sommeu;
		alpbl += sommeu;
		
		
		//Sracinelocus += (Salleles / ((long double)2 * nblocus));
		sommetheta += (al / alpbl);
	}

	if (nblocusdivise < 1) throw Anomalie(3);
	sommetheta /= ((long double)nblocusdivise);

	return ( - log ((long double)1 - sommetheta));
}

long double DistancesGnt::r_dpopReynoldsWeighted(unsigned long pop1,unsigned long pop2) const {

	//distance de Reynolds (1983) entre 2 populations
	// tir� de {Reynolds, J.} and {Weir, B.S.} and {Cockerham, C.}
	// "Estimation of the coancestry coefficient: basis for a short-term genetic distance"
	// Genetics society of America
	// 105: 767-779.1983.

	long double al, alpbl;
	long double sommeal(0);
	long double sommealpbl(0);
	long double sommeu(0);
	long double thetaw(0);
	long double alpha1(0), alpha2(0);
	long double intermediaire;
	long double effpop1(_tabPstrucpop[pop1]->get_nbind()), effpop2(_tabPstrucpop[pop2]->get_nbind());
	// _nbpop => nombre de populations
	
	unsigned long i, l, locus;
	unsigned long nblocus(_VcalcLocus.size());
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));

	nblocusdivise = nblocus;
	
	for (l = 0; l < nblocus; l++) {
		// l numero du locus
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		//sommeal = 0;
		//sommealpbl = 0;
		sommeu = 0;
		alpha1 = 0;
		alpha2 = 0;
		
		for (i = 0; i < _tabNbAll[locus]; i++) {
			//i numero de l'allele
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;
			//frequence de l'allele  i dans la population 1
			alpha1 += ( (*(tabfreq1[locus] + i)) * (*(tabfreq1[locus] + i)) );

			//frequence de l'allele  i dans la population 2
			alpha2 += ( (*(tabfreq2[locus] + i)) * (*(tabfreq2[locus] + i)) );

			intermediaire = ((*(tabfreq1[locus] + i)) - (*(tabfreq2[locus] + i)));
			intermediaire *= intermediaire;
			sommeu += intermediaire;
		}
		sommeu /= ((long double) 2);
		
		alpha1 = (long double)1 - alpha1;
		alpha2 = (long double)1 - alpha2;
		
		al = (effpop1 * alpha1);
		al += (effpop2 * alpha2);
		al /= (((long double)4 * effpop1 * effpop2) * (effpop1 + effpop2 - (long double)1));
		
		alpbl = (((long double)4 * effpop1 * effpop2) - effpop1 - effpop2);
		alpbl *= al;
		
		al *= (effpop1 + effpop2);
		al *= (- (long double)1);
		
		al += sommeu; // al
		alpbl += sommeu; // al + bl
		
		
		//Sracinelocus += (Salleles / ((long double)2 * nblocus));
		sommeal += al;
		sommealpbl += alpbl;
	}

	if (nblocusdivise < 1) throw Anomalie(3);
	thetaw = sommeal / sommealpbl;

	return ( - log ((long double)1 - thetaw));
}


long double DistancesGnt::r_dpopReynoldsLeast(unsigned long pop1,unsigned long pop2) const {

	//distance de Reynolds (1983) entre 2 populations
	// tir� de {Reynolds, J.} and {Weir, B.S.} and {Cockerham, C.}
	// "Estimation of the coancestry coefficient: basis for a short-term genetic distance"
	// Genetics society of America
	// 105: 767-779.1983.

	long double al, alpbl, bl;
	long double sommealcarre(0);
	long double sommeblcarre(0);
	long double sommealbl(0);
	long double sommeu(0);
	long double thetal1(0);
	long double thetal2(0);
	long double alpha1(0), alpha2(0);
	long double intermediaire;
	long double effpop1(_tabPstrucpop[pop1]->get_nbind()), effpop2(_tabPstrucpop[pop2]->get_nbind());
	// _nbpop => nombre de populations
	
	unsigned long i, l, locus;
	unsigned long nblocus(_VcalcLocus.size());
	unsigned long nblocusdivise;
	long double ** tabfreq1;
	long double ** tabfreq2;
	tabfreq1 = (_PtabFreq + (pop1 * _nbloc));
	tabfreq2 = (_PtabFreq + (pop2 * _nbloc));

	nblocusdivise = nblocus;
	
	for (l = 0; l < nblocus; l++) {
		// l numero du locus
		locus = _VcalcLocus[l];
		if ((_tabEviteLocus[(pop1 * _nbloc) + locus]) || (_tabEviteLocus[(pop2 * _nbloc) + locus])) {
			nblocusdivise--;
			continue;
		}

		//sommealcarre = 0;
		//sommeblcarre = 0;
		//sommealpbl = 0;
		sommeu = 0;
		alpha1 = 0;
		alpha2 = 0;
		
		for (i = 0; i < _tabNbAll[locus]; i++) {
			//i numero de l'allele
			if (_Pjeupop->_tabPloc[locus]->getPall(i)->_miss) continue;
			//frequence de l'allele  i dans la population 1
			alpha1 += ( (*(tabfreq1[locus] + i)) * (*(tabfreq1[locus] + i)) );

			//frequence de l'allele  i dans la population 2
			alpha2 += ( (*(tabfreq2[locus] + i)) * (*(tabfreq2[locus] + i)) );

			intermediaire = ((*(tabfreq1[locus] + i)) - (*(tabfreq2[locus] + i)));
			intermediaire *= intermediaire;
			sommeu += intermediaire;
		}
		sommeu /= ((long double) 2);
		
		alpha1 = (long double)1 - alpha1;
		alpha2 = (long double)1 - alpha2;
		
		al = (effpop1 * alpha1);
		al += (effpop2 * alpha2);
		al /= (((long double)4 * effpop1 * effpop2) * (effpop1 + effpop2 - (long double)1));
		
		alpbl = (((long double)4 * effpop1 * effpop2) - effpop1 - effpop2);
		alpbl *= al;
		
		al *= (effpop1 + effpop2);
		al *= (- (long double)1);
		
		al += sommeu; // al
		alpbl += sommeu; // al + bl
		bl = alpbl - al; // bl
		
		
		//Sracinelocus += (Salleles / ((long double)2 * nblocus));
		sommealcarre += (al * al);
		sommealbl += (al * bl);
		sommeblcarre += (bl * bl);
	}

	if (nblocusdivise < 1) throw Anomalie(3);
	
//cerr << "DistancesGnt::r_dpopReynoldsLeast" << endl;	
	//caclcul des 2 solutions possibles
	intermediaire = (long double)2 * (sommeblcarre - sommealcarre);
	al = (((long double)2 * sommealbl) + sommeblcarre + sommealcarre);
	bl = sqrt(((sommealcarre - sommeblcarre)*(sommealcarre - sommeblcarre)) + ( (long double)4 * sommealbl * sommealbl) );
	thetal1 = (al + bl) / intermediaire;
	thetal2 = (al - bl) / intermediaire;
	
//cerr << "numerateur de theta: " << intermediaire << endl;	
	
	// calcul des "Residual sum of squares" pour pouvoir choisir thetal1 ou thetal2
	alpbl = ((long double)2 * sommealbl) + sommealcarre + sommeblcarre;
	
	//al devient la Residual sum of squares 1
	intermediaire = ((long double)1 - ((long double)2 * thetal1) + ((long double)2 * thetal1 * thetal1));

//cerr << "numerateur de R1: " << intermediaire << endl;	
	al = ((alpbl * thetal1 * thetal1) - ((long double)2 * (sommealbl + sommealcarre) * thetal1) + sommealcarre) / intermediaire;
	
	//bl devient la Residual sum of squares 2
	intermediaire = ((long double)1 - ((long double)2 * thetal2) + ((long double)2 * thetal2 * thetal2));
//cerr << "numerateur de R2: " << intermediaire << endl;	
	bl = ((alpbl * thetal2 * thetal2) - ((long double)2 * (sommealbl + sommealcarre) * thetal2) + sommealcarre) / intermediaire;
	
	//calculs des distances:
//cerr << "thetal1: " << thetal1 << " thetal2: " << thetal2 << endl;	

//cerr << "D1: " << thetal1 << " D2: " << thetal2 << endl;	
//cerr << "R1: " << al << " R2: " << bl << endl;	
	if ((al < bl) && (thetal1 < 1)) return (- log ((long double)1 - thetal1));
	else if (thetal2 < 1) return (- log ((long double)1 - thetal2));
	else throw Anomalie(5);
}
