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

(-)main/sc/source/core/inc/interpre.hxx (-13 lines)
Lines 33-51 Link Here
33
#include <math.h>
33
#include <math.h>
34
#include <map>
34
#include <map>
35
35
36
// STLport definitions
37
// This works around some issues with Boost
38
//
39
#ifdef WNT
40
#define _STLP_HAS_NATIVE_FLOAT_ABS
41
#endif
42
43
// Math policy definitions for Boost
44
// This header must be included before including any Boost
45
// math function.
46
//
47
#define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error
48
49
class ScDocument;
36
class ScDocument;
50
class SbxVariable;
37
class SbxVariable;
51
class ScBaseCell;
38
class ScBaseCell;
(-)main/sc/source/core/tool/interpr2.cxx (-7 / +4 lines)
Lines 52-60 Link Here
52
#include <string.h>
52
#include <string.h>
53
#include <math.h>
53
#include <math.h>
54
54
55
#include <boost/math/special_functions/expm1.hpp>
56
#include <boost/math/special_functions/log1p.hpp>
57
58
using namespace formula;
55
using namespace formula;
59
// STATIC DATA -----------------------------------------------------------
56
// STATIC DATA -----------------------------------------------------------
60
57
Lines 1138-1148 Link Here
1138
    else
1135
    else
1139
    {
1136
    {
1140
        if (fPaytype > 0.0) // payment in advance
1137
        if (fPaytype > 0.0) // payment in advance
1141
            fPayment = (fFv + fPv * exp( fNper * ::boost::math::log1p(fRate) ) ) * fRate / 
1138
            fPayment = (fFv + fPv * exp( fNper * ::rtl::math::log1p(fRate) ) ) * fRate / 
1142
                (::boost::math::expm1( (fNper + 1) * ::boost::math::log1p(fRate) ) - fRate);
1139
                (::rtl::math::expm1( (fNper + 1) * ::rtl::math::log1p(fRate) ) - fRate);
1143
        else  // payment in arrear
1140
        else  // payment in arrear
1144
            fPayment = (fFv + fPv * exp(fNper * ::boost::math::log1p(fRate) ) ) * fRate / 
1141
            fPayment = (fFv + fPv * exp(fNper * ::rtl::math::log1p(fRate) ) ) * fRate / 
1145
                ::boost::math::expm1( fNper * ::boost::math::log1p(fRate) );
1142
                ::rtl::math::expm1( fNper * ::rtl::math::log1p(fRate) );
1146
    }
1143
    }
1147
    return -fPayment;
1144
    return -fPayment;
1148
}
1145
}
(-)main/sc/source/core/tool/interpr1.cxx (-7 / +3 lines)
Lines 72-81 Link Here
72
#include "doubleref.hxx"
72
#include "doubleref.hxx"
73
#include "queryparam.hxx"
73
#include "queryparam.hxx"
74
74
75
#include <boost/math/special_functions/acosh.hpp>
76
#include <boost/math/special_functions/asinh.hpp>
77
#include <boost/math/special_functions/atanh.hpp>
78
79
#define SC_DOUBLE_MAXVALUE  1.7e307
75
#define SC_DOUBLE_MAXVALUE  1.7e307
80
76
81
IMPL_FIXEDMEMPOOL_NEWDEL( ScTokenStack, 8, 4 )
77
IMPL_FIXEDMEMPOOL_NEWDEL( ScTokenStack, 8, 4 )
Lines 1706-1712 Link Here
1706
void ScInterpreter::ScArcSinHyp()
1702
void ScInterpreter::ScArcSinHyp()
1707
{
1703
{
1708
    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcSinHyp" );
1704
    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcSinHyp" );
1709
    PushDouble( ::boost::math::asinh( GetDouble()));
1705
    PushDouble( ::rtl::math::asinh( GetDouble()));
1710
}
1706
}
1711
1707
1712
void ScInterpreter::ScArcCosHyp()
1708
void ScInterpreter::ScArcCosHyp()
Lines 1716-1722 Link Here
1716
    if (fVal < 1.0)
