#include "stdafx.h"
#include "DBLMath.h"	// For POW2.
#include "Cardano.h"	// For FCCardano.
#include "Ferrari.h"	// This header.

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//----- 05.04.01 Fukushiro M. _xZkqqHx_iNoNiPjMiOgO_xHqqkZx_ ()-----
//class myLess
//{
//public:
//	bool operator () (const dblcompex& c0, const dblcompex& c1) const
//	{
//		if (almostless(c0.real(), c1.real())) return true;
//		if (almostless(c1.real(), c0.real())) return false;
//		return almostless(c0.imag(), c1.imag()) ? true : false;
//	}
//}; // class myLess.
//----- 05.04.01 Fukushiro M. _xZkqqHx_iNoNiPjMiPeJ_xHqqkZx_ ()-----

/*************************************************************************
 * <_xZkqqHx_iKnGjAjE_xHqqkZx_>	FCFerrari::Set
 *
 * <_xZkqqHx_iLeAjEfM_xHqqkZx_>	_xZkqqHx_jFpLjCpGiOkOiCpAjAnNjCoIiClHiCoJiBeC_xHqqkZx_
 *
 * <_xZkqqHx_iIpIjAjE_xHqqkZx_>	a	:_xZkqqHx_iCfDiOjPiNiAiCmMiMfHjAjEiCpAiOhHjCoIiBeC_xHqqkZx_
 *			b	:_xZkqqHx_iCfCiOjPiNiAiCmMiMfHjAjEiCpAiOhHjCoIiBeC_xHqqkZx_
 *			c	:_xZkqqHx_iCfBiOjPiNiAiCmMiMfHjAjEiCpAiOhHjCoIiBeC_xHqqkZx_
 *			d	:_xZkqqHx_iCfAiOjPiNiAiCmMiMfHjAjEiCpAiOhHjCoIiBeC_xHqqkZx_
 *			e	:_xZkqqHx_iCePiOjPiNiAiCmMiMfHjAjEiCpAiOhHjCoIiBeC_xHqqkZx_
 *
 * <_xZkqqHx_iJpAjAoA_xHqqkZx_>	_xZkqqHx_jFmPjAjE_xHqqkZx_x_xZkqqHx_iCmJjBmOiClHiCoJiCfDiOjPjFpLjCpGiOkO_xHqqkZx_ ax^4+bx^3+cx^2+dx+e=0 _xZkqqHx_iCmMiKgFiMfHjAjEiCpAjAnNjCoIiClHiCoJiBeC_xHqqkZx_
 *
 * <_xZkqqHx_jHjKjHpA_xHqqkZx_>	05.04.01 Fukushiro M. _xZkqqHx_iNoMjAkM_xHqqkZx_
 *************************************************************************/
void FCFerrari::Set (double a, double b, double c, double d, double e)
{
	m_dA = a;
	m_dB = b;
	m_dC = c;
	m_dD = d;
	m_dE = e;
} // FCFerrari::Set.

/*************************************************************************
 * <_xZkqqHx_iKnGjAjE_xHqqkZx_>	FCFerrari::Solve
 *
 * <_xZkqqHx_iLeAjEfM_xHqqkZx_>	_xZkqqHx_jFpLjCpGiOkOiCmMiJpAiCpAiLiBiCnPiCoJiBeC_xHqqkZx_
 *
 * <_xZkqqHx_jFnEjCgM_xHqqkZx_>	_xZkqqHx_iJpAiCmMjAjEiBeC_xHqqkZx_
 *
 * <_xZkqqHx_iJpAjAoA_xHqqkZx_>	Set_xZkqqHx_iKnGjAjEiCmFjAnNjCoIiClDiCoKiClNjFpLjCpGiOkOiCpAiJpAiCkNiBeC_xHqqkZx_\doc\_xZkqqHx_iDhIiDfHiDeHiLmIjApM_xHqqkZx_\_xZkqqHx_iCmM_xHqqkZx_
 *			_xZkqqHx_iDhEiDeGiDiJiDiKjGeAiKnGjIeBiOjBjHlPiCpAiOfBiPmGiBeC_xHqqkZx_
 *
 * <_xZkqqHx_jHjKjHpA_xHqqkZx_>	05.04.01 Fukushiro M. _xZkqqHx_iNoMjAkM_xHqqkZx_
 *************************************************************************/
