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#include <rtl/math.hxx>
17
18namespace sc
19{
20static double err_pow(const double& fVal1, const double& fVal2)
21{
22 // pow() is expected to set domain error or pole error or range error (or
23 // flag them via exceptions) or return NaN or Inf.
24 assert((math_errhandling & (MATH_ERRNO | MATH_ERREXCEPT)) != 0);
25 std::feclearexcept(FE_ALL_EXCEPT);
26 errno = 0;
27 return pow(fVal1, fVal2);
28}
29
30double power(const double& fVal1, const double& fVal2)
31{
32 double fPow;
33 if (fVal1 < 0 && fVal2 != 0.0)
34 {
35 const double f = 1.0 / fVal2 + ((fVal2 < 0.0) ? -0.5 : 0.5);
38 {
39 // Casting to int would be undefined behaviour.
40 fPow = err_pow(fVal1, fVal2);
41 }
42 else
43 {
44 const sal_Int64 i = static_cast<sal_Int64>(f);
45 if (i % 2 != 0 && rtl::math::approxEqual(1 / static_cast<double>(i), fVal2))
46 fPow = -err_pow(-fVal1, fVal2);
47 else
48 fPow = err_pow(fVal1, fVal2);
49 }
50 }
51 else
52 {
53 fPow = err_pow(fVal1, fVal2);
54 }
55 // The pow() call must had been the most recent call to check errno or exception.
56 if ((((math_errhandling & MATH_ERRNO) != 0) && (errno == EDOM || errno == ERANGE))
57// emscripten is currently broken by https://github.com/emscripten-core/emscripten/pull/11087
58// While the removal is correct for C99, it's not for C++11 (see http://www.cplusplus.com/reference/cfenv/FE_INEXACT/)
59// But since emscripten currently doesn't support any math exceptions, we simply ignore them
60#ifndef __EMSCRIPTEN__
61 || (((math_errhandling & MATH_ERREXCEPT) != 0)
62 && std::fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW))
63#endif
64 || !std::isfinite(fPow))
65 {
66 fPow = CreateDoubleError(FormulaError::IllegalFPOperation);
67 }
68 return fPow;
69}
70}
71
72/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
double CreateDoubleError(FormulaError nErr)
int i
constexpr std::enable_if_t< std::is_floating_point_v< F > &&std::is_integral_v< I >, bool > convertsToAtLeast(F value, I min)
constexpr std::enable_if_t< std::is_floating_point_v< F > &&std::is_integral_v< I >, bool > convertsToAtMost(F value, I max)
CAUTION! The following defines must be in the same namespace as the respective type.
Definition: broadcast.cxx:15
double power(const double &fVal1, const double &fVal2)
Return pow(fVal1,fVal2) with error handling.
Definition: math.cxx:30
static double err_pow(const double &fVal1, const double &fVal2)
Definition: math.cxx:20
#define SAL_MAX_INT64
#define SAL_MIN_INT64