1712
    if (fVal < 1.0)
1717
        PushIllegalArgument();
1713
        PushIllegalArgument();
1718
    else
1714
    else
1719
        PushDouble( ::boost::math::acosh( fVal));
1715
        PushDouble( ::rtl::math::acosh( fVal));
1720
}
1716
}
1721
1717
1722
void ScInterpreter::ScArcTanHyp()
1718
void ScInterpreter::ScArcTanHyp()
Lines 1726-1732 Link Here
1726
    if (fabs(fVal) >= 1.0)
1722
    if (fabs(fVal) >= 1.0)
1727
        PushIllegalArgument();
1723
        PushIllegalArgument();
1728
    else
1724
    else
1729
        PushDouble( ::boost::math::atanh( fVal));
1725
        PushDouble( ::rtl::math::atanh( fVal));
1730
}
1726
}
1731
1727
1732
1728
(-)main/sc/source/core/tool/interpr3.cxx (-83 / +13 lines)
Lines 44-53 Link Here
44
#include <vector>
44
#include <vector>
45
#include <algorithm>
45
#include <algorithm>
46
46
47
#include <boost/math/special_functions/atanh.hpp>
48
#include <boost/math/special_functions/expm1.hpp>
49
#include <boost/math/special_functions/log1p.hpp>
50
51
using ::std::vector;
47
using ::std::vector;
52
using namespace formula;
48
using namespace formula;
53
49
Lines 577-667 Link Here
577
    return fSumNum/fSumDenom;
573
    return fSumNum/fSumDenom;
578
}
574
}
579
575
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
576
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 */
577
/** You must ensure non integer arguments for fZ<1 */
609
double ScInterpreter::GetGamma(double fZ)
578
double ScInterpreter::GetGamma(double fZ)
610
{
579
{
611
    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetGamma" );
580
    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)
581
    if (fZ > fMaxGammaArgument)
616
    {
582
    {
617
        SetError(errIllegalFPOperation);
583
        SetError(errIllegalFPOperation);
618
        return HUGE_VAL;
584
        return HUGE_VAL;
619
    }
585
    }
620
586
    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
}
587
}
652
588
653
589
654
/** You must ensure fZ>0 */
590
/** You must ensure fZ>0 */
655
double ScInterpreter::GetLogGamma(double fZ)
591
double ScInterpreter::GetLogGamma(double fZ)
656
{
592
{
657
    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetLogGamma" );
593
    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "bst", "ScInterpreter::GetLogGamma" );
658
    if (fZ >= fMaxGammaArgument)
594
    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
}
595
}
666
596
667
double ScInterpreter::GetFDist(double x, double fF1, double fF2)
597
double ScInterpreter::GetFDist(double x, double fF1, double fF2)
Lines 857-864 Link Here
857
    fLanczos *= sqrt((fABgm/(fA+fgm))/(fB+fgm));
787
    fLanczos *= sqrt((fABgm/(fA+fgm))/(fB+fgm));
858
    double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
788
    double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
859
    double fTempB = fA/(fB+fgm);
789
    double fTempB = fA/(fB+fgm);
860
    double fResult = exp(-fA * ::boost::math::log1p(fTempA)
790
    double fResult = exp(-fA * ::rtl::math::log1p(fTempA)
861
                            -fB * ::boost::math::log1p(fTempB)-fgm);
791
                            -fB * ::rtl::math::log1p(fTempB)-fgm);
862
    fResult *= fLanczos;
792
    fResult *= fLanczos;
863
    return fResult;
793
    return fResult;
864
}
794
}
Lines 886-893 Link Here
886
    fLogLanczos += 0.5*(log(fABgm)-log(fA+fgm)-log(fB+fgm));
816
    fLogLanczos += 0.5*(log(fABgm)-log(fA+fgm)-log(fB+fgm));
887
    double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
817
    double fTempA = fB/(fA+fgm); // (fA+fgm)/fABgm = 1 / ( 1 + fB/(fA+fgm))
888
    double fTempB = fA/(fB+fgm);