long FCFerrari::Solve ()
{
	if (almost0(m_dA))
	//----- a=0_xZkqqHx_iCmMiPoKiNiH_xHqqkZx_ -----
	{
		// bx^3+cx^2+dx+e=0 _xZkqqHx_iCmGiCkCiCkEiOjPjFpLjCpGiOkOiCmGiCmIiCoJiCmMiCmFiBeB_xHqqkZx_
		// _xZkqqHx_iDeKiDiLiDfPiDgNiCmMiCfCiOjPjFpLjCpGiOkOiJpAjGeAiCmFiJpAiCkNiBeC_xHqqkZx_
		FCCardano cd;
		cd.Set(m_dB, m_dC, m_dD, m_dE);
		const long lCount = cd.Solve();
		for (long lC = 0; lC != lCount; lC++)
			m_cSol[lC] = cd.m_cSol[lC];
		return lCount;
	}
	const double dB = m_dB / m_dA;
	const double dC = m_dC / m_dA;
	const double dD = m_dD / m_dA;
	const double dE = m_dE / m_dA;

//----- 05.04.13 Fukushiro M. _xZkqqHx_jFmPiNfIjBeP_xHqqkZx_ ()-----
//	double dAlpha = -3.0 * POW2(dB) / 8.0 + dC;
//	double dBeta = POW3(dB) / 8.0 - dB * dC / 2.0 + dD;
//	double dGamma = -3.0 * POW4(dB) / 256.0 + dC * POW2(dB) / 16.0 - dB * dD / 4.0 + dE;
//
//	FCCardano cd;
//	cd.Set(	1.0,
//			5.0 / 2.0 * dAlpha,
//			2.0 * POW2(dAlpha) - dGamma,
//			POW3(dAlpha) / 2.0 - dAlpha * dGamma / 2.0 - POW2(dBeta) / 8.0);
//	cd.Solve();
//----- 05.04.13 Fukushiro M. _xZkqqHx_jFmPiNfIiMoD_xHqqkZx_ ()-----
	double dAlpha = -3.0 * dB * (dB / 8.0) + dC;
	double dBeta = POW3(dB / 2.0) - dB * dC / 2.0 + dD;
	double dGamma = -3.0 * POW4(dB / 4.0) + dC * POW2(dB / 4.0) - dB * dD / 4.0 + dE;

	FCCardano cd;
	cd.Set(	1.0,
			5.0 / 2.0 * dAlpha,
			2.0 * POW2(dAlpha) - dGamma,
			POW2(dAlpha) * (dAlpha / 2.0) - dAlpha * dGamma / 2.0 - dBeta * (dBeta / 8.0));
	cd.Solve();
//----- 05.04.13 Fukushiro M. _xZkqqHx_jFmPiNfIiPeJ_xHqqkZx_ ()-----

//----- 05.03.22 Fukushiro M. _xZkqqHx_iNoNiPjMiOgO_xHqqkZx_ ()-----
//	set< dblcompex, myLess > stSol;
//	for (long lC = 0; lC != 3; lC++)
//	{
//		dblcompex& cY = cd.m_cSol[lC];
//		dblcompex cM = sqrt(dAlpha + 2.0 * cY);
//		dblcompex cX1 = -dB / 4.0 + (cM + sqrt(-(3.0 * dAlpha + 2.0 * cY + 2.0 * dBeta / cM))) / 2.0;
//		dblcompex cX2 = -dB / 4.0 + (-cM + sqrt(-(3.0 * dAlpha + 2.0 * cY - 2.0 * dBeta / cM))) / 2.0;
//		dblcompex cX3 = -dB / 4.0 + (cM - sqrt(-(3.0 * dAlpha + 2.0 * cY + 2.0 * dBeta / cM))) / 2.0;
//		dblcompex cX4 = -dB / 4.0 + (-cM - sqrt(-(3.0 * dAlpha + 2.0 * cY - 2.0 * dBeta / cM))) / 2.0;
//		stSol.insert(cX1);
//		stSol.insert(cX2);
//		stSol.insert(cX3);
//		stSol.insert(cX4);
//	}
//----- 05.03.22 Fukushiro M. _xZkqqHx_iNoNiPjMiPeJ_xHqqkZx_ ()-----
	dblcompex& cY = cd.m_cSol[0];
	// pow(x, 1.0/3.0)_xZkqqHx_iCmNiBeB_xHqqkZx_x.imag = 0, x.real < 0 _xZkqqHx_iClOiCmGjAlDiClFiCkCiJpAiCpAiPgPiClDiCmIiCkCiCkKiBeB_xHqqkZx_
	// sqrt(x)_xZkqqHx_iCmNiBeB_xHqqkZx_x.imag = 0, x.real < 0 _xZkqqHx_iCmFiCkAiCmBiCmEiCoAjAlDiClFiCkCiJpAiCpAiPgPiClHiBeC_xHqqkZx_
	dblcompex cM = sqrt(dAlpha + 2.0 * cY);
	m_cSol[0] = -dB / 4.0 + (cM + sqrt(-(3.0 * dAlpha + 2.0 * cY + 2.0 * dBeta / cM))) / 2.0;
	m_cSol[1] = -dB / 4.0 + (-cM + sqrt(-(3.0 * dAlpha + 2.0 * cY - 2.0 * dBeta / cM))) / 2.0;
	m_cSol[2] = -dB / 4.0 + (cM - sqrt(-(3.0 * dAlpha + 2.0 * cY + 2.0 * dBeta / cM))) / 2.0;
	m_cSol[3] = -dB / 4.0 + (-cM - sqrt(-(3.0 * dAlpha + 2.0 * cY - 2.0 * dBeta / cM))) / 2.0;
	return 4;
} // FCFerrari::Solve.

