View | Details | Raw Unified | Return to issue 121561
Collapse All | Expand All

(-)sc/source/core/tool/interpr3.cxx (-70 / +5 lines)
Lines 46-51 Link Here
46
46
47
#include <boost/math/special_functions/atanh.hpp>
47
#include <boost/math/special_functions/atanh.hpp>
48
#include <boost/math/special_functions/expm1.hpp>
48
#include <boost/math/special_functions/expm1.hpp>
49
#include <boost/math/special_functions/gamma.hpp>
49
#include <boost/math/special_functions/log1p.hpp>
50
#include <boost/math/special_functions/log1p.hpp>
50
51
51
using ::std::vector;
52
using ::std::vector;
Lines 577-667 Link Here
577
    return fSumNum/fSumDenom;
578
    return fSumNum/fSumDenom;
578
}
579
}
579
580
580
// The algorithm is based on tgamma in gamma.hpp
581
// in math library from http://www.boost.org
582
/** You must ensure fZ>0; fZ>171.624376956302 will overflow. */
583
double lcl_GetGammaHelper(double fZ)
584
{
585
    double fGamma = lcl_getLanczosSum(fZ);
586
    const double fg = 6.024680040776729583740234375;
587
    double fZgHelp = fZ + fg - 0.5;
588
    // avoid intermediate overflow
589
    double fHalfpower = pow( fZgHelp, fZ / 2 - 0.25);
590
    fGamma *= fHalfpower;
591
    fGamma /= exp(fZgHelp);
592
    fGamma *= fHalfpower;
593
    if (fZ <= 20.0 && fZ == ::rtl::math::approxFloor(fZ))
594
        fGamma = ::rtl::math::round(fGamma);
595
    return fGamma;
596
}
597
581
598
// The algorithm is based on tgamma in gamma.hpp
599
// in math library from http://www.boost.org
600
/** You must ensure fZ>0 */
601
double lcl_GetLogGammaHelper(double fZ)
602
{
603
    const double fg = 6.024680040776729583740234375;
604
    double fZgHelp = fZ + fg - 0.5;
605
    return log( lcl_getLanczosSum(fZ)) + (fZ-0.5) * log(fZgHelp) - fZgHelp;
606
}
607
608
/** You must ensure non integer arguments for fZ<1 */
582
/** You must ensure non integer arguments for fZ<1 */
609
double ScInterpreter::GetGamma(double fZ)
583
double ScInterpreter::GetGamma(double fZ)
610
{
584
{
611
    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetGamma" );
585
    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "bst", "ScInterpreter::GetGamma" );
612
    const double fLogPi = log(F_PI);
613
    const double fLogDblMax = log( ::std::numeric_limits<double>::max());
614
615
    if (fZ > fMaxGammaArgument)
586
    if (fZ > fMaxGammaArgument)
616
    {
587
    {
617
        SetError(errIllegalFPOperation);
588
        SetError(errIllegalFPOperation);
618
        return HUGE_VAL;
589
        return HUGE_VAL;
619
    }
590
    }
620
591
    return ::boost::math::tgamma(fZ);
621
    if (fZ >= 1.0)
622
        return lcl_GetGammaHelper(fZ);
623
624
    if (fZ >= 0.5)  // shift to x>=1 using Gamma(x)=Gamma(x+1)/x
625
        return lcl_GetGammaHelper(fZ+1) / fZ;
626
627
    if (fZ >= -0.5) // shift to x>=1, might overflow
628
    {
629
        double fLogTest = lcl_GetLogGammaHelper(fZ+2) - log(fZ+1) - log( fabs(fZ));
630
        if (fLogTest >= fLogDblMax)
631
        {
632
            SetError( errIllegalFPOperation);
633
            return HUGE_VAL;
634
        }
635
        return lcl_GetGammaHelper(fZ+2) / (fZ+1) / fZ;
636
    }
637
    // fZ<-0.5
638
    // Use Euler's reflection formula: gamma(x)= pi/ ( gamma(1-x)*sin(pi*x) )
639
    double fLogDivisor = lcl_GetLogGammaHelper(1-fZ) + log( fabs( ::rtl::math::sin( F_PI*fZ)));
640
    if (fLogDivisor - fLogPi >= fLogDblMax)     // underflow
641
        return 0.0;
642
643
    if (fLogDivisor<0.0)
644
        if (fLogPi - fLogDivisor > fLogDblMax)  // overflow
645
        {
646
            SetError(errIllegalFPOperation);
647
            return HUGE_VAL;
648
        }
649
650
    return exp( fLogPi - fLogDivisor) * ((::rtl::math::sin( F_PI*fZ) < 0.0) ? -1.0 : 1.0);
651
}
592
}
652
593
653
594
654
/** You must ensure fZ>0 */
595
/** You must ensure fZ>0 */
655
double ScInterpreter::GetLogGamma(double fZ)
596
double ScInterpreter::GetLogGamma(double fZ)
656
{
597
{
657
    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetLogGamma" );
598
    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "bst", "ScInterpreter::GetLogGamma" );
658
    if (fZ >= fMaxGammaArgument)
599
    return ::boost::math::lgamma(fZ);
659
        return lcl_GetLogGammaHelper(fZ);
660
    if (fZ >= 1.0)
661
        return log(lcl_GetGammaHelper(fZ));
662
    if (fZ >= 0.5)
663
        return log( lcl_GetGammaHelper(fZ+1) / fZ);
664
    return lcl_GetLogGammaHelper(fZ+2) - log(fZ+1) - log(fZ);
665
}
600
}
666
601
667
double ScInterpreter::GetFDist(double x, double fF1, double fF2)
602
double ScInterpreter::GetFDist(double x, double fF1, double fF2)

Return to issue 121561