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 .
20 #ifndef INCLUDED_RTL_MATH_HXX
21 #define INCLUDED_RTL_MATH_HXX
24 #include "rtl/strbuf.hxx"
25 #include "rtl/string.hxx"
26 #include "rtl/ustring.hxx"
27 #include "rtl/ustrbuf.hxx"
28 #include "sal/mathconf.h"
29 #include "sal/types.h"
38 /** A wrapper around rtl_math_doubleToString.
40 inline rtl::OString
doubleToString(double fValue
, rtl_math_StringFormat eFormat
,
42 sal_Char cDecSeparator
,
43 sal_Int32
const * pGroups
,
44 sal_Char cGroupSeparator
,
45 bool bEraseTrailingDecZeros
= false)
48 rtl_math_doubleToString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
49 cDecSeparator
, pGroups
, cGroupSeparator
,
50 bEraseTrailingDecZeros
);
54 /** A wrapper around rtl_math_doubleToString, with no grouping.
56 inline rtl::OString
doubleToString(double fValue
, rtl_math_StringFormat eFormat
,
58 sal_Char cDecSeparator
,
59 bool bEraseTrailingDecZeros
= false)
62 rtl_math_doubleToString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
63 cDecSeparator
, NULL
, 0, bEraseTrailingDecZeros
);
67 /** A wrapper around rtl_math_doubleToString that appends to an
70 @since LibreOffice 5.4
72 inline void doubleToStringBuffer(
73 rtl::OStringBuffer
& rBuffer
, double fValue
, rtl_math_StringFormat eFormat
,
74 sal_Int32 nDecPlaces
, sal_Char cDecSeparator
, sal_Int32
const * pGroups
,
75 sal_Char cGroupSeparator
, bool bEraseTrailingDecZeros
= false)
78 sal_Int32
* pCapacity
;
79 rBuffer
.accessInternals(&pData
, &pCapacity
);
80 rtl_math_doubleToString(
81 pData
, pCapacity
, rBuffer
.getLength(), fValue
, eFormat
, nDecPlaces
,
82 cDecSeparator
, pGroups
, cGroupSeparator
, bEraseTrailingDecZeros
);
85 /** A wrapper around rtl_math_doubleToString that appends to an
86 rtl::OStringBuffer, with no grouping.
88 @since LibreOffice 5.4
90 inline void doubleToStringBuffer(
91 rtl::OStringBuffer
& rBuffer
, double fValue
, rtl_math_StringFormat eFormat
,
92 sal_Int32 nDecPlaces
, sal_Char cDecSeparator
,
93 bool bEraseTrailingDecZeros
= false)
96 sal_Int32
* pCapacity
;
97 rBuffer
.accessInternals(&pData
, &pCapacity
);
98 rtl_math_doubleToString(
99 pData
, pCapacity
, rBuffer
.getLength(), fValue
, eFormat
, nDecPlaces
,
100 cDecSeparator
, NULL
, 0, bEraseTrailingDecZeros
);
103 /** A wrapper around rtl_math_doubleToUString.
105 inline rtl::OUString
doubleToUString(double fValue
,
106 rtl_math_StringFormat eFormat
,
107 sal_Int32 nDecPlaces
,
108 sal_Unicode cDecSeparator
,
109 sal_Int32
const * pGroups
,
110 sal_Unicode cGroupSeparator
,
111 bool bEraseTrailingDecZeros
= false)
113 rtl::OUString aResult
;
114 rtl_math_doubleToUString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
115 cDecSeparator
, pGroups
, cGroupSeparator
,
116 bEraseTrailingDecZeros
);
120 /** A wrapper around rtl_math_doubleToUString, with no grouping.
122 inline rtl::OUString
doubleToUString(double fValue
,
123 rtl_math_StringFormat eFormat
,
124 sal_Int32 nDecPlaces
,
125 sal_Unicode cDecSeparator
,
126 bool bEraseTrailingDecZeros
= false)
128 rtl::OUString aResult
;
129 rtl_math_doubleToUString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
130 cDecSeparator
, NULL
, 0, bEraseTrailingDecZeros
);
134 /** A wrapper around rtl_math_doubleToUString that appends to an
137 inline void doubleToUStringBuffer( rtl::OUStringBuffer
& rBuffer
, double fValue
,
138 rtl_math_StringFormat eFormat
,
139 sal_Int32 nDecPlaces
,
140 sal_Unicode cDecSeparator
,
141 sal_Int32
const * pGroups
,
142 sal_Unicode cGroupSeparator
,
143 bool bEraseTrailingDecZeros
= false)
145 rtl_uString
** pData
;
146 sal_Int32
* pCapacity
;
147 rBuffer
.accessInternals( &pData
, &pCapacity
);
148 rtl_math_doubleToUString( pData
, pCapacity
, rBuffer
.getLength(), fValue
,
149 eFormat
, nDecPlaces
, cDecSeparator
, pGroups
,
150 cGroupSeparator
, bEraseTrailingDecZeros
);
153 /** A wrapper around rtl_math_doubleToUString that appends to an
154 rtl::OUStringBuffer, with no grouping.
156 inline void doubleToUStringBuffer( rtl::OUStringBuffer
& rBuffer
, double fValue
,
157 rtl_math_StringFormat eFormat
,
158 sal_Int32 nDecPlaces
,
159 sal_Unicode cDecSeparator
,
160 bool bEraseTrailingDecZeros
= false)
162 rtl_uString
** pData
;
163 sal_Int32
* pCapacity
;
164 rBuffer
.accessInternals( &pData
, &pCapacity
);
165 rtl_math_doubleToUString( pData
, pCapacity
, rBuffer
.getLength(), fValue
,
166 eFormat
, nDecPlaces
, cDecSeparator
, NULL
, 0,
167 bEraseTrailingDecZeros
);
170 /** A wrapper around rtl_math_stringToDouble.
172 inline double stringToDouble(rtl::OString
const & rString
,
173 sal_Char cDecSeparator
, sal_Char cGroupSeparator
,
174 rtl_math_ConversionStatus
* pStatus
= NULL
,
175 sal_Int32
* pParsedEnd
= NULL
)
177 sal_Char
const * pBegin
= rString
.getStr();
178 sal_Char
const * pEnd
;
179 double fResult
= rtl_math_stringToDouble(pBegin
,
180 pBegin
+ rString
.getLength(),
181 cDecSeparator
, cGroupSeparator
,
183 if (pParsedEnd
!= NULL
)
184 *pParsedEnd
= static_cast<sal_Int32
>(pEnd
- pBegin
);
188 /** A wrapper around rtl_math_uStringToDouble.
190 inline double stringToDouble(rtl::OUString
const & rString
,
191 sal_Unicode cDecSeparator
,
192 sal_Unicode cGroupSeparator
,
193 rtl_math_ConversionStatus
* pStatus
= NULL
,
194 sal_Int32
* pParsedEnd
= NULL
)
196 sal_Unicode
const * pBegin
= rString
.getStr();
197 sal_Unicode
const * pEnd
;
198 double fResult
= rtl_math_uStringToDouble(pBegin
,
199 pBegin
+ rString
.getLength(),
200 cDecSeparator
, cGroupSeparator
,
202 if (pParsedEnd
!= NULL
)
203 *pParsedEnd
= static_cast<sal_Int32
>(pEnd
- pBegin
);
207 /** A wrapper around rtl_math_round.
210 double fValue
, int nDecPlaces
= 0,
211 rtl_math_RoundingMode eMode
= rtl_math_RoundingMode_Corrected
)
213 return rtl_math_round(fValue
, nDecPlaces
, eMode
);
216 /** A wrapper around rtl_math_pow10Exp.
218 inline double pow10Exp(double fValue
, int nExp
)
220 return rtl_math_pow10Exp(fValue
, nExp
);
223 /** A wrapper around rtl_math_approxValue.
225 inline double approxValue(double fValue
)
227 return rtl_math_approxValue(fValue
);
230 /** A wrapper around rtl_math_expm1.
232 inline double expm1(double fValue
)
234 return rtl_math_expm1(fValue
);
237 /** A wrapper around rtl_math_log1p.
239 inline double log1p(double fValue
)
241 return rtl_math_log1p(fValue
);
244 /** A wrapper around rtl_math_atanh.
246 inline double atanh(double fValue
)
248 return rtl_math_atanh(fValue
);
251 /** A wrapper around rtl_math_erf.
253 inline double erf(double fValue
)
255 return rtl_math_erf(fValue
);
258 /** A wrapper around rtl_math_erfc.
260 inline double erfc(double fValue
)
262 return rtl_math_erfc(fValue
);
265 /** A wrapper around rtl_math_asinh.
267 inline double asinh(double fValue
)
269 return rtl_math_asinh(fValue
);
272 /** A wrapper around rtl_math_acosh.
274 inline double acosh(double fValue
)
276 return rtl_math_acosh(fValue
);
279 /** A wrapper around rtl_math_approxEqual.
281 inline bool approxEqual(double a
, double b
)
283 return rtl_math_approxEqual( a
, b
);
286 /** Test equality of two values with an accuracy defined by nPrec
289 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
291 inline bool approxEqual(double a
, double b
, sal_Int16 nPrec
)
296 return (x
< 0.0 ? -x
: x
)
297 < ((a
< 0.0 ? -a
: a
) * (1.0 / (pow(2.0, nPrec
))));
302 If signs differ and the absolute values are equal according to approxEqual()
303 the method returns 0.0 instead of calculating the sum.
305 If you wanted to sum up multiple values it would be convenient not to call
306 approxAdd() for each value but instead remember the first value not equal to
307 0.0, add all other values using normal + operator, and with the result and
308 the remembered value call approxAdd().
310 inline double approxAdd(double a
, double b
)
312 if ( ((a
< 0.0 && b
> 0.0) || (b
< 0.0 && a
> 0.0))
313 && approxEqual( a
, -b
) )
318 /** Subtract two values (a-b).
320 If signs are identical and the values are equal according to approxEqual()
321 the method returns 0.0 instead of calculating the subtraction.
323 inline double approxSub(double a
, double b
)
325 if ( ((a
< 0.0 && b
< 0.0) || (a
> 0.0 && b
> 0.0)) && approxEqual( a
, b
) )
330 /** floor() method taking approxValue() into account.
332 Use for expected integer values being calculated by double functions.
334 inline double approxFloor(double a
)
336 return floor( approxValue( a
));
339 /** ceil() method taking approxValue() into account.
341 Use for expected integer values being calculated by double functions.
343 inline double approxCeil(double a
)
345 return ceil( approxValue( a
));
348 /** Tests whether a value is neither INF nor NAN.
350 inline bool isFinite(double d
)
352 return SAL_MATH_FINITE(d
);
355 /** If a value represents +INF or -INF.
357 The sign bit may be queried with isSignBitSet().
359 If isFinite(d)==false and isInf(d)==false then NAN.
361 inline bool isInf(double d
)
363 // exponent==0x7ff fraction==0
364 return !SAL_MATH_FINITE(d
) &&
365 (reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.fraction_hi
== 0)
366 && (reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.fraction_lo
370 /** Test on any QNAN or SNAN.
372 inline bool isNan(double d
)
374 // exponent==0x7ff fraction!=0
375 return !SAL_MATH_FINITE(d
) && (
376 (reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.fraction_hi
!= 0)
377 || (reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.fraction_lo
381 /** If the sign bit is set.
383 inline bool isSignBitSet(double d
)
385 return reinterpret_cast< sal_math_Double
* >(&d
)->inf_parts
.sign
!= 0;
388 /** Set to +INF if bNegative==false or -INF if bNegative==true.
390 inline void setInf(double * pd
, bool bNegative
)
397 md
.w32_parts
.msw
= bNegative
? 0xFFF00000 : 0x7FF00000;
398 md
.w32_parts
.lsw
= 0;
404 inline void setNan(double * pd
)
411 md
.w32_parts
.msw
= 0x7FFFFFFF;
412 md
.w32_parts
.lsw
= 0xFFFFFFFF;
416 /** If a value is a valid argument for sin(), cos(), tan().
418 IEEE 754 specifies that absolute values up to 2^64 (=1.844e19) for the
419 radian must be supported by trigonometric functions. Unfortunately, at
420 least on x86 architectures, the FPU doesn't generate an error pattern for
421 values >2^64 but produces erroneous results instead and sets only the
422 "invalid operation" (IM) flag in the status word :-( Thus the application
423 has to handle it itself.
425 inline bool isValidArcArg(double d
)
428 <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
429 * static_cast< double >(static_cast< unsigned long >(0x80000000))
433 /** Safe sin(), returns NAN if not valid.
435 inline double sin(double d
)
437 if ( isValidArcArg( d
) )
443 /** Safe cos(), returns NAN if not valid.
445 inline double cos(double d
)
447 if ( isValidArcArg( d
) )
453 /** Safe tan(), returns NAN if not valid.
455 inline double tan(double d
)
457 if ( isValidArcArg( d
) )
467 #endif // INCLUDED_RTL_MATH_HXX
469 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */