1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 * This file is part of LibreOffice published API.
24 #ifndef INCLUDED_RTL_MATH_HXX
25 #define INCLUDED_RTL_MATH_HXX
28 #include "rtl/strbuf.hxx"
29 #include "rtl/string.hxx"
30 #include "rtl/ustring.hxx"
31 #include "rtl/ustrbuf.hxx"
32 #include "sal/mathconf.h"
33 #include "sal/types.h"
42 /** A wrapper around rtl_math_doubleToString.
44 inline rtl::OString
doubleToString(double fValue
, rtl_math_StringFormat eFormat
,
47 sal_Int32
const * pGroups
,
49 bool bEraseTrailingDecZeros
= false)
52 rtl_math_doubleToString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
53 cDecSeparator
, pGroups
, cGroupSeparator
,
54 bEraseTrailingDecZeros
);
58 /** A wrapper around rtl_math_doubleToString, with no grouping.
60 inline rtl::OString
doubleToString(double fValue
, rtl_math_StringFormat eFormat
,
63 bool bEraseTrailingDecZeros
= false)
66 rtl_math_doubleToString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
67 cDecSeparator
, NULL
, 0, bEraseTrailingDecZeros
);
71 /** A wrapper around rtl_math_doubleToString that appends to an
74 @since LibreOffice 5.4
76 inline void doubleToStringBuffer(
77 rtl::OStringBuffer
& rBuffer
, double fValue
, rtl_math_StringFormat eFormat
,
78 sal_Int32 nDecPlaces
, char cDecSeparator
, sal_Int32
const * pGroups
,
79 char cGroupSeparator
, bool bEraseTrailingDecZeros
= false)
82 sal_Int32
* pCapacity
;
83 rBuffer
.accessInternals(&pData
, &pCapacity
);
84 rtl_math_doubleToString(
85 pData
, pCapacity
, rBuffer
.getLength(), fValue
, eFormat
, nDecPlaces
,
86 cDecSeparator
, pGroups
, cGroupSeparator
, bEraseTrailingDecZeros
);
89 /** A wrapper around rtl_math_doubleToString that appends to an
90 rtl::OStringBuffer, with no grouping.
92 @since LibreOffice 5.4
94 inline void doubleToStringBuffer(
95 rtl::OStringBuffer
& rBuffer
, double fValue
, rtl_math_StringFormat eFormat
,
96 sal_Int32 nDecPlaces
, char cDecSeparator
,
97 bool bEraseTrailingDecZeros
= false)
100 sal_Int32
* pCapacity
;
101 rBuffer
.accessInternals(&pData
, &pCapacity
);
102 rtl_math_doubleToString(
103 pData
, pCapacity
, rBuffer
.getLength(), fValue
, eFormat
, nDecPlaces
,
104 cDecSeparator
, NULL
, 0, bEraseTrailingDecZeros
);
107 /** A wrapper around rtl_math_doubleToUString.
109 inline rtl::OUString
doubleToUString(double fValue
,
110 rtl_math_StringFormat eFormat
,
111 sal_Int32 nDecPlaces
,
112 sal_Unicode cDecSeparator
,
113 sal_Int32
const * pGroups
,
114 sal_Unicode cGroupSeparator
,
115 bool bEraseTrailingDecZeros
= false)
117 rtl::OUString aResult
;
118 rtl_math_doubleToUString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
119 cDecSeparator
, pGroups
, cGroupSeparator
,
120 bEraseTrailingDecZeros
);
124 /** A wrapper around rtl_math_doubleToUString, with no grouping.
126 inline rtl::OUString
doubleToUString(double fValue
,
127 rtl_math_StringFormat eFormat
,
128 sal_Int32 nDecPlaces
,
129 sal_Unicode cDecSeparator
,
130 bool bEraseTrailingDecZeros
= false)
132 rtl::OUString aResult
;
133 rtl_math_doubleToUString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
134 cDecSeparator
, NULL
, 0, bEraseTrailingDecZeros
);
138 /** A wrapper around rtl_math_doubleToUString that appends to an
141 inline void doubleToUStringBuffer( rtl::OUStringBuffer
& rBuffer
, double fValue
,
142 rtl_math_StringFormat eFormat
,
143 sal_Int32 nDecPlaces
,
144 sal_Unicode cDecSeparator
,
145 sal_Int32
const * pGroups
,
146 sal_Unicode cGroupSeparator
,
147 bool bEraseTrailingDecZeros
= false)
149 rtl_uString
** pData
;
150 sal_Int32
* pCapacity
;
151 rBuffer
.accessInternals( &pData
, &pCapacity
);
152 rtl_math_doubleToUString( pData
, pCapacity
, rBuffer
.getLength(), fValue
,
153 eFormat
, nDecPlaces
, cDecSeparator
, pGroups
,
154 cGroupSeparator
, bEraseTrailingDecZeros
);
157 /** A wrapper around rtl_math_doubleToUString that appends to an
158 rtl::OUStringBuffer, with no grouping.
160 inline void doubleToUStringBuffer( rtl::OUStringBuffer
& rBuffer
, double fValue
,
161 rtl_math_StringFormat eFormat
,
162 sal_Int32 nDecPlaces
,
163 sal_Unicode cDecSeparator
,
164 bool bEraseTrailingDecZeros
= false)
166 rtl_uString
** pData
;
167 sal_Int32
* pCapacity
;
168 rBuffer
.accessInternals( &pData
, &pCapacity
);
169 rtl_math_doubleToUString( pData
, pCapacity
, rBuffer
.getLength(), fValue
,
170 eFormat
, nDecPlaces
, cDecSeparator
, NULL
, 0,
171 bEraseTrailingDecZeros
);
174 /** A wrapper around rtl_math_stringToDouble.
176 #ifdef LIBO_INTERNAL_ONLY
177 inline double stringToDouble(std::string_view aString
,
178 char cDecSeparator
, char cGroupSeparator
,
179 rtl_math_ConversionStatus
* pStatus
= NULL
,
180 sal_Int32
* pParsedEnd
= NULL
)
182 char const * pBegin
= aString
.data();
184 double fResult
= rtl_math_stringToDouble(pBegin
,
185 pBegin
+ aString
.size(),
186 cDecSeparator
, cGroupSeparator
,
188 if (pParsedEnd
!= NULL
)
189 *pParsedEnd
= static_cast<sal_Int32
>(pEnd
- pBegin
);
193 inline double stringToDouble(rtl::OString
const & rString
,
194 char cDecSeparator
, char cGroupSeparator
,
195 rtl_math_ConversionStatus
* pStatus
= NULL
,
196 sal_Int32
* pParsedEnd
= NULL
)
198 char const * pBegin
= rString
.getStr();
200 double fResult
= rtl_math_stringToDouble(pBegin
,
201 pBegin
+ rString
.getLength(),
202 cDecSeparator
, cGroupSeparator
,
204 if (pParsedEnd
!= NULL
)
205 *pParsedEnd
= static_cast<sal_Int32
>(pEnd
- pBegin
);
211 /** A wrapper around rtl_math_uStringToDouble.
213 #ifdef LIBO_INTERNAL_ONLY
214 inline double stringToDouble(std::u16string_view aString
,
215 sal_Unicode cDecSeparator
,
216 sal_Unicode cGroupSeparator
,
217 rtl_math_ConversionStatus
* pStatus
= NULL
,
218 sal_Int32
* pParsedEnd
= NULL
)
220 sal_Unicode
const * pBegin
= aString
.data();
221 sal_Unicode
const * pEnd
;
222 double fResult
= rtl_math_uStringToDouble(pBegin
,
223 pBegin
+ aString
.size(),
224 cDecSeparator
, cGroupSeparator
,
226 if (pParsedEnd
!= NULL
)
227 *pParsedEnd
= static_cast<sal_Int32
>(pEnd
- pBegin
);
231 inline double stringToDouble(rtl::OUString
const & rString
,
232 sal_Unicode cDecSeparator
,
233 sal_Unicode cGroupSeparator
,
234 rtl_math_ConversionStatus
* pStatus
= NULL
,
235 sal_Int32
* pParsedEnd
= NULL
)
237 sal_Unicode
const * pBegin
= rString
.getStr();
238 sal_Unicode
const * pEnd
;
239 double fResult
= rtl_math_uStringToDouble(pBegin
,
240 pBegin
+ rString
.getLength(),
241 cDecSeparator
, cGroupSeparator
,
243 if (pParsedEnd
!= NULL
)
244 *pParsedEnd
= static_cast<sal_Int32
>(pEnd
- pBegin
);
249 /** A wrapper around rtl_math_round.
252 double fValue
, int nDecPlaces
= 0,
253 rtl_math_RoundingMode eMode
= rtl_math_RoundingMode_Corrected
)
255 return rtl_math_round(fValue
, nDecPlaces
, eMode
);
258 /** A wrapper around rtl_math_pow10Exp.
260 inline double pow10Exp(double fValue
, int nExp
)
262 return rtl_math_pow10Exp(fValue
, nExp
);
265 /** A wrapper around rtl_math_approxValue.
267 inline double approxValue(double fValue
)
269 return rtl_math_approxValue(fValue
);
272 /** A wrapper around rtl_math_expm1.
274 inline double expm1(double fValue
)
276 return rtl_math_expm1(fValue
);
279 /** A wrapper around rtl_math_log1p.
281 inline double log1p(double fValue
)
283 return rtl_math_log1p(fValue
);
286 /** A wrapper around rtl_math_atanh.
288 inline double atanh(double fValue
)
290 return rtl_math_atanh(fValue
);
293 /** A wrapper around rtl_math_erf.
295 inline double erf(double fValue
)
297 return rtl_math_erf(fValue
);
300 /** A wrapper around rtl_math_erfc.
302 inline double erfc(double fValue
)
304 return rtl_math_erfc(fValue
);
307 /** A wrapper around rtl_math_asinh.
309 inline double asinh(double fValue
)
311 return rtl_math_asinh(fValue
);
314 /** A wrapper around rtl_math_acosh.
316 inline double acosh(double fValue
)
318 return rtl_math_acosh(fValue
);
321 /** A wrapper around rtl_math_approxEqual.
323 inline bool approxEqual(double a
, double b
)
325 return rtl_math_approxEqual( a
, b
);
328 /** Test equality of two values with an accuracy defined by nPrec
331 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
333 inline bool approxEqual(double a
, double b
, sal_Int16 nPrec
)
338 return (x
< 0.0 ? -x
: x
)
339 < ((a
< 0.0 ? -a
: a
) * (1.0 / (pow(2.0, nPrec
))));
344 If signs differ and the absolute values are equal according to approxEqual()
345 the method returns 0.0 instead of calculating the sum.
347 If you wanted to sum up multiple values it would be convenient not to call
348 approxAdd() for each value but instead remember the first value not equal to
349 0.0, add all other values using normal + operator, and with the result and
350 the remembered value call approxAdd().
352 inline double approxAdd(double a
, double b
)
354 if ( ((a
< 0.0 && b
> 0.0) || (b
< 0.0 && a
> 0.0))
355 && approxEqual( a
, -b
) )
360 /** Subtract two values (a-b).
362 If signs are identical and the values are equal according to approxEqual()
363 the method returns 0.0 instead of calculating the subtraction.
365 inline double approxSub(double a
, double b
)
367 if ( ((a
< 0.0 && b
< 0.0) || (a
> 0.0 && b
> 0.0)) && approxEqual( a
, b
) )
372 /** floor() method taking approxValue() into account.
374 Use for expected integer values being calculated by double functions.
376 inline double approxFloor(double a
)
378 return floor( approxValue( a
));
381 /** ceil() method taking approxValue() into account.
383 Use for expected integer values being calculated by double functions.
385 inline double approxCeil(double a
)
387 return ceil( approxValue( a
));
390 /** Tests whether a value is neither INF nor NAN.
392 inline bool isFinite(double d
)
394 return SAL_MATH_FINITE(d
);
397 /** If a value represents +INF or -INF.
399 The sign bit may be queried with isSignBitSet().
401 If isFinite(d)==false and isInf(d)==false then NAN.
403 inline bool isInf(double d
)
405 // exponent==0x7ff fraction==0
406 return !SAL_MATH_FINITE(d
) &&
407 (reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.fraction_hi
== 0)
408 && (reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.fraction_lo
412 /** Test on any QNAN or SNAN.
414 inline bool isNan(double d
)
416 // exponent==0x7ff fraction!=0
417 return !SAL_MATH_FINITE(d
) && (
418 (reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.fraction_hi
!= 0)
419 || (reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.fraction_lo
423 /** If the sign bit is set.
425 inline bool isSignBitSet(double d
)
427 return reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.sign
!= 0;
430 /** Set to +INF if bNegative==false or -INF if bNegative==true.
432 inline void setInf(double * pd
, bool bNegative
)
439 md
.w32_parts
.msw
= bNegative
? 0xFFF00000 : 0x7FF00000;
440 md
.w32_parts
.lsw
= 0;
446 inline void setNan(double * pd
)
453 md
.w32_parts
.msw
= 0x7FFFFFFF;
454 md
.w32_parts
.lsw
= 0xFFFFFFFF;
458 /** If a value is a valid argument for sin(), cos(), tan().
460 IEEE 754 specifies that absolute values up to 2^64 (=1.844e19) for the
461 radian must be supported by trigonometric functions. Unfortunately, at
462 least on x86 architectures, the FPU doesn't generate an error pattern for
463 values >2^64 but produces erroneous results instead and sets only the
464 "invalid operation" (IM) flag in the status word :-( Thus the application
465 has to handle it itself.
467 inline bool isValidArcArg(double d
)
470 <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
471 * static_cast< double >(static_cast< unsigned long >(0x80000000))
475 /** Safe sin(), returns NAN if not valid.
477 inline double sin(double d
)
479 if ( isValidArcArg( d
) )
485 /** Safe cos(), returns NAN if not valid.
487 inline double cos(double d
)
489 if ( isValidArcArg( d
) )
495 /** Safe tan(), returns NAN if not valid.
497 inline double tan(double d
)
499 if ( isValidArcArg( d
) )
509 #endif // INCLUDED_RTL_MATH_HXX
511 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */