void BetaShifted_HGVolatilityParam::initializeShiftMatrix(
	LMMTenorStructure_PTR        pLMMTenorStructure, 
	const LowerTriangularMatrix& betas, 
	const std::vector<double>&   liborsInitValues)
{
	assert(betas.size1() == betas.size2() && betas.size2() == liborsInitValues.size() && pLMMTenorStructure->get_nbLIBOR());

	//unused first column, first row is automatically null since it is lower triangular matrix
	LowerTriangularMatrix m(betas.size1(), betas.size2());

	for(size_t k=0; k<m.size1();++k)
	{
		shift_matrix_(k,0) = 1.0e100;	
	}

	for(size_t liborIndex=1; liborIndex<m.size1();++liborIndex)
	{
		for(size_t timeIndex=1;timeIndex<=liborIndex;++timeIndex)
		{
			double beta = betas(liborIndex,timeIndex);
			double liborInitValue = liborsInitValues[liborIndex];
			shift_matrix_(liborIndex,timeIndex) = 1+ (1-beta)/beta*liborInitValue;
		}	
	} 
}
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;
}