--- sal/inc/rtl/math.h (revision 1446929) +++ sal/inc/rtl/math.h (working copy) @@ -24,6 +24,8 @@ #if !defined INCLUDED_RTL_MATH_H #define INCLUDED_RTL_MATH_H +#define STRICTER_MATH + #include "rtl/ustring.h" #include "sal/types.h" @@ -396,6 +398,21 @@ */ double SAL_CALL rtl_math_pow10Exp(double fValue, int nExp) SAL_THROW_EXTERN_C(); +/** Similar to pow() with stricter exception handling for indeterminate values. + + powr is intended to partially mimic the IEEE 754 2008 Floating Point Standard. + + @param fValue + The value to be raised. + + @param fExp + The exponent. + + @return + powr(fValue, fExp) + */ +double SAL_CALL rtl_math_powr(double fValue, double fExp) SAL_THROW_EXTERN_C(); + /** Rounds value to 15 significant decimal digits. @param fValue --- sal/inc/rtl/math.hxx (revision 1446929) +++ sal/inc/rtl/math.hxx (working copy) @@ -186,6 +186,13 @@ return rtl_math_pow10Exp(fValue, nExp); } +/** A wrapper around rtl_math_powr. + */ +inline double powr(double fValue, int fExp) +{ + return rtl_math_powr(fValue, fExp); +} + /** A wrapper around rtl_math_approxValue. */ inline double approxValue(double fValue) --- sal/rtl/source/math.cxx (revision 1446929) +++ sal/rtl/source/math.cxx (working copy) @@ -1113,7 +1113,22 @@ return (fe-1.0) * fValue / log(fe); } +double SAL_CALL rtl_math_powr( double fValue, double fExp ) SAL_THROW_EXTERN_C() +{ +#ifdef STRICTER_MATH + if ((fValue == 0.0 && fExp == 0.0) || + (rtl::math::isInf( fExp ) && !rtl::math::isSignBitSet( fExp )) || + (rtl::math::isInf( fValue ) && !rtl::math::isSignBitSet( fValue ))) + { + double fResult; + ::rtl::math::setNan( &fResult ); + return fResult; + } +#endif + return pow(fValue, fExp); +} + double SAL_CALL rtl_math_log1p( double fValue ) SAL_THROW_EXTERN_C() { // Use volatile because a compiler may be too smart "optimizing" the --- sal/util/sal.map (revision 1446929) +++ sal/util/sal.map (working copy) @@ -629,6 +629,8 @@ global: osl_loadAsciiModule; osl_loadAsciiModuleRelative; + + rtl_math_powr; } UDK_3.11; PRIVATE_1.0 { --- sc/source/core/tool/interpr5.cxx (revision 1446929) +++ sc/source/core/tool/interpr5.cxx (working copy) @@ -1608,15 +1608,19 @@ if (pResMat) { SCSIZE nCount = nC * nR; + if (pMat->IsValue(0)) + pResMat->PutDouble(1); + else + pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0); if (bFlag) - { for ( SCSIZE i = 0; i < nCount; i++ ) + { for ( SCSIZE i = 1; i < nCount; i++ ) if (pMat->IsValue(i)) pResMat->PutDouble(pow(fVal,pMat->GetDouble(i)), i); else pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i); } else - { for ( SCSIZE i = 0; i < nCount; i++ ) + { for ( SCSIZE i = 1; i < nCount; i++ ) if (pMat->IsValue(i)) pResMat->PutDouble(pow(pMat->GetDouble(i),fVal), i); else @@ -1628,7 +1632,7 @@ PushIllegalArgument(); } else - PushDouble(pow(fVal1,fVal2)); + PushDouble(::rtl::math::powr(fVal1,fVal2)); } void ScInterpreter::ScSumProduct()