818
    double fTempB = fA/(fB+fgm);
889
    double fResult = -fA * ::boost::math::log1p(fTempA)
819
    double fResult = -fA * ::rtl::math::log1p(fTempA)
890
                        -fB * ::boost::math::log1p(fTempB)-fgm;
820
                        -fB * ::rtl::math::log1p(fTempB)-fgm;
891
    fResult += fLogLanczos;
821
    fResult += fLogLanczos;
892
    return fResult;
822
    return fResult;
893
}
823
}
Lines 908-914 Link Here
908
            return HUGE_VAL;
838
            return HUGE_VAL;
909
        }
839
        }
910
        if (fX <= 0.01)
840
        if (fX <= 0.01)
911
            return fB + fB * ::boost::math::expm1((fB-1.0) * ::boost::math::log1p(-fX));
841
            return fB + fB * ::rtl::math::expm1((fB-1.0) * ::rtl::math::log1p(-fX));
912
        else
842
        else
913
            return fB * pow(0.5-fX+0.5,fB-1.0);
843
            return fB * pow(0.5-fX+0.5,fB-1.0);
914
    }
844
    }
Lines 947-953 Link Here
947
    // normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b)
877
    // normal cases; result x^(a-1)*(1-x)^(b-1)/Beta(a,b)
948
    const double fLogDblMax = log( ::std::numeric_limits<double>::max());
878
    const double fLogDblMax = log( ::std::numeric_limits<double>::max());
949
    const double fLogDblMin = log( ::std::numeric_limits<double>::min());
879
    const double fLogDblMin = log( ::std::numeric_limits<double>::min());
950
    double fLogY = (fX < 0.1) ? ::boost::math::log1p(-fX) : log(0.5-fX+0.5);
880
    double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5);
951
    double fLogX = log(fX);
881
    double fLogX = log(fX);
952
    double fAm1LogX = (fA-1.0) * fLogX;
882
    double fAm1LogX = (fA-1.0) * fLogX;
953
    double fBm1LogY = (fB-1.0) * fLogY;
883
    double fBm1LogY = (fB-1.0) * fLogY;
Lines 1028-1040 Link Here
1028
        return pow(fXin, fAlpha);
958
        return pow(fXin, fAlpha);
1029
    if (fAlpha == 1.0)
959
    if (fAlpha == 1.0)
1030
    //            1.0 - pow(1.0-fX,fBeta) is not accurate enough
960
    //            1.0 - pow(1.0-fX,fBeta) is not accurate enough
1031
        return -::boost::math::expm1(fBeta * ::boost::math::log1p(-fXin));
961
        return -::rtl::math::expm1(fBeta * ::rtl::math::log1p(-fXin));
1032
    //FIXME: need special algorithm for fX near fP for large fA,fB
962
    //FIXME: need special algorithm for fX near fP for large fA,fB
1033
    double fResult;
963
    double fResult;
1034
    // I use always continued fraction, power series are neither
964
    // I use always continued fraction, power series are neither
1035
    // faster nor more accurate.
965
    // faster nor more accurate.
1036
    double fY = (0.5-fXin)+0.5;
966
    double fY = (0.5-fXin)+0.5;
1037
    double flnY = ::boost::math::log1p(-fXin);
967
    double flnY = ::rtl::math::log1p(-fXin);
1038
    double fX = fXin;
968
    double fX = fXin;
1039
    double flnX = log(fXin);
969
    double flnX = log(fXin);
1040
    double fA = fAlpha;
970
    double fA = fAlpha;
Lines 1145-1151 Link Here
1145
    if (fabs(fVal) >= 1.0)
1075
    if (fabs(fVal) >= 1.0)
1146
        PushIllegalArgument();
1076
        PushIllegalArgument();
1147
    else
1077
    else
1148
        PushDouble( ::boost::math::atanh( fVal));
1078
        PushDouble( ::rtl::math::atanh( fVal));
1149
}
1079
}
1150
1080
1151
void ScInterpreter::ScFisherInv()
1081
void ScInterpreter::ScFisherInv()

Return to issue 121561