LibreOffice Module sc (master)  1
math.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <math.hxx>
11 #include <cmath>
12 #include <cerrno>
13 #include <cfenv>
14 
16 
17 namespace sc {
18 
19 static double err_pow( const double& fVal1, const double& fVal2 )
20 {
21  // pow() is expected to set domain error or pole error or range error (or
22  // flag them via exceptions) or return NaN or Inf.
23  assert((math_errhandling & (MATH_ERRNO | MATH_ERREXCEPT)) != 0);
24  std::feclearexcept(FE_ALL_EXCEPT);
25  errno = 0;
26  return pow( fVal1, fVal2);
27 }
28 
29 double power( const double& fVal1, const double& fVal2 )
30 {
31  double fPow;
32  if (fVal1 < 0 && fVal2 != 0.0)
33  {
34  const double f = 1.0 / fVal2 + ((fVal2 < 0.0) ? -0.5 : 0.5);
37  {
38  // Casting to int would be undefined behaviour.
39  fPow = err_pow( fVal1, fVal2);
40  }
41  else
42  {
43  const sal_Int64 i = static_cast<sal_Int64>(f);
44  if (i % 2 != 0 && rtl::math::approxEqual(1 / static_cast<double>(i), fVal2))
45  fPow = -err_pow( -fVal1, fVal2);
46  else
47  fPow = err_pow( fVal1, fVal2);
48  }
49  }
50  else
51  {
52  fPow = err_pow( fVal1, fVal2);
53  }
54  // The pow() call must had been the most recent call to check errno or exception.
55  if ((((math_errhandling & MATH_ERRNO) != 0) && (errno == EDOM || errno == ERANGE))
56  || (((math_errhandling & MATH_ERREXCEPT) != 0)
57  && std::fetestexcept( FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW))
58  || !std::isfinite(fPow))
59  {
60  fPow = CreateDoubleError( FormulaError::IllegalFPOperation);
61  }
62  return fPow;
63 }
64 
65 }
66 
67 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
#define SAL_MIN_INT64
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
int i
static double err_pow(const double &fVal1, const double &fVal2)
Definition: math.cxx:19
std::enable_if_t< std::is_floating_point_v< F > &&std::is_integral_v< I >, bool > convertsToAtMost(F value, I max)
double power(const double &fVal1, const double &fVal2)
Return pow(fVal1,fVal2) with error handling.
Definition: math.cxx:29
double CreateDoubleError(FormulaError nErr)
std::enable_if_t< std::is_floating_point_v< F > &&std::is_integral_v< I >, bool > convertsToAtLeast(F value, I min)
void(* f)(TrueTypeTable *)
#define SAL_MAX_INT64