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 #include <com/sun/star/util/Date.hpp>
21 #include <com/sun/star/util/XNumberFormatTypes.hpp>
22 #include <com/sun/star/util/NumberFormatter.hpp>
26 #include <o3tl/any.hxx>
27 #include <rtl/math.hxx>
32 #include "analysisdefs.hxx"
33 #include "analysishelper.hxx"
34 #include <analysis.hrc>
35 #include <strings.hrc>
36 #include "deffuncname.hxx"
38 using namespace ::com::sun::star
;
39 using namespace sca::analysis
;
41 #define UNIQUE false // function name does not exist in Calc
42 #define DOUBLE true // function name exists in Calc
44 #define STDPAR false // all parameters are described
45 #define INTPAR true // first parameter is internal
47 #define FUNCDATA( FUNCNAME, DBL, OPT, NUMOFPAR, CAT ) \
48 { "get" #FUNCNAME, ANALYSIS_FUNCNAME_##FUNCNAME, ANALYSIS_##FUNCNAME, DBL, OPT, ANALYSIS_DEFFUNCNAME_##FUNCNAME, NUMOFPAR, CAT, nullptr }
50 #define FUNCDATAS( FUNCNAME, DBL, OPT, NUMOFPAR, CAT, SUFFIX ) \
51 { "get" #FUNCNAME, ANALYSIS_FUNCNAME_##FUNCNAME, ANALYSIS_##FUNCNAME, DBL, OPT, ANALYSIS_DEFFUNCNAME_##FUNCNAME, NUMOFPAR, CAT, SUFFIX }
53 const FuncDataBase pFuncDatas
[] =
55 // UNIQUE or INTPAR or
56 // function name DOUBLE STDPAR # of param category
57 FUNCDATA( Workday
, UNIQUE
, INTPAR
, 3, FDCategory::DateTime
),
58 FUNCDATA( Yearfrac
, UNIQUE
, INTPAR
, 3, FDCategory::DateTime
),
59 FUNCDATA( Edate
, UNIQUE
, INTPAR
, 2, FDCategory::DateTime
),
60 FUNCDATAS( Weeknum
, DOUBLE
, INTPAR
, 2, FDCategory::DateTime
, "_EXCEL2003" ),
61 FUNCDATA( Eomonth
, UNIQUE
, INTPAR
, 2, FDCategory::DateTime
),
62 FUNCDATAS( Networkdays
, DOUBLE
, INTPAR
, 3, FDCategory::DateTime
, "_EXCEL2003" ),
63 FUNCDATA( Iseven
, DOUBLE
, STDPAR
, 1, FDCategory::Inf
),
64 FUNCDATA( Isodd
, DOUBLE
, STDPAR
, 1, FDCategory::Inf
),
65 FUNCDATA( Multinomial
, UNIQUE
, STDPAR
, 1, FDCategory::Math
),
66 FUNCDATA( Seriessum
, UNIQUE
, STDPAR
, 4, FDCategory::Math
),
67 FUNCDATA( Quotient
, UNIQUE
, STDPAR
, 2, FDCategory::Math
),
68 FUNCDATA( Mround
, UNIQUE
, STDPAR
, 2, FDCategory::Math
),
69 FUNCDATA( Sqrtpi
, UNIQUE
, STDPAR
, 1, FDCategory::Math
),
70 FUNCDATA( Randbetween
, UNIQUE
, STDPAR
, 2, FDCategory::Math
),
71 FUNCDATAS( Gcd
, DOUBLE
, INTPAR
, 1, FDCategory::Math
, "_EXCEL2003" ),
72 FUNCDATAS( Lcm
, DOUBLE
, INTPAR
, 1, FDCategory::Math
, "_EXCEL2003" ),
73 FUNCDATA( Besseli
, UNIQUE
, STDPAR
, 2, FDCategory::Tech
),
74 FUNCDATA( Besselj
, UNIQUE
, STDPAR
, 2, FDCategory::Tech
),
75 FUNCDATA( Besselk
, UNIQUE
, STDPAR
, 2, FDCategory::Tech
),
76 FUNCDATA( Bessely
, UNIQUE
, STDPAR
, 2, FDCategory::Tech
),
77 FUNCDATA( Bin2Oct
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
78 FUNCDATA( Bin2Dec
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
79 FUNCDATA( Bin2Hex
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
80 FUNCDATA( Oct2Bin
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
81 FUNCDATA( Oct2Dec
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
82 FUNCDATA( Oct2Hex
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
83 FUNCDATA( Dec2Bin
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
84 FUNCDATA( Dec2Hex
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
85 FUNCDATA( Dec2Oct
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
86 FUNCDATA( Hex2Bin
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
87 FUNCDATA( Hex2Dec
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
88 FUNCDATA( Hex2Oct
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
89 FUNCDATA( Delta
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
90 FUNCDATA( Erf
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
91 FUNCDATA( Erfc
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
92 FUNCDATA( Gestep
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
93 FUNCDATA( Factdouble
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
94 FUNCDATA( Imabs
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
95 FUNCDATA( Imaginary
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
96 FUNCDATA( Impower
, UNIQUE
, STDPAR
, 2, FDCategory::Tech
),
97 FUNCDATA( Imargument
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
98 FUNCDATA( Imcos
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
99 FUNCDATA( Imdiv
, UNIQUE
, STDPAR
, 2, FDCategory::Tech
),
100 FUNCDATA( Imexp
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
101 FUNCDATA( Imconjugate
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
102 FUNCDATA( Imln
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
103 FUNCDATA( Imlog10
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
104 FUNCDATA( Imlog2
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
105 FUNCDATA( Improduct
, UNIQUE
, INTPAR
, 2, FDCategory::Tech
),
106 FUNCDATA( Imreal
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
107 FUNCDATA( Imsin
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
108 FUNCDATA( Imsub
, UNIQUE
, STDPAR
, 2, FDCategory::Tech
),
109 FUNCDATA( Imsqrt
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
110 FUNCDATA( Imsum
, UNIQUE
, INTPAR
, 1, FDCategory::Tech
),
111 FUNCDATA( Imtan
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
112 FUNCDATA( Imsec
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
113 FUNCDATA( Imcsc
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
114 FUNCDATA( Imcot
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
115 FUNCDATA( Imsinh
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
116 FUNCDATA( Imcosh
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
117 FUNCDATA( Imsech
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
118 FUNCDATA( Imcsch
, UNIQUE
, STDPAR
, 1, FDCategory::Tech
),
119 FUNCDATA( Complex
, UNIQUE
, STDPAR
, 3, FDCategory::Tech
),
120 FUNCDATA( Convert
, UNIQUE
, STDPAR
, 3, FDCategory::Tech
),
121 FUNCDATA( Amordegrc
, UNIQUE
, INTPAR
, 7, FDCategory::Finance
),
122 FUNCDATA( Amorlinc
, UNIQUE
, INTPAR
, 7, FDCategory::Finance
),
123 FUNCDATA( Accrint
, UNIQUE
, INTPAR
, 7, FDCategory::Finance
),
124 FUNCDATA( Accrintm
, UNIQUE
, INTPAR
, 5, FDCategory::Finance
),
125 FUNCDATA( Received
, UNIQUE
, INTPAR
, 5, FDCategory::Finance
),
126 FUNCDATA( Disc
, UNIQUE
, INTPAR
, 5, FDCategory::Finance
),
127 FUNCDATA( Duration
, UNIQUE
, INTPAR
, 6, FDCategory::Finance
),
128 FUNCDATA( Effect
, DOUBLE
, STDPAR
, 2, FDCategory::Finance
),
129 FUNCDATA( Cumprinc
, DOUBLE
, STDPAR
, 6, FDCategory::Finance
),
130 FUNCDATA( Cumipmt
, DOUBLE
, STDPAR
, 6, FDCategory::Finance
),
131 FUNCDATA( Price
, UNIQUE
, INTPAR
, 7, FDCategory::Finance
),
132 FUNCDATA( Pricedisc
, UNIQUE
, INTPAR
, 5, FDCategory::Finance
),
133 FUNCDATA( Pricemat
, UNIQUE
, INTPAR
, 6, FDCategory::Finance
),
134 FUNCDATA( Mduration
, UNIQUE
, INTPAR
, 6, FDCategory::Finance
),
135 FUNCDATA( Nominal
, DOUBLE
, STDPAR
, 2, FDCategory::Finance
),
136 FUNCDATA( Dollarfr
, UNIQUE
, STDPAR
, 2, FDCategory::Finance
),
137 FUNCDATA( Dollarde
, UNIQUE
, STDPAR
, 2, FDCategory::Finance
),
138 FUNCDATA( Yield
, UNIQUE
, INTPAR
, 7, FDCategory::Finance
),
139 FUNCDATA( Yielddisc
, UNIQUE
, INTPAR
, 5, FDCategory::Finance
),
140 FUNCDATA( Yieldmat
, UNIQUE
, INTPAR
, 6, FDCategory::Finance
),
141 FUNCDATA( Tbilleq
, UNIQUE
, INTPAR
, 3, FDCategory::Finance
),
142 FUNCDATA( Tbillprice
, UNIQUE
, INTPAR
, 3, FDCategory::Finance
),
143 FUNCDATA( Tbillyield
, UNIQUE
, INTPAR
, 3, FDCategory::Finance
),
144 FUNCDATA( Oddfprice
, UNIQUE
, INTPAR
, 9, FDCategory::Finance
),
145 FUNCDATA( Oddfyield
, UNIQUE
, INTPAR
, 9, FDCategory::Finance
),
146 FUNCDATA( Oddlprice
, UNIQUE
, INTPAR
, 8, FDCategory::Finance
),
147 FUNCDATA( Oddlyield
, UNIQUE
, INTPAR
, 8, FDCategory::Finance
),
148 FUNCDATA( Xirr
, UNIQUE
, INTPAR
, 3, FDCategory::Finance
),
149 FUNCDATA( Xnpv
, UNIQUE
, STDPAR
, 3, FDCategory::Finance
),
150 FUNCDATA( Intrate
, UNIQUE
, INTPAR
, 5, FDCategory::Finance
),
151 FUNCDATA( Coupncd
, UNIQUE
, INTPAR
, 4, FDCategory::Finance
),
152 FUNCDATA( Coupdays
, UNIQUE
, INTPAR
, 4, FDCategory::Finance
),
153 FUNCDATA( Coupdaysnc
, UNIQUE
, INTPAR
, 4, FDCategory::Finance
),
154 FUNCDATA( Coupdaybs
, UNIQUE
, INTPAR
, 4, FDCategory::Finance
),
155 FUNCDATA( Couppcd
, UNIQUE
, INTPAR
, 4, FDCategory::Finance
),
156 FUNCDATA( Coupnum
, UNIQUE
, INTPAR
, 4, FDCategory::Finance
),
157 FUNCDATA( Fvschedule
, UNIQUE
, STDPAR
, 2, FDCategory::Finance
)
161 namespace sca::analysis
{
163 sal_uInt16
DaysInMonth( sal_uInt16 nMonth
, sal_uInt16 nYear
)
165 if( (nMonth
== 2) && IsLeapYear( nYear
) )
167 static const sal_uInt16 aDaysInMonth
[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
168 return aDaysInMonth
[ nMonth
];
173 * Convert a date to a count of days starting from 01/01/0001
175 * The internal representation of a Date used in this Addin
176 * is the number of days between 01/01/0001 and the date
177 * this function converts a Day , Month, Year representation
178 * to this internal Date value.
182 sal_Int32
DateToDays( sal_uInt16 nDay
, sal_uInt16 nMonth
, sal_uInt16 nYear
)
184 sal_Int32 nDays
= (static_cast<sal_Int32
>(nYear
)-1) * 365;
185 nDays
+= ((nYear
-1) / 4) - ((nYear
-1) / 100) + ((nYear
-1) / 400);
187 for( sal_uInt16 i
= 1; i
< nMonth
; i
++ )
188 nDays
+= DaysInMonth(i
,nYear
);
196 * Convert a count of days starting from 01/01/0001 to a date
198 * The internal representation of a Date used in this Addin
199 * is the number of days between 01/01/0001 and the date
200 * this function converts this internal Date value
201 * to a Day , Month, Year representation of a Date.
205 void DaysToDate( sal_Int32 nDays
, sal_uInt16
& rDay
, sal_uInt16
& rMonth
, sal_uInt16
& rYear
)
208 throw lang::IllegalArgumentException();
217 rYear
= static_cast<sal_uInt16
>((nTempDays
/ 365) - i
);
218 nTempDays
-= (static_cast<sal_Int32
>(rYear
) -1) * 365;
219 nTempDays
-= (( rYear
-1) / 4) - (( rYear
-1) / 100) + ((rYear
-1) / 400);
228 if ( nTempDays
> 365 )
230 if ( (nTempDays
!= 366) || !IsLeapYear( rYear
) )
241 while ( nTempDays
> DaysInMonth( rMonth
, rYear
) )
243 nTempDays
-= DaysInMonth( rMonth
, rYear
);
246 rDay
= static_cast<sal_uInt16
>(nTempDays
);
251 * Get the null date used by the spreadsheet document
253 * The internal representation of a Date used in this Addin
254 * is the number of days between 01/01/0001 and the date
255 * this function returns this internal Date value for the document null date
259 sal_Int32
GetNullDate( const uno::Reference
< beans::XPropertySet
>& xOpt
)
265 uno::Any aAny
= xOpt
->getPropertyValue( "NullDate" );
268 return DateToDays( aDate
.Day
, aDate
.Month
, aDate
.Year
);
270 catch( uno::Exception
& )
275 // no null date available -> no calculations possible
276 throw uno::RuntimeException();
280 sal_Int32
GetDiffDate360(
281 sal_uInt16 nDay1
, sal_uInt16 nMonth1
, sal_uInt16 nYear1
, bool bLeapYear1
,
282 sal_uInt16 nDay2
, sal_uInt16 nMonth2
, sal_uInt16 nYear2
,
287 else if( bUSAMethod
&& ( nMonth1
== 2 && ( nDay1
== 29 || ( nDay1
== 28 && !bLeapYear1
) ) ) )
292 if( bUSAMethod
&& nDay1
!= 30 )
307 return nDay2
+ nMonth2
* 30 + nYear2
* 360 - nDay1
- nMonth1
* 30 - nYear1
* 360;
311 sal_Int32
GetDiffDate360( sal_Int32 nNullDate
, sal_Int32 nDate1
, sal_Int32 nDate2
, bool bUSAMethod
)
316 sal_uInt16 nDay1
, nMonth1
, nYear1
, nDay2
, nMonth2
, nYear2
;
318 DaysToDate( nDate1
, nDay1
, nMonth1
, nYear1
);
319 DaysToDate( nDate2
, nDay2
, nMonth2
, nYear2
);
321 return GetDiffDate360( nDay1
, nMonth1
, nYear1
, IsLeapYear( nYear1
), nDay2
, nMonth2
, nYear2
, bUSAMethod
);
325 sal_Int32
GetDaysInYears( sal_uInt16 nYear1
, sal_uInt16 nYear2
)
327 sal_uInt16 nLeaps
= 0;
328 for( sal_uInt16 n
= nYear1
; n
<= nYear2
; n
++ )
330 if( IsLeapYear( n
) )
344 sal_Int32
GetDiffDate( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
,
345 sal_Int32
* pOptDaysIn1stYear
)
347 bool bNeg
= nStartDate
> nEndDate
;
350 std::swap( nStartDate
, nEndDate
);
356 case 0: // 0=USA (NASD) 30/360
357 case 4: // 4=Europe 30/360
359 sal_uInt16 nD1
, nM1
, nY1
, nD2
, nM2
, nY2
;
361 nStartDate
+= nNullDate
;
362 nEndDate
+= nNullDate
;
364 DaysToDate( nStartDate
, nD1
, nM1
, nY1
);
365 DaysToDate( nEndDate
, nD2
, nM2
, nY2
);
367 bool bLeap
= IsLeapYear( nY1
);
368 sal_Int32 nDays
, nMonths
;
373 nMonths
+= ( nY2
- nY1
) * 12;
375 nRet
= nMonths
* 30 + nDays
;
376 if( nMode
== 0 && nM1
== 2 && nM2
!= 2 && nY1
== nY2
)
377 nRet
-= bLeap
? 1 : 2;
379 if( pOptDaysIn1stYear
)
380 *pOptDaysIn1stYear
= 360;
383 case 1: // 1=exact/exact
384 if( pOptDaysIn1stYear
)
386 sal_uInt16 nD
, nM
, nY
;
388 DaysToDate( nStartDate
+ nNullDate
, nD
, nM
, nY
);
390 *pOptDaysIn1stYear
= IsLeapYear( nY
)? 366 : 365;
392 nRet
= nEndDate
- nStartDate
;
394 case 2: // 2=exact/360
395 nRet
= nEndDate
- nStartDate
;
396 if( pOptDaysIn1stYear
)
397 *pOptDaysIn1stYear
= 360;
399 case 3: //3=exact/365
400 nRet
= nEndDate
- nStartDate
;
401 if( pOptDaysIn1stYear
)
402 *pOptDaysIn1stYear
= 365;
405 throw lang::IllegalArgumentException();
408 return bNeg
? -nRet
: nRet
;
412 double GetYearDiff( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
)
414 sal_Int32 nDays1stYear
;
415 sal_Int32 nTotalDays
= GetDiffDate( nNullDate
, nStartDate
, nEndDate
, nMode
, &nDays1stYear
);
417 return double( nTotalDays
) / double( nDays1stYear
);
421 sal_Int32
GetDaysInYear( sal_Int32 nNullDate
, sal_Int32 nDate
, sal_Int32 nMode
)
425 case 0: // 0=USA (NASD) 30/360
426 case 2: // 2=exact/360
427 case 4: // 4=Europe 30/360
429 case 1: // 1=exact/exact
431 sal_uInt16 nD
, nM
, nY
;
433 DaysToDate( nDate
, nD
, nM
, nY
);
434 return IsLeapYear( nY
)? 366 : 365;
436 case 3: //3=exact/365
439 throw lang::IllegalArgumentException();
444 // tdf69569 making code compliant with change request for ODFF1.2 par 4.11.7.7
446 * Function GetYearFrac implements YEARFRAC as defined in:
447 * Open Document Format for Office Applications version 1.2 Part 2, par. 6.10.24
448 * The calculations are defined in:
449 * Open Document Format for Office Applications version 1.2 Part 2, par. 4.11.7
451 double GetYearFrac( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
)
453 if( nStartDate
== nEndDate
)
454 return 0.0; // nothing to do...
456 if( nStartDate
> nEndDate
)
457 std::swap( nStartDate
, nEndDate
);
459 sal_Int32 nDate1
= nStartDate
+ nNullDate
;
460 sal_Int32 nDate2
= nEndDate
+ nNullDate
;
462 sal_uInt16 nDay1
, nDay2
;
463 sal_uInt16 nMonth1
, nMonth2
;
464 sal_uInt16 nYear1
, nYear2
;
466 DaysToDate( nDate1
, nDay1
, nMonth1
, nYear1
);
467 DaysToDate( nDate2
, nDay2
, nMonth2
, nYear2
);
469 // calculate days between nDate1 and nDate2
473 case 0: // 0=USA (NASD) 30/360
478 if ( nDay1
== 30 && nDay2
== 31 )
484 if ( nMonth1
== 2 && nDay1
== ( IsLeapYear( nYear1
) ? 29 : 28 ) )
487 if ( nMonth2
== 2 && nDay2
== ( IsLeapYear( nYear2
) ? 29 : 28 ) )
493 nDayDiff
= ( nYear2
- nYear1
) * 360 + ( nMonth2
- nMonth1
) * 30 + ( nDay2
- nDay1
);
495 case 1: // 1=exact/exact
496 case 2: // 2=exact/360
497 case 3: // 3=exact/365
498 nDayDiff
= nDate2
- nDate1
;
500 case 4: // 4=Europe 30/360
509 nDayDiff
= ( nYear2
- nYear1
) * 360 + ( nMonth2
- nMonth1
) * 30 + ( nDay2
- nDay1
);
512 throw lang::IllegalArgumentException();
515 //calculate days in year
519 case 0: // 0=USA (NASD) 30/360
520 case 2: // 2=exact/360
521 case 4: // 4=Europe 30/360
524 case 1: // 1=exact/exact
526 const bool isYearDifferent
= ( nYear1
!= nYear2
);
527 // ODFv1.2 part 2 section 4.11.7.7.7
528 if ( isYearDifferent
&&
529 ( ( nYear2
!= nYear1
+ 1 ) ||
530 ( nMonth1
< nMonth2
) ||
531 ( nMonth1
== nMonth2
&& nDay1
< nDay2
) ) )
533 // return average of days in year between nDate1 and nDate2, inclusive
534 sal_Int32 nDayCount
= 0;
535 for ( sal_uInt16 i
= nYear1
; i
<= nYear2
; i
++ )
536 nDayCount
+= ( IsLeapYear( i
) ? 366 : 365 );
538 nDaysInYear
= static_cast<double>(nDayCount
) / static_cast<double>( nYear2
- nYear1
+ 1 );
542 // as a consequence, !isYearDifferent or
543 // nYear2 == nYear + 1 and (nMonth1 > nMonth2 or
544 // (nMonth1 == nMonth2 and nDay1 >= nDay2))
545 assert( ( !isYearDifferent
||
546 ( nYear1
+ 1 == nYear2
&&
547 ( nMonth1
> nMonth2
||
548 ( nMonth1
== nMonth2
|| nDay1
>= nDay2
) ) ) ) );
550 // ODFv1.2 part 2 section 4.11.7.7.8 (CHANGE REQUEST PENDING, see tdf6959)
551 if ( !isYearDifferent
&& IsLeapYear( nYear1
) )
557 // ODFv1.2 part 2 section 4.11.7.7.9/10 (CHANGE REQUEST PENDING, see tdf69569)
558 // we need to determine whether there is a 29 February
559 // between nDate1 (inclusive) and nDate2 (inclusive)
560 // the case of nYear1 == nYear2 is adequately tested in previous test
561 if( isYearDifferent
&&
562 ( ( IsLeapYear( nYear1
) &&
563 ( ( nMonth1
< 2 ) || ( ( nMonth1
== 2 ) && ( nDay1
<= 29 ) ) ) ) ||
564 ( IsLeapYear( nYear2
) &&
565 ( nMonth2
> 2 || ( ( nMonth2
== 2 ) && ( nDay2
== 29 ) ) ) ) ) )
577 case 3: // 3=exact/365
580 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
582 throw lang::IllegalArgumentException();
585 return double( nDayDiff
) / nDaysInYear
;
588 double BinomialCoefficient( double n
, double k
)
590 // This method is a copy of BinomKoeff()
591 // found in sc/source/core/tool/interpr3.cxx
594 k
= ::rtl::math::approxFloor(k
);
614 double GetGcd( double f1
, double f2
)
616 double f
= fmod( f1
, f2
);
628 double ConvertToDec( const OUString
& aStr
, sal_uInt16 nBase
, sal_uInt16 nCharLim
)
630 if ( nBase
< 2 || nBase
> 36 )
631 throw lang::IllegalArgumentException();
633 sal_uInt32 nStrLen
= aStr
.getLength();
634 if( nStrLen
> nCharLim
)
635 throw lang::IllegalArgumentException();
641 const sal_Unicode
* p
= aStr
.getStr();
643 sal_uInt16 nFirstDig
= 0;
644 bool bFirstDig
= true;
645 double fBase
= nBase
;
651 if( '0' <= *p
&& *p
<= '9' )
653 else if( 'A' <= *p
&& *p
<= 'Z' )
654 n
= 10 + ( *p
- 'A' );
655 else if ( 'a' <= *p
&& *p
<= 'z' )
656 n
= 10 + ( *p
- 'a' );
661 throw lang::IllegalArgumentException(); // illegal char!
668 fVal
= fVal
* fBase
+ double( n
);
674 if( nStrLen
== nCharLim
&& !bFirstDig
&& (nFirstDig
>= nBase
/ 2) )
675 { // handling negative values
676 fVal
= ( pow( double( nBase
), double( nCharLim
) ) - fVal
); // complement
684 static char GetMaxChar( sal_uInt16 nBase
)
686 const char* const c
= "--123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
691 OUString
ConvertFromDec( double fNum
, double fMin
, double fMax
, sal_uInt16 nBase
,
692 sal_Int32 nPlaces
, sal_Int32 nMaxPlaces
, bool bUsePlaces
)
694 fNum
= ::rtl::math::approxFloor( fNum
);
695 fMin
= ::rtl::math::approxFloor( fMin
);
696 fMax
= ::rtl::math::approxFloor( fMax
);
698 if( fNum
< fMin
|| fNum
> fMax
|| ( bUsePlaces
&& ( nPlaces
<= 0 || nPlaces
> nMaxPlaces
) ) )
699 throw lang::IllegalArgumentException();
701 sal_Int64 nNum
= static_cast< sal_Int64
>( fNum
);
702 bool bNeg
= nNum
< 0;
704 nNum
= sal_Int64( pow( double( nBase
), double( nMaxPlaces
) ) ) + nNum
;
706 OUString
aRet(OUString::number(nNum
, nBase
).toAsciiUpperCase());
711 sal_Int32 nLen
= aRet
.getLength();
712 if( !bNeg
&& nLen
> nPlaces
)
714 throw lang::IllegalArgumentException();
716 else if( ( bNeg
&& nLen
< nMaxPlaces
) || ( !bNeg
&& nLen
< nPlaces
) )
718 sal_Int32 nLeft
= nPlaces
- nLen
;
719 std::unique_ptr
<char[]> p( new char[ nLeft
+ 1 ] );
720 memset( p
.get(), bNeg
? GetMaxChar( nBase
) : '0', nLeft
);
722 aRet
= OUString( p
.get(), nLeft
, RTL_TEXTENCODING_MS_1252
) + aRet
;
729 double Erf( double x
)
734 double Erfc( double x
)
739 static bool IsNum( sal_Unicode c
)
741 return c
>= '0' && c
<= '9';
745 static bool IsComma( sal_Unicode c
)
747 return c
== '.' || c
== ',';
751 static bool IsExpStart( sal_Unicode c
)
753 return c
== 'e' || c
== 'E';
757 static bool IsImagUnit( sal_Unicode c
)
759 return c
== 'i' || c
== 'j';
763 static sal_uInt16
GetVal( sal_Unicode c
)
765 return sal_uInt16( c
- '0' );
769 bool ParseDouble( const sal_Unicode
*& rp
, double& rRet
)
773 double fMult
= 0.1; // multiplier to multiply digits with, when adding fractional ones
775 sal_Int32 nMaxExp
= 307;
776 sal_uInt16 nDigCnt
= 18; // max. number of digits to read in, rest doesn't matter
778 enum State
{ S_End
= 0, S_Sign
, S_IntStart
, S_Int
, S_IgnoreIntDigs
, S_Frac
, S_IgnoreFracDigs
, S_ExpSign
, S_Exp
};
782 bool bNegNum
= false;
783 bool bNegExp
= false;
785 const sal_Unicode
* p
= rp
;
807 else if( IsComma( c
) )
819 else if( IsComma( c
) )
821 else if( IsImagUnit( c
) )
833 fInt
+= double( GetVal( c
) );
836 eS
= S_IgnoreIntDigs
;
838 else if( IsComma( c
) )
840 else if( IsExpStart( c
) )
845 case S_IgnoreIntDigs
:
847 nExp
++; // just multiply num with 10... ;-)
848 else if( IsComma( c
) )
850 else if( IsExpStart( c
) )
858 fFrac
+= double( GetVal( c
) ) * fMult
;
863 eS
= S_IgnoreFracDigs
;
865 else if( IsExpStart( c
) )
870 case S_IgnoreFracDigs
:
871 if( IsExpStart( c
) )
873 else if( !IsNum( c
) )
901 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
909 p
--; // set pointer back to last
914 if (fInt
!= 0.0) // exact check; log10(0.0) may entail a pole error
916 sal_Int32 nLog10
= sal_Int32( log10( fInt
) );
921 if( nLog10
+ nExp
> nMaxExp
)
924 fInt
= ::rtl::math::pow10Exp( fInt
, nExp
);
936 OUString
GetString( double f
, bool bLeadingSign
, sal_uInt16 nMaxDig
)
938 const int nBuff
= 256;
939 char aBuff
[ nBuff
+ 1 ];
940 const char* pFormStr
= bLeadingSign
? "%+.*g" : "%.*g";
941 int nLen
= snprintf( aBuff
, nBuff
, pFormStr
, int( nMaxDig
), f
);
942 // you never know which underlying implementation you get ...
944 if ( nLen
< 0 || nLen
> nBuff
)
945 nLen
= strlen( aBuff
);
947 OUString
aRet( aBuff
, nLen
, RTL_TEXTENCODING_MS_1252
);
953 double GetAmordegrc( sal_Int32 nNullDate
, double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
,
954 double fRestVal
, double fPer
, double fRate
, sal_Int32 nBase
)
956 sal_uInt32 nPer
= sal_uInt32( fPer
);
957 double fUsePer
= 1.0 / fRate
;
962 else if( fUsePer
< 5.0 )
964 else if( fUsePer
<= 6.0 )
970 double fNRate
= ::rtl::math::round( GetYearFrac( nNullDate
, nDate
, nFirstPer
, nBase
) * fRate
* fCost
);
972 double fRest
= fCost
- fRestVal
; // aboriginal cost - residual value - sum of all write-downs
974 for( sal_uInt32 n
= 0 ; n
< nPer
; n
++ )
976 fNRate
= ::rtl::math::round( fRate
* fCost
);
985 return ::rtl::math::round( fCost
* 0.5 );
998 double GetAmorlinc( sal_Int32 nNullDate
, double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
,
999 double fRestVal
, double fPer
, double fRate
, sal_Int32 nBase
)
1001 sal_uInt32 nPer
= sal_uInt32( fPer
);
1002 double fOneRate
= fCost
* fRate
;
1003 double fCostDelta
= fCost
- fRestVal
;
1004 double f0Rate
= GetYearFrac( nNullDate
, nDate
, nFirstPer
, nBase
) * fRate
* fCost
;
1005 sal_uInt32 nNumOfFullPeriods
= sal_uInt32( ( fCost
- fRestVal
- f0Rate
) / fOneRate
);
1007 double fResult
= 0.0;
1010 else if( nPer
<= nNumOfFullPeriods
)
1012 else if( nPer
== nNumOfFullPeriods
+ 1 )
1013 fResult
= fCostDelta
- fOneRate
* nNumOfFullPeriods
- f0Rate
;
1015 if ( fResult
> 0.0 )
1022 double GetDuration( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
,
1023 double fYield
, sal_Int32 nFreq
, sal_Int32 nBase
)
1025 double fYearfrac
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
);
1026 double fNumOfCoups
= GetCoupnum( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1028 const double f100
= 100.0;
1029 fCoup
*= f100
/ double( nFreq
); // fCoup is used as cash flow
1033 double nDiff
= fYearfrac
* nFreq
- fNumOfCoups
;
1037 for( t
= 1.0 ; t
< fNumOfCoups
; t
++ )
1038 fDur
+= ( t
+ nDiff
) * fCoup
/ pow( fYield
, t
+ nDiff
);
1040 fDur
+= ( fNumOfCoups
+ nDiff
) * ( fCoup
+ f100
) / pow( fYield
, fNumOfCoups
+ nDiff
);
1043 for( t
= 1.0 ; t
< fNumOfCoups
; t
++ )
1044 p
+= fCoup
/ pow( fYield
, t
+ nDiff
);
1046 p
+= ( fCoup
+ f100
) / pow( fYield
, fNumOfCoups
+ nDiff
);
1049 fDur
/= double( nFreq
);
1055 double GetYieldmat( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nIssue
,
1056 double fRate
, double fPrice
, sal_Int32 nBase
)
1058 double fIssMat
= GetYearFrac( nNullDate
, nIssue
, nMat
, nBase
);
1059 double fIssSet
= GetYearFrac( nNullDate
, nIssue
, nSettle
, nBase
);
1060 double fSetMat
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
);
1062 double y
= 1.0 + fIssMat
* fRate
;
1063 y
/= fPrice
/ 100.0 + fIssSet
* fRate
;
1071 double GetOddfprice( sal_Int32
/*nNullDate*/, sal_Int32
/*nSettle*/, sal_Int32
/*nMat*/, sal_Int32
/*nIssue*/,
1072 sal_Int32
/*nFirstCoup*/, double /*fRate*/, double /*fYield*/, double /*fRedemp*/, sal_Int32
/*nFreq*/,
1073 sal_Int32
/*nBase*/ )
1075 // If you change this to not unconditionally throw, the
1076 // SAL_WNOUNREACHABLE_CODE_PUSH/POP around the caller in
1077 // financial.cxx can be removed.
1078 throw uno::RuntimeException();
1082 double getYield_( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
, double fPrice
,
1083 double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
)
1085 double fRate
= fCoup
;
1086 double fPriceN
= 0.0;
1087 double fYield1
= 0.0;
1088 double fYield2
= 1.0;
1089 double fPrice1
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield1
, fRedemp
, nFreq
, nBase
);
1090 double fPrice2
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield2
, fRedemp
, nFreq
, nBase
);
1091 double fYieldN
= ( fYield2
- fYield1
) * 0.5;
1093 for( sal_uInt32 nIter
= 0 ; nIter
< 100 && !rtl::math::approxEqual(fPriceN
, fPrice
) ; nIter
++ )
1095 fPriceN
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYieldN
, fRedemp
, nFreq
, nBase
);
1097 if( rtl::math::approxEqual(fPrice
, fPrice1
) )
1099 else if( rtl::math::approxEqual(fPrice
, fPrice2
) )
1101 else if( rtl::math::approxEqual(fPrice
, fPriceN
) )
1103 else if( fPrice
< fPrice2
)
1106 fPrice2
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield2
, fRedemp
, nFreq
, nBase
);
1108 fYieldN
= ( fYield2
- fYield1
) * 0.5;
1112 if( fPrice
< fPriceN
)
1123 fYieldN
= fYield2
- ( fYield2
- fYield1
) * ( ( fPrice
- fPrice2
) / ( fPrice1
- fPrice2
) );
1127 if( fabs( fPrice
- fPriceN
) > fPrice
/ 100.0 )
1128 throw lang::IllegalArgumentException(); // result not precise enough
1134 double getPrice_( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fRate
, double fYield
,
1135 double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
)
1137 double fFreq
= nFreq
;
1139 double fE
= GetCoupdays( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1140 double fDSC_E
= GetCoupdaysnc( nNullDate
, nSettle
, nMat
, nFreq
, nBase
) / fE
;
1141 double fN
= GetCoupnum( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1142 double fA
= GetCoupdaybs( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1144 double fRet
= fRedemp
/ ( pow( 1.0 + fYield
/ fFreq
, fN
- 1.0 + fDSC_E
) );
1145 fRet
-= 100.0 * fRate
/ fFreq
* fA
/ fE
;
1147 double fT1
= 100.0 * fRate
/ fFreq
;
1148 double fT2
= 1.0 + fYield
/ fFreq
;
1150 for( double fK
= 0.0 ; fK
< fN
; fK
++ )
1151 fRet
+= fT1
/ pow( fT2
, fK
+ fDSC_E
);
1157 double GetOddfyield( sal_Int32
/*nNullDate*/, sal_Int32
/*nSettle*/, sal_Int32
/*nMat*/, sal_Int32
/*nIssue*/,
1158 sal_Int32
/*nFirstCoup*/, double /*fRate*/, double /*fPrice*/, double /*fRedemp*/, sal_Int32
/*nFreq*/,
1159 sal_Int32
/*nBase*/ )
1161 // If you change this to not unconditionally throw, the
1162 // SAL_WNOUNREACHABLE_CODE_PUSH/POP around the caller in
1163 // financial.cxx can be removed.
1164 throw uno::RuntimeException();
1168 double GetOddlprice( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastCoup
,
1169 double fRate
, double fYield
, double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
)
1171 double fFreq
= double( nFreq
);
1172 double fDCi
= GetYearFrac( nNullDate
, nLastCoup
, nMat
, nBase
) * fFreq
;
1173 double fDSCi
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
) * fFreq
;
1174 double fAi
= GetYearFrac( nNullDate
, nLastCoup
, nSettle
, nBase
) * fFreq
;
1176 double p
= fRedemp
+ fDCi
* 100.0 * fRate
/ fFreq
;
1177 p
/= fDSCi
* fYield
/ fFreq
+ 1.0;
1178 p
-= fAi
* 100.0 * fRate
/ fFreq
;
1184 double GetOddlyield( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastCoup
,
1185 double fRate
, double fPrice
, double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
)
1187 double fFreq
= double( nFreq
);
1188 double fDCi
= GetYearFrac( nNullDate
, nLastCoup
, nMat
, nBase
) * fFreq
;
1189 double fDSCi
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
) * fFreq
;
1190 double fAi
= GetYearFrac( nNullDate
, nLastCoup
, nSettle
, nBase
) * fFreq
;
1192 double y
= fRedemp
+ fDCi
* 100.0 * fRate
/ fFreq
;
1193 y
/= fPrice
+ fAi
* 100.0 * fRate
/ fFreq
;
1201 double GetPmt( double fRate
, double fNper
, double fPv
, double fFv
, sal_Int32 nPayType
)
1205 fPmt
= ( fPv
+ fFv
) / fNper
;
1208 double fTerm
= pow( 1.0 + fRate
, fNper
);
1210 fPmt
= ( fFv
* fRate
/ ( fTerm
- 1.0 ) + fPv
* fRate
/ ( 1.0 - 1.0 / fTerm
) ) / ( 1.0 + fRate
);
1212 fPmt
= fFv
* fRate
/ ( fTerm
- 1.0 ) + fPv
* fRate
/ ( 1.0 - 1.0 / fTerm
);
1219 double GetFv( double fRate
, double fNper
, double fPmt
, double fPv
, sal_Int32 nPayType
)
1223 fFv
= fPv
+ fPmt
* fNper
;
1226 double fTerm
= pow( 1.0 + fRate
, fNper
);
1228 fFv
= fPv
* fTerm
+ fPmt
* ( 1.0 + fRate
) * ( fTerm
- 1.0 ) / fRate
;
1230 fFv
= fPv
* fTerm
+ fPmt
* ( fTerm
- 1.0 ) / fRate
;
1236 // financial functions COUP***
1238 // COUPPCD: find last coupon date before settlement (can be equal to settlement)
1239 /// @throws css::lang::IllegalArgumentException
1240 static void lcl_GetCouppcd( ScaDate
& rDate
, const ScaDate
& rSettle
, const ScaDate
& rMat
, sal_Int32 nFreq
)
1243 rDate
.setYear( rSettle
.getYear() );
1244 if( rDate
< rSettle
)
1245 rDate
.addYears( 1 );
1246 while( rDate
> rSettle
)
1247 rDate
.addMonths( -12 / nFreq
);
1250 double GetCouppcd( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1252 if( nSettle
>= nMat
|| isFreqInvalid(nFreq
) )
1253 throw lang::IllegalArgumentException();
1256 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1257 return aDate
.getDate( nNullDate
);
1260 // COUPNCD: find first coupon date after settlement (is never equal to settlement)
1261 /// @throws css::lang::IllegalArgumentException
1262 static void lcl_GetCoupncd( ScaDate
& rDate
, const ScaDate
& rSettle
, const ScaDate
& rMat
, sal_Int32 nFreq
)
1265 rDate
.setYear( rSettle
.getYear() );
1266 if( rDate
> rSettle
)
1267 rDate
.addYears( -1 );
1268 while( rDate
<= rSettle
)
1269 rDate
.addMonths( 12 / nFreq
);
1272 double GetCoupncd( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1274 if( nSettle
>= nMat
|| isFreqInvalid(nFreq
) )
1275 throw lang::IllegalArgumentException();
1278 lcl_GetCoupncd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1279 return aDate
.getDate( nNullDate
);
1282 // COUPDAYBS: get day count: coupon date before settlement <-> settlement
1283 double GetCoupdaybs( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1285 if( nSettle
>= nMat
|| isFreqInvalid(nFreq
) )
1286 throw lang::IllegalArgumentException();
1288 ScaDate
aSettle( nNullDate
, nSettle
, nBase
);
1290 lcl_GetCouppcd( aDate
, aSettle
, ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1291 return ScaDate::getDiff( aDate
, aSettle
);
1294 // COUPDAYSNC: get day count: settlement <-> coupon date after settlement
1295 double GetCoupdaysnc( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1297 if( nSettle
>= nMat
|| isFreqInvalid(nFreq
) )
1298 throw lang::IllegalArgumentException();
1300 if( (nBase
!= 0) && (nBase
!= 4) )
1302 ScaDate
aSettle( nNullDate
, nSettle
, nBase
);
1304 lcl_GetCoupncd( aDate
, aSettle
, ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1305 return ScaDate::getDiff( aSettle
, aDate
);
1307 return GetCoupdays( nNullDate
, nSettle
, nMat
, nFreq
, nBase
) - GetCoupdaybs( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1310 // COUPDAYS: get day count: coupon date before settlement <-> coupon date after settlement
1311 double GetCoupdays( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1313 if( nSettle
>= nMat
|| isFreqInvalid(nFreq
) )
1314 throw lang::IllegalArgumentException();
1319 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1320 ScaDate
aNextDate( aDate
);
1321 aNextDate
.addMonths( 12 / nFreq
);
1322 return ScaDate::getDiff( aDate
, aNextDate
);
1324 return static_cast< double >( GetDaysInYear( 0, 0, nBase
) ) / nFreq
;
1327 // COUPNUM: get count of coupon dates
1328 double GetCoupnum( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1330 if( nSettle
>= nMat
|| isFreqInvalid(nFreq
) )
1331 throw lang::IllegalArgumentException();
1333 ScaDate
aMat( nNullDate
, nMat
, nBase
);
1335 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), aMat
, nFreq
);
1336 sal_uInt16 nMonths
= (aMat
.getYear() - aDate
.getYear()) * 12 + aMat
.getMonth() - aDate
.getMonth();
1337 return static_cast< double >( nMonths
* nFreq
/ 12 );
1340 FuncData::FuncData(const FuncDataBase
& r
) :
1341 aIntName( OUString::createFromAscii( r
.pIntName
) ),
1342 pUINameID( r
.pUINameID
),
1343 pDescrID( r
.pDescrID
),
1344 bDouble( r
.bDouble
),
1345 bWithOpt( r
.bWithOpt
),
1346 nParam( r
.nNumOfParams
),
1350 aSuffix
= OUString::createFromAscii(r
.pSuffix
);
1352 aCompList
.resize(2);
1353 aCompList
[0] = OUString(r
.pCompListID
[0], strlen(r
.pCompListID
[0]), RTL_TEXTENCODING_UTF8
);
1354 aCompList
[1] = OUString(r
.pCompListID
[1], strlen(r
.pCompListID
[1]), RTL_TEXTENCODING_UTF8
);
1357 sal_uInt16
FuncData::GetStrIndex( sal_uInt16 nParamNum
) const
1362 if( nParamNum
> nParam
)
1365 return nParamNum
* 2;
1368 void InitFuncDataList(FuncDataList
& rList
)
1370 for(const auto & rFuncData
: pFuncDatas
)
1371 rList
.push_back(FuncData(rFuncData
));
1374 SortedIndividualInt32List::SortedIndividualInt32List()
1379 SortedIndividualInt32List::~SortedIndividualInt32List()
1384 void SortedIndividualInt32List::Insert( sal_Int32 nDay
)
1386 sal_uInt32 nIndex
= Count();
1390 sal_Int32 nRef
= Get( nIndex
);
1393 else if( nDay
> nRef
)
1395 maVector
.insert( maVector
.begin() + nIndex
+ 1, nDay
);
1399 maVector
.insert( maVector
.begin(), nDay
);
1403 void SortedIndividualInt32List::Insert( sal_Int32 nDay
, sal_Int32 nNullDate
, bool bInsertOnWeekend
)
1409 if( bInsertOnWeekend
|| (GetDayOfWeek( nDay
) < 5) )
1414 void SortedIndividualInt32List::Insert(
1415 double fDay
, sal_Int32 nNullDate
, bool bInsertOnWeekend
)
1417 if( (fDay
< -2147483648.0) || (fDay
> 2147483649.0) )
1418 throw lang::IllegalArgumentException();
1419 Insert( static_cast< sal_Int32
>( fDay
), nNullDate
, bInsertOnWeekend
);
1423 bool SortedIndividualInt32List::Find( sal_Int32 nVal
) const
1425 sal_uInt32 nE
= Count();
1427 if( !nE
|| nVal
< Get( 0 ) || nVal
> Get( nE
- 1 ) )
1432 for( sal_uInt32 n
= 0 ; n
< nE
; n
++ )
1434 sal_Int32 nRef
= Get( n
);
1438 else if( nRef
> nVal
)
1445 void SortedIndividualInt32List::InsertHolidayList(
1446 const ScaAnyConverter
& rAnyConv
,
1447 const uno::Any
& rHolAny
,
1448 sal_Int32 nNullDate
,
1449 bool bInsertOnWeekend
)
1452 if( rAnyConv
.getDouble( fDay
, rHolAny
) )
1453 Insert( fDay
, nNullDate
, bInsertOnWeekend
);
1457 void SortedIndividualInt32List::InsertHolidayList(
1458 ScaAnyConverter
& rAnyConv
,
1459 const uno::Reference
< beans::XPropertySet
>& xOptions
,
1460 const uno::Any
& rHolAny
,
1461 sal_Int32 nNullDate
)
1463 rAnyConv
.init( xOptions
);
1464 if( rHolAny
.getValueTypeClass() == uno::TypeClass_SEQUENCE
)
1466 uno::Sequence
< uno::Sequence
< uno::Any
> > aAnySeq
;
1467 if( !(rHolAny
>>= aAnySeq
) )
1468 throw lang::IllegalArgumentException();
1470 for( const uno::Sequence
< uno::Any
>& rSubSeq
: std::as_const(aAnySeq
) )
1472 for( const uno::Any
& rAny
: rSubSeq
)
1473 InsertHolidayList( rAnyConv
, rAny
, nNullDate
, false/*bInsertOnWeekend*/ );
1477 InsertHolidayList( rAnyConv
, rHolAny
, nNullDate
, false/*bInsertOnWeekend*/ );
1481 void ScaDoubleList::Append(
1482 const uno::Sequence
< uno::Sequence
< double > >& rValueSeq
)
1484 for( const uno::Sequence
< double >& rSubSeq
: rValueSeq
)
1486 for( const double fValue
: rSubSeq
)
1492 void ScaDoubleList::Append(
1493 const uno::Sequence
< uno::Sequence
< sal_Int32
> >& rValueSeq
)
1495 for( const uno::Sequence
< sal_Int32
>& rSubSeq
: rValueSeq
)
1497 for( const sal_Int32 nValue
: rSubSeq
)
1502 void ScaDoubleList::Append(
1503 const ScaAnyConverter
& rAnyConv
,
1504 const uno::Any
& rAny
,
1507 if( auto s
= o3tl::tryAccess
<
1508 css::uno::Sequence
<css::uno::Sequence
<css::uno::Any
>>>(rAny
) )
1509 Append( rAnyConv
, *s
, bIgnoreEmpty
);
1513 if( rAnyConv
.getDouble( fValue
, rAny
) )
1515 else if( !bIgnoreEmpty
)
1521 void ScaDoubleList::Append(
1522 const ScaAnyConverter
& rAnyConv
,
1523 const uno::Sequence
< uno::Any
>& rAnySeq
,
1526 for( const uno::Any
& rAny
: rAnySeq
)
1527 Append( rAnyConv
, rAny
, bIgnoreEmpty
);
1531 void ScaDoubleList::Append(
1532 const ScaAnyConverter
& rAnyConv
,
1533 const uno::Sequence
< uno::Sequence
< uno::Any
> >& rAnySeq
,
1536 for( const uno::Sequence
< uno::Any
>& rArray
: rAnySeq
)
1537 Append( rAnyConv
, rArray
, bIgnoreEmpty
);
1540 void ScaDoubleList::Append(
1541 ScaAnyConverter
& rAnyConv
,
1542 const uno::Reference
< beans::XPropertySet
>& xOpt
,
1543 const uno::Sequence
< uno::Any
>& rAnySeq
)
1545 rAnyConv
.init( xOpt
);
1546 Append( rAnyConv
, rAnySeq
, true/*bIgnoreEmpty*/ );
1550 bool ScaDoubleList::CheckInsert( double ) const
1556 bool ScaDoubleListGT0::CheckInsert( double fValue
) const
1559 throw lang::IllegalArgumentException();
1560 return fValue
> 0.0;
1564 bool ScaDoubleListGE0::CheckInsert( double fValue
) const
1567 throw lang::IllegalArgumentException();
1572 Complex::Complex( const OUString
& rStr
)
1574 if( !ParseString( rStr
, *this ) )
1575 throw lang::IllegalArgumentException();
1579 inline bool Complex::IsImagUnit( sal_Unicode c
)
1581 return c
== 'i' || c
== 'j';
1584 bool Complex::ParseString( const OUString
& rStr
, Complex
& rCompl
)
1586 rCompl
.c
= '\0'; // do not force a symbol, if only real part present
1588 const sal_Unicode
* pStr
= rStr
.getStr();
1590 if( IsImagUnit( *pStr
) && rStr
.getLength() == 1)
1600 if( !ParseDouble( pStr
, f
) )
1605 case '-': // imag part follows
1609 if( IsImagUnit( pStr
[ 1 ] ) )
1611 rCompl
.c
= pStr
[ 1 ];
1612 if( pStr
[ 2 ] == 0 )
1615 rCompl
.i
= ( *pStr
== '+' )? 1.0 : -1.0;
1619 else if( ParseDouble( pStr
, f
) && IsImagUnit( *pStr
) )
1643 case 0: // only real-part
1653 OUString
Complex::GetString() const
1657 OUStringBuffer aRet
;
1659 bool bHasImag
= i
!= 0.0;
1660 bool bHasReal
= !bHasImag
|| (r
!= 0.0);
1663 aRet
.append(::GetString( r
, false ));
1671 else if( i
== -1.0 )
1674 aRet
.append(::GetString( i
, bHasReal
));
1675 aRet
.append((c
!= 'j') ? 'i' : 'j');
1678 return aRet
.makeStringAndClear();
1682 double Complex::Arg() const
1684 if( r
== 0.0 && i
== 0.0 )
1685 throw lang::IllegalArgumentException();
1687 double phi
= acos( r
/ Abs() );
1696 void Complex::Power( double fPower
)
1698 if( r
== 0.0 && i
== 0.0 )
1701 throw lang::IllegalArgumentException();
1710 phi
= acos( r
/ p
);
1714 p
= pow( p
, fPower
);
1722 void Complex::Sqrt()
1724 static const double fMultConst
= M_SQRT1_2
;
1726 double i_
= sqrt( p
- r
) * fMultConst
;
1728 r
= sqrt( p
+ r
) * fMultConst
;
1729 i
= ( i
< 0.0 )? -i_
: i_
;
1735 if( !::rtl::math::isValidArcArg( r
) )
1736 throw lang::IllegalArgumentException();
1742 r_
= sin( r
) * cosh( i
);
1743 i
= cos( r
) * sinh( i
);
1753 if( !::rtl::math::isValidArcArg( r
) )
1754 throw lang::IllegalArgumentException();
1760 r_
= cos( r
) * cosh( i
);
1761 i
= -( sin( r
) * sinh( i
) );
1769 void Complex::Div( const Complex
& z
)
1771 if( z
.r
== 0 && z
.i
== 0 )
1772 throw lang::IllegalArgumentException();
1779 double f
= 1.0 / ( a2
* a2
+ b2
* b2
);
1781 r
= ( a1
* a2
+ b1
* b2
) * f
;
1782 i
= ( a2
* b1
- a1
* b2
) * f
;
1790 double fE
= exp( r
);
1798 if( r
== 0.0 && i
== 0.0 )
1799 throw lang::IllegalArgumentException();
1801 double fAbs
= Abs();
1802 bool bNegi
= i
< 0.0;
1804 i
= acos( r
/ fAbs
);
1813 void Complex::Log10()
1820 void Complex::Log2()
1831 if( !::rtl::math::isValidArcArg( 2.0 * r
) )
1832 throw lang::IllegalArgumentException();
1833 double fScale
=1.0 / ( cos( 2.0 * r
) + cosh( 2.0 * i
));
1834 r
= sin( 2.0 * r
) * fScale
;
1835 i
= sinh( 2.0 * i
) * fScale
;
1839 if( !::rtl::math::isValidArcArg( r
) )
1840 throw lang::IllegalArgumentException();
1850 if( !::rtl::math::isValidArcArg( 2 * r
) )
1851 throw lang::IllegalArgumentException();
1852 double fScale
= 1.0 / (cosh( 2.0 * i
) + cos ( 2.0 * r
));
1854 r_
= 2.0 * cos( r
) * cosh( i
) * fScale
;
1855 i
= 2.0 * sin( r
) * sinh( i
) * fScale
;
1860 if( !::rtl::math::isValidArcArg( r
) )
1861 throw lang::IllegalArgumentException();
1871 if( !::rtl::math::isValidArcArg( 2 * r
) )
1872 throw lang::IllegalArgumentException();
1873 double fScale
= 1.0 / (cosh( 2.0 * i
) - cos ( 2.0 * r
));
1875 r_
= 2.0 * sin( r
) * cosh( i
) * fScale
;
1876 i
= -2.0 * cos( r
) * sinh( i
) * fScale
;
1881 if( !::rtl::math::isValidArcArg( r
) )
1882 throw lang::IllegalArgumentException();
1892 if( !::rtl::math::isValidArcArg( 2.0 * r
) )
1893 throw lang::IllegalArgumentException();
1894 double fScale
=1.0 / ( cosh( 2.0 * i
) - cos( 2.0 * r
) );
1895 r
= sin( 2.0 * r
) * fScale
;
1896 i
= - ( sinh( 2.0 * i
) * fScale
);
1900 if( !::rtl::math::isValidArcArg( r
) )
1901 throw lang::IllegalArgumentException();
1907 void Complex::Sinh()
1909 if( !::rtl::math::isValidArcArg( r
) )
1910 throw lang::IllegalArgumentException();
1915 r_
= sinh( r
) * cos( i
);
1916 i
= cosh( r
) * sin( i
);
1924 void Complex::Cosh()
1926 if( !::rtl::math::isValidArcArg( r
) )
1927 throw lang::IllegalArgumentException();
1932 r_
= cosh( r
) * cos( i
);
1933 i
= sinh( r
) * sin( i
);
1941 void Complex::Sech()
1945 if( !::rtl::math::isValidArcArg( 2.0 * r
) )
1946 throw lang::IllegalArgumentException();
1947 double fScale
=1.0 / ( cosh( 2.0 * r
) + cos( 2.0 * i
));
1949 r_
= 2.0 * cosh( r
) * cos( i
) * fScale
;
1950 i
= - (2.0 * sinh( r
) * sin( i
) * fScale
);
1955 if( !::rtl::math::isValidArcArg( r
) )
1956 throw lang::IllegalArgumentException();
1957 r
= 1.0 / cosh( r
);
1962 void Complex::Csch()
1966 if( !::rtl::math::isValidArcArg( 2.0 * r
) )
1967 throw lang::IllegalArgumentException();
1968 double fScale
=1.0 / ( cosh( 2.0 * r
) - cos( 2.0 * i
));
1970 r_
= 2.0 * sinh( r
) * cos( i
) * fScale
;
1971 i
= - ( 2.0 * cosh( r
) * sin( i
) * fScale
);
1976 if( !::rtl::math::isValidArcArg( r
) )
1977 throw lang::IllegalArgumentException();
1978 r
= 1.0 / sinh( r
);
1983 ComplexList::~ComplexList()
1988 void ComplexList::Append( const uno::Sequence
< uno::Sequence
< OUString
> >& r
)
1990 for( const uno::Sequence
< OUString
>& rList
: r
)
1992 for( const OUString
& rStr
: rList
)
1994 if( !rStr
.isEmpty() )
1995 Append( Complex( rStr
) );
2001 void ComplexList::Append( const uno::Sequence
< uno::Any
>& aMultPars
)
2003 for( const uno::Any
& r
: aMultPars
)
2005 switch( r
.getValueTypeClass() )
2007 case uno::TypeClass_VOID
: break;
2008 case uno::TypeClass_STRING
:
2010 auto pStr
= o3tl::forceAccess
<OUString
>(r
);
2012 if( !pStr
->isEmpty() )
2013 Append( Complex( *pStr
) );
2016 case uno::TypeClass_DOUBLE
:
2017 Append( Complex( *o3tl::forceAccess
<double>(r
), 0.0 ) );
2019 case uno::TypeClass_SEQUENCE
:
2021 uno::Sequence
< uno::Sequence
< uno::Any
> > aValArr
;
2022 if( !(r
>>= aValArr
) )
2023 throw lang::IllegalArgumentException();
2025 for( const uno::Sequence
< uno::Any
>& rArr
: std::as_const(aValArr
) )
2030 throw lang::IllegalArgumentException();
2035 ConvertData::ConvertData(const char p
[], double fC
, ConvertDataClass e
, bool bPrefSupport
)
2037 , aName(p
, strlen(p
), RTL_TEXTENCODING_MS_1252
)
2039 , bPrefixSupport(bPrefSupport
)
2043 ConvertData::~ConvertData()
2047 sal_Int16
ConvertData::GetMatchingLevel( const OUString
& rRef
) const
2049 OUString aStr
= rRef
;
2050 sal_Int32 nLen
= rRef
.getLength();
2051 sal_Int32 nIndex
= rRef
.lastIndexOf( '^' );
2052 if( nIndex
> 0 && nIndex
== ( nLen
- 2 ) )
2053 aStr
= aStr
.subView( 0, nLen
- 2 ) + OUStringChar( aStr
[ nLen
- 1 ] );
2058 const sal_Unicode
* p
= aStr
.getStr();
2060 nLen
= aStr
.getLength();
2061 bool bPref
= bPrefixSupport
;
2062 bool bOneChar
= (bPref
&& nLen
> 1 && (aName
== p
+ 1));
2063 if (bOneChar
|| (bPref
&& nLen
> 2 && (aName
== p
+ 2) &&
2064 *p
== 'd' && *(p
+1) == 'a'))
2069 case 'y': n
= -24; break; // yocto
2070 case 'z': n
= -21; break; // zepto
2071 case 'a': n
= -18; break;
2072 case 'f': n
= -15; break;
2073 case 'p': n
= -12; break;
2074 case 'n': n
= -9; break;
2075 case 'u': n
= -6; break;
2076 case 'm': n
= -3; break;
2077 case 'c': n
= -2; break;
2086 case 'e': n
= 1; break;
2087 case 'h': n
= 2; break;
2088 case 'k': n
= 3; break;
2089 case 'M': n
= 6; break;
2090 case 'G': n
= 9; break;
2091 case 'T': n
= 12; break;
2092 case 'P': n
= 15; break;
2093 case 'E': n
= 18; break;
2094 case 'Z': n
= 21; break; // zetta
2095 case 'Y': n
= 24; break; // yotta
2100 // We could weed some nonsense out, ODFF doesn't say so though.
2102 if (n
< 0 && Class() == CDC_Information
)
2103 n
= INV_MATCHLEV
; // milli-bits doesn't make sense
2106 //! <HACK> "cm3" is not 10^-2 m^3 but 10^-6 m^3 !!! ------------------
2107 if( n
!= INV_MATCHLEV
)
2109 sal_Unicode cLast
= p
[ aStr
.getLength() - 1 ];
2112 else if( cLast
== '3' )
2115 //! </HACK> -------------------------------------------------------------------
2119 else if ( nLen
> 2 && ( aName
== p
+ 2 ) && ( Class() == CDC_Information
) )
2121 const sal_Unicode
* pStr
= aStr
.getStr();
2122 if ( *(pStr
+ 1) != 'i')
2123 return INV_MATCHLEV
;
2127 case 'k': n
= 10; break;
2128 case 'M': n
= 20; break;
2129 case 'G': n
= 30; break;
2130 case 'T': n
= 40; break;
2131 case 'P': n
= 50; break;
2132 case 'E': n
= 60; break;
2133 case 'Z': n
= 70; break;
2134 case 'Y': n
= 80; break;
2141 return INV_MATCHLEV
;
2146 double ConvertData::Convert(
2147 double f
, const ConvertData
& r
, sal_Int16 nLevFrom
, sal_Int16 nLevTo
) const
2149 if( Class() != r
.Class() )
2150 throw lang::IllegalArgumentException();
2152 bool bBinFromLev
= ( nLevFrom
> 0 && ( nLevFrom
% 10 ) == 0 );
2153 bool bBinToLev
= ( nLevTo
> 0 && ( nLevTo
% 10 ) == 0 );
2155 if ( Class() == CDC_Information
&& ( bBinFromLev
|| bBinToLev
) )
2157 if ( bBinFromLev
&& bBinToLev
)
2159 nLevFrom
= sal::static_int_cast
<sal_Int16
>( nLevFrom
- nLevTo
);
2160 f
*= r
.fConst
/ fConst
;
2162 f
*= pow( 2.0, nLevFrom
);
2164 else if ( bBinFromLev
)
2165 f
*= ( r
.fConst
/ fConst
) * ( pow( 2.0, nLevFrom
) / pow( 10.0, nLevTo
) );
2167 f
*= ( r
.fConst
/ fConst
) * ( pow( 10.0, nLevFrom
) / pow( 2.0, nLevTo
) );
2171 nLevFrom
= sal::static_int_cast
<sal_Int16
>( nLevFrom
- nLevTo
); // effective level
2173 f
*= r
.fConst
/ fConst
;
2176 f
= ::rtl::math::pow10Exp( f
, nLevFrom
);
2182 double ConvertData::ConvertFromBase( double f
, sal_Int16 n
) const
2184 return ::rtl::math::pow10Exp( f
* fConst
, -n
);
2187 ConvertDataLinear::~ConvertDataLinear()
2191 double ConvertDataLinear::Convert(
2192 double f
, const ConvertData
& r
, sal_Int16 nLevFrom
, sal_Int16 nLevTo
) const
2194 if( Class() != r
.Class() )
2195 throw lang::IllegalArgumentException();
2196 return r
.ConvertFromBase( ConvertToBase( f
, nLevFrom
), nLevTo
);
2200 double ConvertDataLinear::ConvertToBase( double f
, sal_Int16 n
) const
2203 f
= ::rtl::math::pow10Exp( f
, n
);
2212 double ConvertDataLinear::ConvertFromBase( double f
, sal_Int16 n
) const
2218 f
= ::rtl::math::pow10Exp( f
, -n
);
2224 ConvertDataList::ConvertDataList()
2226 #define NEWD(str,unit,cl) maVector.emplace_back(new ConvertData(str,unit,cl))
2227 #define NEWDP(str,unit,cl) maVector.emplace_back(new ConvertData(str,unit,cl,true))
2228 #define NEWL(str,unit,offs,cl) maVector.emplace_back(new ConvertDataLinear(str,unit,offs,cl))
2229 #define NEWLP(str,unit,offs,cl) maVector.emplace_back(new ConvertDataLinear(str,unit,offs,cl,true))
2231 // *** are extra and not standard Excel Analysis Addin!
2233 // MASS: 1 Gram is...
2234 NEWDP( "g", 1.0000000000000000E00
, CDC_Mass
); // Gram
2235 NEWD( "sg", 6.8522050005347800E-05, CDC_Mass
); // Pieces
2236 NEWD( "lbm", 2.2046229146913400E-03, CDC_Mass
); // Pound (commercial weight)
2237 NEWDP( "u", 6.0221370000000000E23
, CDC_Mass
); // U (atomic mass)
2238 NEWD( "ozm", 3.5273971800362700E-02, CDC_Mass
); // Ounce (commercial weight)
2239 NEWD( "stone", 1.574730e-04, CDC_Mass
); // *** Stone
2240 NEWD( "ton", 1.102311e-06, CDC_Mass
); // *** Ton
2241 NEWD( "grain", 1.543236E01
, CDC_Mass
); // *** Grain
2242 NEWD( "pweight", 7.054792E-01, CDC_Mass
); // *** Pennyweight
2243 NEWD( "hweight", 1.968413E-05, CDC_Mass
); // *** Hundredweight
2244 NEWD( "shweight", 2.204623E-05, CDC_Mass
); // *** Shorthundredweight
2245 NEWD( "brton", 9.842065E-07, CDC_Mass
); // *** Gross Registered Ton
2246 NEWD( "cwt", 2.2046226218487758E-05, CDC_Mass
); // U.S. (short) hundredweight
2247 NEWD( "shweight", 2.2046226218487758E-05, CDC_Mass
); // U.S. (short) hundredweight also
2248 NEWD( "uk_cwt", 1.9684130552221213E-05, CDC_Mass
); // Imperial hundredweight
2249 NEWD( "lcwt", 1.9684130552221213E-05, CDC_Mass
); // Imperial hundredweight also
2250 NEWD( "hweight", 1.9684130552221213E-05, CDC_Mass
); // Imperial hundredweight also
2251 NEWD( "uk_ton", 9.8420652761106063E-07, CDC_Mass
); // Imperial ton
2252 NEWD( "LTON", 9.8420652761106063E-07, CDC_Mass
); // Imperial ton also
2254 // LENGTH: 1 Meter is...
2255 NEWDP( "m", 1.0000000000000000E00
, CDC_Length
); // Meter
2256 NEWD( "mi", 6.2137119223733397E-04, CDC_Length
); // Britsh Mile 6,21371192237333969617434184363e-4
2257 NEWD( "Nmi", 5.3995680345572354E-04, CDC_Length
); // Nautical Mile 5,39956803455723542116630669546e-4
2258 NEWD( "in", 3.9370078740157480E01
, CDC_Length
); // Inch 39,37007874015748031496062992126
2259 NEWD( "ft", 3.2808398950131234E00
, CDC_Length
); // Foot 3,2808398950131233595800524934383
2260 NEWD( "yd", 1.0936132983377078E00
, CDC_Length
); // Yard 1,0936132983377077865266841644794
2261 NEWDP( "ang", 1.0000000000000000E10
, CDC_Length
); // Angstrom
2262 NEWD( "Pica", 2.8346456692913386E03
, CDC_Length
); // Pica Point (1/72 Inch) 2834,6456692913385826771653543307
2263 NEWD( "picapt", 2.8346456692913386E03
, CDC_Length
); // Pica Point (1/72 Inch) 2834,6456692913385826771653543307
2264 NEWD( "pica", 2.36220472441E02
, CDC_Length
); // pica (1/6 Inch)
2265 NEWD( "ell", 8.748906E-01, CDC_Length
); // *** Ell
2266 NEWDP( "parsec", 3.240779E-17, CDC_Length
); // *** Parsec
2267 NEWDP( "pc", 3.240779E-17, CDC_Length
); // *** Parsec also
2268 NEWDP( "lightyear", 1.0570234557732930E-16, CDC_Length
); // *** Light Year
2269 NEWDP( "ly", 1.0570234557732930E-16, CDC_Length
); // *** Light Year also
2270 NEWD( "survey_mi", 6.2136994949494949E-04, CDC_Length
); // U.S. survey mile
2272 // TIME: 1 Second is...
2273 NEWD( "yr", 3.1688087814028950E-08, CDC_Time
); // Year
2274 NEWD( "day", 1.1574074074074074E-05, CDC_Time
); // Day
2275 NEWD( "d", 1.1574074074074074E-05, CDC_Time
); // Day also
2276 NEWD( "hr", 2.7777777777777778E-04, CDC_Time
); // Hour
2277 NEWD( "mn", 1.6666666666666667E-02, CDC_Time
); // Minute
2278 NEWD( "min", 1.6666666666666667E-02, CDC_Time
); // Minute also
2279 NEWDP( "sec", 1.0000000000000000E00
, CDC_Time
); // Second
2280 NEWDP( "s", 1.0000000000000000E00
, CDC_Time
); // Second also
2282 // PRESSURE: 1 Pascal is...
2283 NEWDP( "Pa", 1.0000000000000000E00
, CDC_Pressure
); // Pascal
2284 NEWDP( "atm", 9.8692329999819300E-06, CDC_Pressure
); // Atmosphere
2285 NEWDP( "at", 9.8692329999819300E-06, CDC_Pressure
); // Atmosphere also
2286 NEWDP( "mmHg", 7.5006170799862700E-03, CDC_Pressure
); // mm Hg (Mercury)
2287 NEWD( "Torr", 7.5006380000000000E-03, CDC_Pressure
); // *** Torr
2288 NEWD( "psi", 1.4503770000000000E-04, CDC_Pressure
); // *** Psi
2290 // FORCE: 1 Newton is...
2291 NEWDP( "N", 1.0000000000000000E00
, CDC_Force
); // Newton
2292 NEWDP( "dyn", 1.0000000000000000E05
, CDC_Force
); // Dyn
2293 NEWDP( "dy", 1.0000000000000000E05
, CDC_Force
); // Dyn also
2294 NEWD( "lbf", 2.24808923655339E-01, CDC_Force
); // Pound-Force
2295 NEWDP( "pond", 1.019716E02
, CDC_Force
); // *** Pond
2297 // ENERGY: 1 Joule is...
2298 NEWDP( "J", 1.0000000000000000E00
, CDC_Energy
); // Joule
2299 NEWDP( "e", 1.0000000000000000E07
, CDC_Energy
); // Erg -> https://en.wikipedia.org/wiki/Erg
2300 NEWDP( "c", 2.3900624947346700E-01, CDC_Energy
); // Thermodynamical Calorie
2301 NEWDP( "cal", 2.3884619064201700E-01, CDC_Energy
); // Calorie
2302 NEWDP( "eV", 6.2414570000000000E18
, CDC_Energy
); // Electronvolt
2303 NEWDP( "ev", 6.2414570000000000E18
, CDC_Energy
); // Electronvolt also
2304 NEWD( "HPh", 3.7250611111111111E-07, CDC_Energy
); // Horsepower Hours
2305 NEWD( "hh", 3.7250611111111111E-07, CDC_Energy
); // Horsepower Hours also
2306 NEWDP( "Wh", 2.7777777777777778E-04, CDC_Energy
); // Watt Hours
2307 NEWDP( "wh", 2.7777777777777778E-04, CDC_Energy
); // Watt Hours also
2308 NEWD( "flb", 2.37304222192651E01
, CDC_Energy
); // Foot Pound
2309 NEWD( "BTU", 9.4781506734901500E-04, CDC_Energy
); // British Thermal Unit
2310 NEWD( "btu", 9.4781506734901500E-04, CDC_Energy
); // British Thermal Unit also
2312 // POWER: 1 Watt is...
2313 NEWDP( "W", 1.0000000000000000E00
, CDC_Power
); // Watt
2314 NEWDP( "w", 1.0000000000000000E00
, CDC_Power
); // Watt also
2315 NEWD( "HP", 1.341022E-03, CDC_Power
); // Horsepower
2316 NEWD( "h", 1.341022E-03, CDC_Power
); // Horsepower also
2317 NEWD( "PS", 1.359622E-03, CDC_Power
); // *** German Pferdestaerke
2319 // MAGNETISM: 1 Tesla is...
2320 NEWDP( "T", 1.0000000000000000E00
, CDC_Magnetism
); // Tesla
2321 NEWDP( "ga", 1.0000000000000000E04
, CDC_Magnetism
); // Gauss
2323 // TEMPERATURE: 1 Kelvin is...
2324 NEWL( "C", 1.0000000000000000E00
, -2.7315000000000000E02
, CDC_Temperature
); // Celsius
2325 NEWL( "cel", 1.0000000000000000E00
, -2.7315000000000000E02
, CDC_Temperature
); // Celsius also
2326 NEWL( "F", 1.8000000000000000E00
, -2.5537222222222222E02
, CDC_Temperature
); // Fahrenheit
2327 NEWL( "fah", 1.8000000000000000E00
, -2.5537222222222222E02
, CDC_Temperature
); // Fahrenheit also
2328 NEWLP( "K", 1.0000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // Kelvin
2329 NEWLP( "kel", 1.0000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // Kelvin also
2330 NEWL( "Reau", 8.0000000000000000E-01, -2.7315000000000000E02
, CDC_Temperature
); // *** Reaumur
2331 NEWL( "Rank", 1.8000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // *** Rankine
2333 // VOLUME: 1 Liter is...
2334 NEWD( "tsp", 2.0288413621105798E02
, CDC_Volume
); // US teaspoon 1/768 gallon
2335 NEWD( "tbs", 6.7628045403685994E01
, CDC_Volume
); // US tablespoon 1/256 gallon
2336 NEWD( "oz", 3.3814022701842997E01
, CDC_Volume
); // Ounce Liquid 1/128 gallon
2337 NEWD( "cup", 4.2267528377303746E00
, CDC_Volume
); // Cup 1/16 gallon
2338 NEWD( "pt", 2.1133764188651873E00
, CDC_Volume
); // US Pint 1/8 gallon
2339 NEWD( "us_pt", 2.1133764188651873E00
, CDC_Volume
); // US Pint also
2340 NEWD( "uk_pt", 1.7597539863927023E00
, CDC_Volume
); // UK Pint 1/8 imperial gallon
2341 NEWD( "qt", 1.0566882094325937E00
, CDC_Volume
); // Quart 1/4 gallon
2342 NEWD( "gal", 2.6417205235814842E-01, CDC_Volume
); // Gallon 1/3.785411784
2343 NEWDP( "l", 1.0000000000000000E00
, CDC_Volume
); // Liter
2344 NEWDP( "L", 1.0000000000000000E00
, CDC_Volume
); // Liter also
2345 NEWDP( "lt", 1.0000000000000000E00
, CDC_Volume
); // Liter also
2346 NEWDP( "m3", 1.0000000000000000E-03, CDC_Volume
); // *** Cubic Meter
2347 NEWD( "mi3", 2.3991275857892772E-13, CDC_Volume
); // *** Cubic Britsh Mile
2348 NEWD( "Nmi3", 1.5742621468581148E-13, CDC_Volume
); // *** Cubic Nautical Mile
2349 NEWD( "in3", 6.1023744094732284E01
, CDC_Volume
); // *** Cubic Inch
2350 NEWD( "ft3", 3.5314666721488590E-02, CDC_Volume
); // *** Cubic Foot
2351 NEWD( "yd3", 1.3079506193143922E-03, CDC_Volume
); // *** Cubic Yard
2352 NEWDP( "ang3", 1.0000000000000000E27
, CDC_Volume
); // *** Cubic Angstrom
2353 NEWD( "Pica3", 2.2776990435870636E07
, CDC_Volume
); // *** Cubic Pica Point (1/72 inch)
2354 NEWD( "picapt3", 2.2776990435870636E07
, CDC_Volume
); // *** Cubic Pica Point (1/72 inch)
2355 NEWD( "pica3", 1.31811287245E04
, CDC_Volume
); // *** Cubic Pica (1/6 inch)
2356 NEWD( "barrel", 6.2898107704321051E-03, CDC_Volume
); // *** Barrel (=42gal)
2357 NEWD( "bushel", 2.837759E-02, CDC_Volume
); // *** Bushel
2358 NEWD( "regton", 3.531467E-04, CDC_Volume
); // *** Register ton
2359 NEWD( "GRT", 3.531467E-04, CDC_Volume
); // *** Register ton also
2360 NEWD( "Schooner", 2.3529411764705882E00
, CDC_Volume
); // *** austr. Schooner
2361 NEWD( "Middy", 3.5087719298245614E00
, CDC_Volume
); // *** austr. Middy
2362 NEWD( "Glass", 5.0000000000000000E00
, CDC_Volume
); // *** austr. Glass
2363 NEWD( "Sixpack", 0.5, CDC_Volume
); // ***
2364 NEWD( "Humpen", 2.0, CDC_Volume
); // ***
2365 NEWD( "ly3", 1.1810108125623799E-51, CDC_Volume
); // *** Cubic light-year
2366 NEWD( "MTON", 1.4125866688595436E00
, CDC_Volume
); // *** Measurement ton
2367 NEWD( "tspm", 2.0000000000000000E02
, CDC_Volume
); // *** Modern teaspoon
2368 NEWD( "uk_gal", 2.1996924829908779E-01, CDC_Volume
); // U.K. / Imperial gallon 1/4.54609
2369 NEWD( "uk_qt", 8.7987699319635115E-01, CDC_Volume
); // U.K. / Imperial quart 1/4 imperial gallon
2371 // 1 Square Meter is...
2372 NEWDP( "m2", 1.0000000000000000E00
, CDC_Area
); // *** Square Meter
2373 NEWD( "mi2", 3.8610215854244585E-07, CDC_Area
); // *** Square Britsh Mile
2374 NEWD( "Nmi2", 2.9155334959812286E-07, CDC_Area
); // *** Square Nautical Mile
2375 NEWD( "in2", 1.5500031000062000E03
, CDC_Area
); // *** Square Inch
2376 NEWD( "ft2", 1.0763910416709722E01
, CDC_Area
); // *** Square Foot
2377 NEWD( "yd2", 1.1959900463010803E00
, CDC_Area
); // *** Square Yard
2378 NEWDP( "ang2", 1.0000000000000000E20
, CDC_Area
); // *** Square Angstrom
2379 NEWD( "Pica2", 8.0352160704321409E06
, CDC_Area
); // *** Square Pica Point (1/72 inch)
2380 NEWD( "picapt2", 8.0352160704321409E06
, CDC_Area
); // *** Square Pica Point (1/72 inch)
2381 NEWD( "pica2", 5.58001116002232E04
, CDC_Area
); // *** Square Pica (1/6 inch)
2382 NEWD( "Morgen", 4.0000000000000000E-04, CDC_Area
); // *** Morgen
2383 NEWDP( "ar", 1.000000E-02, CDC_Area
); // *** Ar
2384 NEWD( "acre", 2.471053815E-04, CDC_Area
); // *** Acre
2385 NEWD( "uk_acre", 2.4710538146716534E-04, CDC_Area
); // *** International acre
2386 NEWD( "us_acre", 2.4710439304662790E-04, CDC_Area
); // *** U.S. survey/statute acre
2387 NEWD( "ly2", 1.1172985860549147E-32, CDC_Area
); // *** Square Light-year
2388 NEWD( "ha", 1.000000E-04, CDC_Area
); // *** Hectare
2390 // SPEED: 1 Meter per Second is...
2391 NEWDP( "m/s", 1.0000000000000000E00
, CDC_Speed
); // *** Meters per Second
2392 NEWDP( "m/sec", 1.0000000000000000E00
, CDC_Speed
); // *** Meters per Second also
2393 NEWDP( "m/h", 3.6000000000000000E03
, CDC_Speed
); // *** Meters per Hour
2394 NEWDP( "m/hr", 3.6000000000000000E03
, CDC_Speed
); // *** Meters per Hour also
2395 NEWD( "mph", 2.2369362920544023E00
, CDC_Speed
); // *** Britsh Miles per Hour
2396 NEWD( "kn", 1.9438444924406048E00
, CDC_Speed
); // *** Knot = Nautical Miles per Hour
2397 NEWD( "admkn", 1.9438446603753486E00
, CDC_Speed
); // *** Admiralty Knot
2398 NEWD( "ludicrous speed", 2.0494886343432328E-14, CDC_Speed
); // ***
2399 NEWD( "ridiculous speed", 4.0156958471424288E-06, CDC_Speed
); // ***
2401 // INFORMATION: 1 Bit is...
2402 NEWDP( "bit", 1.00E00
, CDC_Information
); // *** Bit
2403 NEWDP( "byte", 1.25E-01, CDC_Information
); // *** Byte
2407 ConvertDataList::~ConvertDataList()
2412 double ConvertDataList::Convert( double fVal
, const OUString
& rFrom
, const OUString
& rTo
)
2414 ConvertData
* pFrom
= nullptr;
2415 ConvertData
* pTo
= nullptr;
2416 bool bSearchFrom
= true;
2417 bool bSearchTo
= true;
2418 sal_Int16 nLevelFrom
= 0;
2419 sal_Int16 nLevelTo
= 0;
2421 for( const auto& rItem
: maVector
)
2423 ConvertData
* p
= rItem
.get();
2426 sal_Int16 n
= p
->GetMatchingLevel( rFrom
);
2427 if( n
!= INV_MATCHLEV
)
2430 { // only first match for partial equality rulz a little bit more
2435 { // ... but exact match rulz most
2437 bSearchFrom
= false;
2445 sal_Int16 n
= p
->GetMatchingLevel( rTo
);
2446 if( n
!= INV_MATCHLEV
)
2449 { // only first match for partial equality rulz a little bit more
2454 { // ... but exact match rulz most
2462 if( !bSearchFrom
&& !bSearchTo
)
2466 if( !pFrom
|| !pTo
)
2467 throw lang::IllegalArgumentException();
2469 return pFrom
->Convert( fVal
, *pTo
, nLevelFrom
, nLevelTo
);
2473 ScaDate::ScaDate() :
2478 bLastDayMode( true ),
2485 ScaDate::ScaDate( sal_Int32 nNullDate
, sal_Int32 nDate
, sal_Int32 nBase
)
2487 DaysToDate( nNullDate
+ nDate
, nOrigDay
, nMonth
, nYear
);
2488 bLastDayMode
= (nBase
!= 5);
2489 bLastDay
= (nOrigDay
>= ::DaysInMonth( nMonth
, nYear
));
2490 b30Days
= (nBase
== 0) || (nBase
== 4);
2491 bUSMode
= (nBase
== 0);
2495 ScaDate::ScaDate( const ScaDate
& rCopy
) :
2496 nOrigDay( rCopy
.nOrigDay
),
2498 nMonth( rCopy
.nMonth
),
2499 nYear( rCopy
.nYear
),
2500 bLastDayMode( rCopy
.bLastDayMode
),
2501 bLastDay( rCopy
.bLastDay
),
2502 b30Days( rCopy
.b30Days
),
2503 bUSMode( rCopy
.bUSMode
)
2507 ScaDate
& ScaDate::operator=( const ScaDate
& rCopy
)
2509 if( this != &rCopy
)
2511 nOrigDay
= rCopy
.nOrigDay
;
2513 nMonth
= rCopy
.nMonth
;
2514 nYear
= rCopy
.nYear
;
2515 bLastDayMode
= rCopy
.bLastDayMode
;
2516 bLastDay
= rCopy
.bLastDay
;
2517 b30Days
= rCopy
.b30Days
;
2518 bUSMode
= rCopy
.bUSMode
;
2523 void ScaDate::setDay()
2527 // 30-days-mode: set nDay to 30 if original was last day in month
2528 nDay
= std::min( nOrigDay
, static_cast< sal_uInt16
>( 30 ) );
2529 if( bLastDay
|| (nDay
>= ::DaysInMonth( nMonth
, nYear
)) )
2534 // set nDay to last day in this month if original was last day
2535 sal_uInt16 nLastDay
= ::DaysInMonth( nMonth
, nYear
);
2536 nDay
= bLastDay
? nLastDay
: std::min( nOrigDay
, nLastDay
);
2540 sal_Int32
ScaDate::getDaysInMonthRange( sal_uInt16 nFrom
, sal_uInt16 nTo
) const
2547 nRet
= (nTo
- nFrom
+ 1) * 30;
2550 for( sal_uInt16 nMonthIx
= nFrom
; nMonthIx
<= nTo
; ++nMonthIx
)
2551 nRet
+= getDaysInMonth( nMonthIx
);
2556 sal_Int32
ScaDate::getDaysInYearRange( sal_uInt16 nFrom
, sal_uInt16 nTo
) const
2561 return b30Days
? ((nTo
- nFrom
+ 1) * 360) : ::GetDaysInYears( nFrom
, nTo
);
2564 void ScaDate::doAddYears( sal_Int32 nYearCount
)
2566 sal_Int32 nNewYear
= nYearCount
+ nYear
;
2567 if( (nNewYear
< 0) || (nNewYear
> 0x7FFF) )
2568 throw lang::IllegalArgumentException();
2569 nYear
= static_cast< sal_uInt16
>( nNewYear
);
2572 void ScaDate::addMonths( sal_Int32 nMonthCount
)
2574 sal_Int32 nNewMonth
= nMonthCount
+ nMonth
;
2575 if( nNewMonth
> 12 )
2578 doAddYears( nNewMonth
/ 12 );
2579 nMonth
= static_cast< sal_uInt16
>( nNewMonth
% 12 ) + 1;
2581 else if( nNewMonth
< 1 )
2583 doAddYears( nNewMonth
/ 12 - 1 );
2584 nMonth
= static_cast< sal_uInt16
>( nNewMonth
% 12 + 12 );
2587 nMonth
= static_cast< sal_uInt16
>( nNewMonth
);
2591 sal_Int32
ScaDate::getDate( sal_Int32 nNullDate
) const
2593 sal_uInt16 nLastDay
= ::DaysInMonth( nMonth
, nYear
);
2594 sal_uInt16 nRealDay
= (bLastDayMode
&& bLastDay
) ? nLastDay
: std::min( nLastDay
, nOrigDay
);
2595 return ::DateToDays( nRealDay
, nMonth
, nYear
) - nNullDate
;
2598 sal_Int32
ScaDate::getDiff( const ScaDate
& rFrom
, const ScaDate
& rTo
)
2601 return getDiff( rTo
, rFrom
);
2603 sal_Int32 nDiff
= 0;
2604 ScaDate
aFrom( rFrom
);
2609 // corrections for base 0 (US NASD)
2612 if( ((rFrom
.nMonth
== 2) || (rFrom
.nDay
< 30)) && (aTo
.nOrigDay
== 31) )
2614 else if( (aTo
.nMonth
== 2) && aTo
.bLastDay
)
2615 aTo
.nDay
= ::DaysInMonth( 2, aTo
.nYear
);
2617 // corrections for base 4 (Europe)
2620 if( (aFrom
.nMonth
== 2) && (aFrom
.nDay
== 30) )
2621 aFrom
.nDay
= ::DaysInMonth( 2, aFrom
.nYear
);
2622 if( (aTo
.nMonth
== 2) && (aTo
.nDay
== 30) )
2623 aTo
.nDay
= ::DaysInMonth( 2, aTo
.nYear
);
2627 if( (aFrom
.nYear
< aTo
.nYear
) || ((aFrom
.nYear
== aTo
.nYear
) && (aFrom
.nMonth
< aTo
.nMonth
)) )
2629 // move aFrom to 1st day of next month
2630 nDiff
= aFrom
.getDaysInMonth() - aFrom
.nDay
+ 1;
2631 aFrom
.nOrigDay
= aFrom
.nDay
= 1;
2632 aFrom
.bLastDay
= false;
2633 aFrom
.addMonths( 1 );
2635 if( aFrom
.nYear
< aTo
.nYear
)
2637 // move aFrom to 1st day of next year
2638 nDiff
+= aFrom
.getDaysInMonthRange( aFrom
.nMonth
, 12 );
2639 aFrom
.addMonths( 13 - aFrom
.nMonth
);
2641 // move aFrom to 1st day of this year
2642 nDiff
+= aFrom
.getDaysInYearRange( aFrom
.nYear
, aTo
.nYear
- 1 );
2643 aFrom
.addYears( aTo
.nYear
- aFrom
.nYear
);
2646 // move aFrom to 1st day of this month
2647 nDiff
+= aFrom
.getDaysInMonthRange( aFrom
.nMonth
, aTo
.nMonth
- 1 );
2648 aFrom
.addMonths( aTo
.nMonth
- aFrom
.nMonth
);
2650 // finally add remaining days in this month
2651 nDiff
+= aTo
.nDay
- aFrom
.nDay
;
2652 return std::max
<sal_Int32
>(nDiff
, 0);
2655 bool ScaDate::operator<( const ScaDate
& rCmp
) const
2657 if( nYear
!= rCmp
.nYear
)
2658 return nYear
< rCmp
.nYear
;
2659 if( nMonth
!= rCmp
.nMonth
)
2660 return nMonth
< rCmp
.nMonth
;
2661 if( nDay
!= rCmp
.nDay
)
2662 return nDay
< rCmp
.nDay
;
2663 if( bLastDay
|| rCmp
.bLastDay
)
2664 return !bLastDay
&& rCmp
.bLastDay
;
2665 return nOrigDay
< rCmp
.nOrigDay
;
2669 ScaAnyConverter::ScaAnyConverter( const uno::Reference
< uno::XComponentContext
>& xContext
)
2671 , bHasValidFormat(false)
2673 xFormatter
= util::NumberFormatter::create(xContext
);
2676 ScaAnyConverter::~ScaAnyConverter()
2680 void ScaAnyConverter::init( const uno::Reference
< beans::XPropertySet
>& xPropSet
)
2682 // try to get default number format
2683 bHasValidFormat
= false;
2684 if( !xFormatter
.is() )
2687 // get XFormatsSupplier from outer XPropertySet
2688 uno::Reference
< util::XNumberFormatsSupplier
> xFormatsSupp( xPropSet
, uno::UNO_QUERY
);
2689 if( !xFormatsSupp
.is() )
2692 // get XNumberFormatTypes from XNumberFormatsSupplier to get standard index
2693 uno::Reference
< util::XNumberFormats
> xFormats( xFormatsSupp
->getNumberFormats() );
2694 uno::Reference
< util::XNumberFormatTypes
> xFormatTypes( xFormats
, uno::UNO_QUERY
);
2695 if( xFormatTypes
.is() )
2697 lang::Locale eLocale
;
2698 nDefaultFormat
= xFormatTypes
->getStandardIndex( eLocale
);
2699 xFormatter
->attachNumberFormatsSupplier( xFormatsSupp
);
2700 bHasValidFormat
= true;
2704 double ScaAnyConverter::convertToDouble( const OUString
& rString
) const
2706 double fValue
= 0.0;
2707 if( bHasValidFormat
)
2711 fValue
= xFormatter
->convertStringToNumber( nDefaultFormat
, rString
);
2713 catch( uno::Exception
& )
2715 throw lang::IllegalArgumentException();
2720 rtl_math_ConversionStatus eStatus
;
2722 fValue
= ::rtl::math::stringToDouble( rString
, '.', ',', &eStatus
, &nEnd
);
2723 if( (eStatus
!= rtl_math_ConversionStatus_Ok
) || (nEnd
< rString
.getLength()) )
2724 throw lang::IllegalArgumentException();
2729 bool ScaAnyConverter::getDouble(
2731 const uno::Any
& rAny
) const
2734 bool bContainsVal
= true;
2735 switch( rAny
.getValueTypeClass() )
2737 case uno::TypeClass_VOID
:
2738 bContainsVal
= false;
2740 case uno::TypeClass_DOUBLE
:
2743 case uno::TypeClass_STRING
:
2745 auto pString
= o3tl::forceAccess
< OUString
>( rAny
);
2746 if( !pString
->isEmpty() )
2747 rfResult
= convertToDouble( *pString
);
2749 bContainsVal
= false;
2753 throw lang::IllegalArgumentException();
2755 return bContainsVal
;
2758 bool ScaAnyConverter::getDouble(
2760 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2761 const uno::Any
& rAny
)
2764 return getDouble( rfResult
, rAny
);
2767 double ScaAnyConverter::getDouble(
2768 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2769 const uno::Any
& rAny
,
2773 if( !getDouble( fResult
, xPropSet
, rAny
) )
2778 bool ScaAnyConverter::getInt32(
2779 sal_Int32
& rnResult
,
2780 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2781 const uno::Any
& rAny
)
2784 bool bContainsVal
= getDouble( fResult
, xPropSet
, rAny
);
2785 if( (fResult
<= -2147483649.0) || (fResult
>= 2147483648.0) )
2786 throw lang::IllegalArgumentException();
2788 rnResult
= static_cast< sal_Int32
>( fResult
);
2789 return bContainsVal
;
2792 sal_Int32
ScaAnyConverter::getInt32(
2793 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2794 const uno::Any
& rAny
,
2795 sal_Int32 nDefault
)
2798 if( !getInt32( nResult
, xPropSet
, rAny
) )
2805 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */