// we need next two functions only for verification of lucky method in debugging mode 
void swapAndFlip(word* pAfter, int nVars, int iVarInPosition, int jVar, char * pCanonPerm, unsigned* pUCanonPhase)
{
    int Temp;
    swap_ij(pAfter, nVars, iVarInPosition, jVar);
    
    Temp = pCanonPerm[iVarInPosition];
    pCanonPerm[iVarInPosition] = pCanonPerm[jVar];
    pCanonPerm[jVar] = Temp;
    
    if ( ((*pUCanonPhase & (1 << iVarInPosition)) > 0) != ((*pUCanonPhase & (1 << jVar)) > 0) )
    {
        *pUCanonPhase ^= (1 << iVarInPosition);
        *pUCanonPhase ^= (1 << jVar);
    }
    if((*pUCanonPhase>>iVarInPosition) & 1)
        Kit_TruthChangePhase_64bit( pAfter, nVars, iVarInPosition );
    
}
UpperTriangleVanillaSwaptionQuotes_ConstPTR UpperTriangleVanillaSwaptionQuotes::create_ATMSwaptionImpliedVol
	(
	LiborQuotes_ConstPTR libor_quotes_ptr,
	const Tenor&  fixedTenor,
	const Tenor&  floatingTenor,
	LmmVanillaSwaptionApproxPricer_Rebonato_PTR black_vol_approx_ptr,
	const double&  strike_bump
	)
{
	LMMTenorStructure_PTR pLMMTenorStructure = libor_quotes_ptr->get_LMMTenorStructure_PTR() ;
	size_t fix_float_ratio = fixedTenor.ratioTo(floatingTenor);
	size_t lastLiborIndex  = pLMMTenorStructure->get_nbLIBOR()-1;
	assert(lastLiborIndex%fix_float_ratio == 0);
	size_t last_year = lastLiborIndex / fix_float_ratio ;

	size_t matrix_size = last_year + 1 ;
	UpperTriangularDoubleMatrix swap_rate_matrix(matrix_size,matrix_size);
	UpperTriangularDoubleMatrix black_vol_matrix(matrix_size,matrix_size);

	//first row and first column never used
	for(size_t k=0;k<matrix_size;++k)
	{
		swap_rate_matrix(k,0) = -1000000; swap_rate_matrix(0,k) = -1000000;
		black_vol_matrix(k,0) = -1000000; black_vol_matrix(0,k) = -1000000;
	}


	const std::vector<double> & init_libor = libor_quotes_ptr->get_InitLibor();
	LmmVanillaSwapPricer swap_pricer(pLMMTenorStructure);
	for(size_t iMaturity=1;iMaturity<matrix_size;++iMaturity)
	{
		for(size_t jTenor=1;jTenor<matrix_size - iMaturity ;++jTenor)
		{
			size_t start_swap_index = iMaturity * fix_float_ratio;
			size_t end_swap_index   = (iMaturity+jTenor) * fix_float_ratio;	

			double empty_strike = -100000000;
			VanillaSwap swap_ij(empty_strike,start_swap_index,end_swap_index,floatingTenor,fixedTenor,pLMMTenorStructure);
			double swap_rate_ij = strike_bump+swap_pricer.swapRate_Analytical(swap_ij,init_libor);

			swap_ij.set_strike(swap_rate_ij);
			swap_rate_matrix(iMaturity,jTenor) = swap_rate_ij;

			VanillaSwaption swaption_ij(swap_ij, OptionType::OptionType::CALL);
			double black_vol_ij = black_vol_approx_ptr->volBlack(swaption_ij,init_libor);

			black_vol_matrix(iMaturity,jTenor)=black_vol_ij;
		}
	}

	UpperTriangleVanillaSwaptionQuotes_PTR atm_swaption_implied_vol 
		(new UpperTriangleVanillaSwaptionQuotes(
		pLMMTenorStructure,
		last_year,
		fixedTenor,
		floatingTenor,
		swap_rate_matrix,
		black_vol_matrix
		) 
		);

	atm_swaption_implied_vol->set_Data_FileName("VirtuallyCreatedData");

	return atm_swaption_implied_vol;
}