📄 mgcspecialfunction.cpp
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement. The various license agreements may be found at
// the Magic Software web site. This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License/free.pdf
#include "MgcSpecialFunction.h"
//---------------------------------------------------------------------------
MgcReal MgcSpecialFunction::LogGamma (MgcReal fX)
{
static const MgcReal s_afCoeff[6] =
{
76.18009173, -86.50532033, 24.01409822, -1.231739516,
0.120858003e-2, -0.536382e-5
};
fX -= 1.0;
MgcReal fTmp = fX + 5.5;
fTmp -= (fX+0.5)*MgcMath::Log(fTmp);
MgcReal fSeries = 1.0;
for (int j = 0; j <= 5; j++)
{
fX += 1.0;
fSeries += s_afCoeff[j]/fX;
}
return -fTmp + MgcMath::Log(2.50662827465*fSeries);
}
//---------------------------------------------------------------------------
MgcReal MgcSpecialFunction::Gamma (MgcReal fX)
{
return MgcMath::Exp(LogGamma(fX));
}
//---------------------------------------------------------------------------
MgcReal MgcSpecialFunction::IncompleteGammaS (MgcReal fA, MgcReal fX)
{
const int iMaxIterations = 100;
const MgcReal fTolerance = 3e-07;
if ( fX > 0.0 )
{
MgcReal fAp = fA;
MgcReal fSum = 1.0/fA, fDel = fSum;
for (int i = 1; i <= iMaxIterations; i++)
{
fAp += 1.0;
fDel *= fX/fAp;
fSum += fDel;
if ( MgcMath::Abs(fDel) < MgcMath::Abs(fSum)*fTolerance )
{
MgcReal fArg = -fX+fA*MgcMath::Log(fX)-LogGamma(fA);
return fSum*MgcMath::Exp(fArg);
}
}
}
if ( fX == 0.0 )
return 0.0;
return MgcMath::INFINITY; // LogGamma not defined for x < 0
}
//---------------------------------------------------------------------------
MgcReal MgcSpecialFunction::IncompleteGammaCF (MgcReal fA, MgcReal fX)
{
const int iMaxIterations = 100;
const MgcReal fTolerance = 3e-07;
MgcReal fA0 = 1.0, fA1 = fX;
MgcReal fB0 = 0, fB1 = 1.0;
MgcReal fGold = 0.0, fFac = 1.0;
for (int i = 1; i <= iMaxIterations; i++)
{
MgcReal fI = (MgcReal) i;
MgcReal fImA = fI - fA;
fA0 = (fA1 + fA0*fImA)*fFac;
fB0 = (fB1 + fB0*fImA)*fFac;
MgcReal fItF = fI*fFac;
fA1 = fX*fA0 + fItF*fA1;
fB1 = fX*fB0 + fItF*fB1;
if ( fA1 != 0.0 )
{
fFac = 1.0/fA1;
MgcReal fG = fB1*fFac;
if ( MgcMath::Abs((fG-fGold)/fG) < fTolerance)
{
MgcReal fArg = -fX + fA*MgcMath::Log(fX) - LogGamma(fA);
return fG*MgcMath::Exp(fArg);
}
fGold = fG;
}
}
return MgcMath::INFINITY; // numerical error if you get here
}
//---------------------------------------------------------------------------
MgcReal MgcSpecialFunction::IncompleteGamma (MgcReal fA, MgcReal fX)
{
if ( fX < 1.0 + fA )
return IncompleteGammaS(fA,fX);
else
return 1-IncompleteGammaCF(fA,fX);
}
//---------------------------------------------------------------------------
MgcReal MgcSpecialFunction::Erf (MgcReal fX)
{
return 1-Erfc(fX);
}
//---------------------------------------------------------------------------
MgcReal MgcSpecialFunction::Erfc (MgcReal fX)
{
static const MgcReal s_afCoeff[10] =
{
-1.26551223, 1.00002368, 0.37409196, 0.09678418, -0.18628806,
0.27886807, -1.13520398, 1.48851587, -0.82215223, 0.17087277
};
MgcReal fZ = MgcMath::Abs(fX);
MgcReal fT = 1.0/(1.0+0.5*fZ);
MgcReal fSum = s_afCoeff[9];
for (int i = 9; i >= 0; i--)
fSum = fT*fSum + s_afCoeff[i];
MgcReal fResult = fT*MgcMath::Exp(-fZ*fZ + fSum);
return fX >= 0.0 ? fResult : 2.0 - fResult;
}
//---------------------------------------------------------------------------
MgcReal MgcSpecialFunction::ModBessel0 (MgcReal fX)
{
if ( fX < 0.0 ) // function is even
fX = -fX;
MgcReal fT, fResult;
int i;
if ( fX <= 3.75 )
{
static const MgcReal s_afCoeff[7] =
{
+1.0000000, +3.5156229, +3.0899424, +1.2067492, +0.2659732,
+0.0360768, +0.0045813
};
fT = fX/3.75;
MgcReal fT2 = fT*fT;
fResult = s_afCoeff[6];
for (i = 5; i >= 0; i--)
{
fResult *= fT2;
fResult += s_afCoeff[i];
}
// |error| < 1.6e-07
}
else
{
static const MgcReal s_afCoeff[9] =
{
+0.39894228, +0.01328592, +0.00225319, -0.00157565, +0.00916281,
-0.02057706, +0.02635537, -0.01647633, +0.00392377
};
fT = fX/3.75;
MgcReal fInvT = 1.0/fT;
fResult = s_afCoeff[8];
for (i = 7; i >= 0; i--)
{
fResult *= fInvT;
fResult += s_afCoeff[i];
}
fResult *= MgcMath::Exp(fX);
fResult /= MgcMath::Sqrt(fX);
// |error| < 1.9e-07
}
return fResult;
}
//---------------------------------------------------------------------------
MgcReal MgcSpecialFunction::ModBessel1 (MgcReal fX)
{
int iSign;
if ( fX > 0.0 )
{
iSign = 1;
}
else if ( fX < 0.0 )
{
fX = -fX;
iSign = -1;
}
else
{
return 0.0;
}
MgcReal fT, fResult;
int i;
if ( fX <= 3.75 )
{
static const MgcReal s_afCoeff[7] =
{
+0.50000000, +0.87890549, +0.51498869, +0.15084934,
+0.02658733, +0.00301532, +0.00032411
};
fT = fX/3.75;
MgcReal fT2 = fT*fT;
fResult = s_afCoeff[6];
for (i = 5; i >= 0; i--)
{
fResult *= fT2;
fResult += s_afCoeff[i];
}
fResult *= fX;
// |error| < 8e-09
}
else
{
static const MgcReal s_afCoeff[9] =
{
+0.39894228, -0.03988024, -0.00362018, +0.00163801, -0.01031555,
+0.02282967, -0.02895312, +0.01787654, -0.00420059
};
fT = fX/3.75;
MgcReal fInvT = 1.0/fT;
fResult = s_afCoeff[8];
for (i = 7; i >= 0; i--)
{
fResult *= fInvT;
fResult += s_afCoeff[i];
}
fResult *= MgcMath::Exp(fX);
fResult /= MgcMath::Sqrt(fX);
// |error| < 2.2e-07
}
fResult *= iSign;
return fResult;
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -