Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #ifndef INCLUDED_RTL_MATH_HXX
30 : : #define INCLUDED_RTL_MATH_HXX
31 : :
32 : : #include "rtl/math.h"
33 : : #include "rtl/string.hxx"
34 : : #include "rtl/ustring.hxx"
35 : : #include "rtl/ustrbuf.hxx"
36 : : #include "sal/mathconf.h"
37 : : #include "sal/types.h"
38 : :
39 : : #include <math.h>
40 : :
41 : : namespace rtl {
42 : :
43 : : namespace math {
44 : :
45 : : /** A wrapper around rtl_math_doubleToString.
46 : : */
47 : 0 : inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
48 : : sal_Int32 nDecPlaces,
49 : : sal_Char cDecSeparator,
50 : : sal_Int32 const * pGroups,
51 : : sal_Char cGroupSeparator,
52 : : bool bEraseTrailingDecZeros = false)
53 : : {
54 : 0 : rtl::OString aResult;
55 : : rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
56 : : cDecSeparator, pGroups, cGroupSeparator,
57 : 0 : bEraseTrailingDecZeros);
58 : 0 : return aResult;
59 : : }
60 : :
61 : : /** A wrapper around rtl_math_doubleToString, with no grouping.
62 : : */
63 : 0 : inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
64 : : sal_Int32 nDecPlaces,
65 : : sal_Char cDecSeparator,
66 : : bool bEraseTrailingDecZeros = false)
67 : : {
68 : 0 : rtl::OString aResult;
69 : : rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
70 : 0 : cDecSeparator, 0, 0, bEraseTrailingDecZeros);
71 : 0 : return aResult;
72 : : }
73 : :
74 : : /** A wrapper around rtl_math_doubleToUString.
75 : : */
76 : 0 : inline rtl::OUString doubleToUString(double fValue,
77 : : rtl_math_StringFormat eFormat,
78 : : sal_Int32 nDecPlaces,
79 : : sal_Unicode cDecSeparator,
80 : : sal_Int32 const * pGroups,
81 : : sal_Unicode cGroupSeparator,
82 : : bool bEraseTrailingDecZeros = false)
83 : : {
84 : 0 : rtl::OUString aResult;
85 : : rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
86 : : cDecSeparator, pGroups, cGroupSeparator,
87 : 0 : bEraseTrailingDecZeros);
88 : 0 : return aResult;
89 : : }
90 : :
91 : : /** A wrapper around rtl_math_doubleToUString, with no grouping.
92 : : */
93 : 65133 : inline rtl::OUString doubleToUString(double fValue,
94 : : rtl_math_StringFormat eFormat,
95 : : sal_Int32 nDecPlaces,
96 : : sal_Unicode cDecSeparator,
97 : : bool bEraseTrailingDecZeros = false)
98 : : {
99 : 65133 : rtl::OUString aResult;
100 : : rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
101 : 65133 : cDecSeparator, 0, 0, bEraseTrailingDecZeros);
102 : 65133 : return aResult;
103 : : }
104 : :
105 : : /** A wrapper around rtl_math_doubleToUString that appends to an
106 : : rtl::OUStringBuffer.
107 : : */
108 : : inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
109 : : rtl_math_StringFormat eFormat,
110 : : sal_Int32 nDecPlaces,
111 : : sal_Unicode cDecSeparator,
112 : : sal_Int32 const * pGroups,
113 : : sal_Unicode cGroupSeparator,
114 : : bool bEraseTrailingDecZeros = false)
115 : : {
116 : : rtl_uString ** pData;
117 : : sal_Int32 * pCapacity;
118 : : rBuffer.accessInternals( &pData, &pCapacity );
119 : : rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
120 : : eFormat, nDecPlaces, cDecSeparator, pGroups,
121 : : cGroupSeparator, bEraseTrailingDecZeros);
122 : : }
123 : :
124 : : /** A wrapper around rtl_math_doubleToUString that appends to an
125 : : rtl::OUStringBuffer, with no grouping.
126 : : */
127 : 1283 : inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
128 : : rtl_math_StringFormat eFormat,
129 : : sal_Int32 nDecPlaces,
130 : : sal_Unicode cDecSeparator,
131 : : bool bEraseTrailingDecZeros = false)
132 : : {
133 : : rtl_uString ** pData;
134 : : sal_Int32 * pCapacity;
135 : 1283 : rBuffer.accessInternals( &pData, &pCapacity );
136 : : rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
137 : : eFormat, nDecPlaces, cDecSeparator, 0, 0,
138 : 1283 : bEraseTrailingDecZeros);
139 : 1283 : }
140 : :
141 : : /** A wrapper around rtl_math_stringToDouble.
142 : : */
143 : 4327 : inline double stringToDouble(rtl::OString const & rString,
144 : : sal_Char cDecSeparator, sal_Char cGroupSeparator,
145 : : rtl_math_ConversionStatus * pStatus = 0,
146 : : sal_Int32 * pParsedEnd = 0)
147 : : {
148 : 4327 : sal_Char const * pBegin = rString.getStr();
149 : : sal_Char const * pEnd;
150 : : double fResult = rtl_math_stringToDouble(pBegin,
151 : 4327 : pBegin + rString.getLength(),
152 : : cDecSeparator, cGroupSeparator,
153 : 4327 : pStatus, &pEnd);
154 [ - + ]: 4327 : if (pParsedEnd != 0)
155 : 0 : *pParsedEnd = (sal_Int32)(pEnd - pBegin);
156 : 4327 : return fResult;
157 : : }
158 : :
159 : : /** A wrapper around rtl_math_uStringToDouble.
160 : : */
161 : 42390 : inline double stringToDouble(rtl::OUString const & rString,
162 : : sal_Unicode cDecSeparator,
163 : : sal_Unicode cGroupSeparator,
164 : : rtl_math_ConversionStatus * pStatus = 0,
165 : : sal_Int32 * pParsedEnd = 0)
166 : : {
167 : 42390 : sal_Unicode const * pBegin = rString.getStr();
168 : : sal_Unicode const * pEnd;
169 : : double fResult = rtl_math_uStringToDouble(pBegin,
170 : 42390 : pBegin + rString.getLength(),
171 : : cDecSeparator, cGroupSeparator,
172 : 42390 : pStatus, &pEnd);
173 [ + + ]: 42390 : if (pParsedEnd != 0)
174 : 1136 : *pParsedEnd = (sal_Int32)(pEnd - pBegin);
175 : 42390 : return fResult;
176 : : }
177 : :
178 : : /** A wrapper around rtl_math_round.
179 : : */
180 : 49489603 : inline double round(
181 : : double fValue, int nDecPlaces = 0,
182 : : rtl_math_RoundingMode eMode = rtl_math_RoundingMode_Corrected)
183 : : {
184 : 49489603 : return rtl_math_round(fValue, nDecPlaces, eMode);
185 : : }
186 : :
187 : : /** A wrapper around rtl_math_pow10Exp.
188 : : */
189 : 26431 : inline double pow10Exp(double fValue, int nExp)
190 : : {
191 : 26431 : return rtl_math_pow10Exp(fValue, nExp);
192 : : }
193 : :
194 : : /** A wrapper around rtl_math_approxValue.
195 : : */
196 : 38183 : inline double approxValue(double fValue)
197 : : {
198 : 38183 : return rtl_math_approxValue(fValue);
199 : : }
200 : :
201 : : /** A wrapper around rtl_math_expm1.
202 : : */
203 : 0 : inline double expm1(double fValue)
204 : : {
205 : 0 : return rtl_math_expm1(fValue);
206 : : }
207 : :
208 : : /** A wrapper around rtl_math_log1p.
209 : : */
210 : 0 : inline double log1p(double fValue)
211 : : {
212 : 0 : return rtl_math_log1p(fValue);
213 : : }
214 : :
215 : : /** A wrapper around rtl_math_atanh.
216 : : */
217 : 0 : inline double atanh(double fValue)
218 : : {
219 : 0 : return rtl_math_atanh(fValue);
220 : : }
221 : :
222 : : /** A wrapper around rtl_math_erf.
223 : : */
224 : 0 : inline double erf(double fValue)
225 : : {
226 : 0 : return rtl_math_erf(fValue);
227 : : }
228 : :
229 : : /** A wrapper around rtl_math_erfc.
230 : : */
231 : 0 : inline double erfc(double fValue)
232 : : {
233 : 0 : return rtl_math_erfc(fValue);
234 : : }
235 : :
236 : : /** A wrapper around rtl_math_asinh.
237 : : */
238 : 0 : inline double asinh(double fValue)
239 : : {
240 : 0 : return rtl_math_asinh(fValue);
241 : : }
242 : :
243 : : /** A wrapper around rtl_math_acosh.
244 : : */
245 : 3 : inline double acosh(double fValue)
246 : : {
247 : 3 : return rtl_math_acosh(fValue);
248 : : }
249 : :
250 : :
251 : : /** Test equality of two values with an accuracy of the magnitude of the
252 : : given values scaled by 2^-48 (4 bits roundoff stripped).
253 : :
254 : : @attention
255 : : approxEqual( value!=0.0, 0.0 ) _never_ yields true.
256 : : */
257 : 28543821 : inline bool approxEqual(double a, double b)
258 : : {
259 [ + + ]: 28543821 : if ( a == b )
260 : 9859908 : return true;
261 : 18683913 : double x = a - b;
262 : : return (x < 0.0 ? -x : x)
263 [ + + ][ + + ]: 28543821 : < ((a < 0.0 ? -a : a) * (1.0 / (16777216.0 * 16777216.0)));
264 : : }
265 : :
266 : : /** Test equality of two values with an accuracy defined by nPrec
267 : :
268 : : @attention
269 : : approxEqual( value!=0.0, 0.0 ) _never_ yields true.
270 : : */
271 : 0 : inline bool approxEqual(double a, double b, sal_Int16 nPrec)
272 : : {
273 [ # # ]: 0 : if ( a == b )
274 : 0 : return true;
275 : 0 : double x = a - b;
276 : : return (x < 0.0 ? -x : x)
277 [ # # ][ # # ]: 0 : < ((a < 0.0 ? -a : a) * (1.0 / (pow(static_cast<double>(2.0), nPrec))));
278 : : }
279 : : /** Add two values.
280 : :
281 : : If signs differ and the absolute values are equal according to approxEqual()
282 : : the method returns 0.0 instead of calculating the sum.
283 : :
284 : : If you wanted to sum up multiple values it would be convenient not to call
285 : : approxAdd() for each value but instead remember the first value not equal to
286 : : 0.0, add all other values using normal + operator, and with the result and
287 : : the remembered value call approxAdd().
288 : : */
289 : 416 : inline double approxAdd(double a, double b)
290 : : {
291 [ + + ][ - + ]: 423 : if ( ((a < 0.0 && b > 0.0) || (b < 0.0 && a > 0.0))
[ - + ]
[ # # - + ]
[ - + ]
292 : 7 : && approxEqual( a, -b ) )
293 : 0 : return 0.0;
294 : 416 : return a + b;
295 : : }
296 : :
297 : : /** Substract two values (a-b).
298 : :
299 : : If signs are identical and the values are equal according to approxEqual()
300 : : the method returns 0.0 instead of calculating the substraction.
301 : : */
302 : 49828 : inline double approxSub(double a, double b)
303 : : {
304 [ + + ][ + + ]: 49828 : if ( ((a < 0.0 && b < 0.0) || (a > 0.0 && b > 0.0)) && approxEqual( a, b ) )
[ + + ][ + + ]
[ + + ][ + + ]
305 : 8621 : return 0.0;
306 : 49828 : return a - b;
307 : : }
308 : :
309 : : /** floor() method taking approxValue() into account.
310 : :
311 : : Use for expected integer values being calculated by double functions.
312 : : */
313 : 36847 : inline double approxFloor(double a)
314 : : {
315 : 36847 : return floor( approxValue( a ));
316 : : }
317 : :
318 : : /** ceil() method taking approxValue() into account.
319 : :
320 : : Use for expected integer values being calculated by double functions.
321 : : */
322 : 1336 : inline double approxCeil(double a)
323 : : {
324 : 1336 : return ceil( approxValue( a ));
325 : : }
326 : :
327 : : /** Tests whether a value is neither INF nor NAN.
328 : : */
329 : 252687 : inline bool isFinite(double d)
330 : : {
331 : 252687 : return SAL_MATH_FINITE(d) != 0;
332 : : }
333 : :
334 : : /** If a value represents +INF or -INF.
335 : :
336 : : The sign bit may be queried with isSignBitSet().
337 : :
338 : : If isFinite(d)==false and isInf(d)==false then NAN.
339 : : */
340 : 597408 : inline bool isInf(double d)
341 : : {
342 : : // exponent==0x7ff fraction==0
343 : 597408 : return (SAL_MATH_FINITE(d) == 0) &&
344 : : (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi == 0)
345 : : && (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
346 [ + + ][ + - ]: 597408 : == 0);
[ + + ]
347 : : }
348 : :
349 : : /** Test on any QNAN or SNAN.
350 : : */
351 : 778823 : inline bool isNan(double d)
352 : : {
353 : : // exponent==0x7ff fraction!=0
354 : 778823 : return (SAL_MATH_FINITE(d) == 0) && (
355 : : (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi != 0)
356 : : || (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
357 [ + + ][ - + ]: 778823 : != 0) );
[ + + ]
358 : : }
359 : :
360 : : /** If the sign bit is set.
361 : : */
362 : 358626 : inline bool isSignBitSet(double d)
363 : : {
364 : 358626 : return reinterpret_cast< sal_math_Double * >(&d)->inf_parts.sign != 0;
365 : : }
366 : :
367 : : /** Set to +INF if bNegative==false or -INF if bNegative==true.
368 : : */
369 : 289944 : inline void setInf(double * pd, bool bNegative)
370 : : {
371 : : union
372 : : {
373 : : double sd;
374 : : sal_math_Double md;
375 : : };
376 [ + + ]: 289944 : md.w32_parts.msw = bNegative ? 0xFFF00000 : 0x7FF00000;
377 : 289944 : md.w32_parts.lsw = 0;
378 : 289944 : *pd = sd;
379 : 289944 : }
380 : :
381 : : /** Set a QNAN.
382 : : */
383 : 266203 : inline void setNan(double * pd)
384 : : {
385 : : union
386 : : {
387 : : double sd;
388 : : sal_math_Double md;
389 : : };
390 : 266203 : md.w32_parts.msw = 0x7FFFFFFF;
391 : 266203 : md.w32_parts.lsw = 0xFFFFFFFF;
392 : 266203 : *pd = sd;
393 : 266203 : }
394 : :
395 : : /** If a value is a valid argument for sin(), cos(), tan().
396 : :
397 : : IEEE 754 specifies that absolute values up to 2^64 (=1.844e19) for the
398 : : radian must be supported by trigonometric functions. Unfortunately, at
399 : : least on x86 architectures, the FPU doesn't generate an error pattern for
400 : : values >2^64 but produces erroneous results instead and sets only the
401 : : "invalid operation" (IM) flag in the status word :-( Thus the application
402 : : has to handle it itself.
403 : : */
404 : 5424 : inline bool isValidArcArg(double d)
405 : : {
406 : 5424 : return fabs(d)
407 : : <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
408 : : * static_cast< double >(static_cast< unsigned long >(0x80000000))
409 : 5424 : * 2);
410 : : }
411 : :
412 : : /** Safe sin(), returns NAN if not valid.
413 : : */
414 : 3004 : inline double sin(double d)
415 : : {
416 [ + - ]: 3004 : if ( isValidArcArg( d ) )
417 : 3004 : return ::sin( d );
418 : 0 : setNan( &d );
419 : 3004 : return d;
420 : : }
421 : :
422 : : /** Safe cos(), returns NAN if not valid.
423 : : */
424 : 2420 : inline double cos(double d)
425 : : {
426 [ + - ]: 2420 : if ( isValidArcArg( d ) )
427 : 2420 : return ::cos( d );
428 : 0 : setNan( &d );
429 : 2420 : return d;
430 : : }
431 : :
432 : : /** Safe tan(), returns NAN if not valid.
433 : : */
434 : 0 : inline double tan(double d)
435 : : {
436 [ # # ]: 0 : if ( isValidArcArg( d ) )
437 : 0 : return ::tan( d );
438 : 0 : setNan( &d );
439 : 0 : return d;
440 : : }
441 : :
442 : : }
443 : :
444 : : }
445 : :
446 : : #endif // INCLUDED_RTL_MATH_HXX
447 : :
448 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|