1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 #include <com/sun/star/util/XNumberFormatTypes.hpp>
32 #include <tools/resary.hxx>
33 #include <rtl/math.hxx>
34 #include "analysishelper.hxx"
35 #include "analysis.hrc"
37 using namespace ::rtl
;
38 using namespace ::com::sun::star
;
42 #define UNIQUE sal_False // function name does not exist in Calc
43 #define DOUBLE sal_True // function name exists in Calc
45 #define STDPAR sal_False // all parameters are described
46 #define INTPAR sal_True // first parameter is internal
48 #define FUNCDATA( FUNCNAME, DBL, OPT, NUMOFPAR, CAT ) \
49 { "get" #FUNCNAME, ANALYSIS_FUNCNAME_##FUNCNAME, ANALYSIS_##FUNCNAME, DBL, OPT, ANALYSIS_DEFFUNCNAME_##FUNCNAME, NUMOFPAR, CAT }
51 const FuncDataBase pFuncDatas
[] =
53 // UNIQUE or INTPAR or
54 // function name DOUBLE STDPAR # of param category
55 FUNCDATA( Workday
, UNIQUE
, INTPAR
, 3, FDCat_DateTime
),
56 FUNCDATA( Yearfrac
, UNIQUE
, INTPAR
, 3, FDCat_DateTime
),
57 FUNCDATA( Edate
, UNIQUE
, INTPAR
, 2, FDCat_DateTime
),
58 FUNCDATA( Weeknum
, DOUBLE
, INTPAR
, 2, FDCat_DateTime
),
59 FUNCDATA( Eomonth
, UNIQUE
, INTPAR
, 2, FDCat_DateTime
),
60 FUNCDATA( Networkdays
, UNIQUE
, INTPAR
, 3, FDCat_DateTime
),
61 FUNCDATA( Iseven
, DOUBLE
, STDPAR
, 1, FDCat_Inf
),
62 FUNCDATA( Isodd
, DOUBLE
, STDPAR
, 1, FDCat_Inf
),
63 FUNCDATA( Multinomial
, UNIQUE
, STDPAR
, 1, FDCat_Math
),
64 FUNCDATA( Seriessum
, UNIQUE
, STDPAR
, 4, FDCat_Math
),
65 FUNCDATA( Quotient
, UNIQUE
, STDPAR
, 2, FDCat_Math
),
66 FUNCDATA( Mround
, UNIQUE
, STDPAR
, 2, FDCat_Math
),
67 FUNCDATA( Sqrtpi
, UNIQUE
, STDPAR
, 1, FDCat_Math
),
68 FUNCDATA( Randbetween
, UNIQUE
, STDPAR
, 2, FDCat_Math
),
69 FUNCDATA( Gcd
, DOUBLE
, INTPAR
, 1, FDCat_Math
),
70 FUNCDATA( Lcm
, DOUBLE
, INTPAR
, 1, FDCat_Math
),
71 FUNCDATA( Besseli
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
72 FUNCDATA( Besselj
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
73 FUNCDATA( Besselk
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
74 FUNCDATA( Bessely
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
75 FUNCDATA( Bin2Oct
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
76 FUNCDATA( Bin2Dec
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
77 FUNCDATA( Bin2Hex
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
78 FUNCDATA( Oct2Bin
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
79 FUNCDATA( Oct2Dec
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
80 FUNCDATA( Oct2Hex
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
81 FUNCDATA( Dec2Bin
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
82 FUNCDATA( Dec2Hex
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
83 FUNCDATA( Dec2Oct
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
84 FUNCDATA( Hex2Bin
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
85 FUNCDATA( Hex2Dec
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
86 FUNCDATA( Hex2Oct
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
87 FUNCDATA( Delta
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
88 FUNCDATA( Erf
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
89 FUNCDATA( Erfc
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
90 FUNCDATA( Gestep
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
91 FUNCDATA( Factdouble
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
92 FUNCDATA( Imabs
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
93 FUNCDATA( Imaginary
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
94 FUNCDATA( Impower
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
95 FUNCDATA( Imargument
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
96 FUNCDATA( Imcos
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
97 FUNCDATA( Imdiv
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
98 FUNCDATA( Imexp
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
99 FUNCDATA( Imconjugate
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
100 FUNCDATA( Imln
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
101 FUNCDATA( Imlog10
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
102 FUNCDATA( Imlog2
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
103 FUNCDATA( Improduct
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
104 FUNCDATA( Imreal
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
105 FUNCDATA( Imsin
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
106 FUNCDATA( Imsub
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
107 FUNCDATA( Imsqrt
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
108 FUNCDATA( Imsum
, UNIQUE
, INTPAR
, 1, FDCat_Tech
),
109 FUNCDATA( Complex
, UNIQUE
, STDPAR
, 3, FDCat_Tech
),
110 FUNCDATA( Convert
, DOUBLE
, STDPAR
, 3, FDCat_Tech
),
111 FUNCDATA( Amordegrc
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
112 FUNCDATA( Amorlinc
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
113 FUNCDATA( Accrint
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
114 FUNCDATA( Accrintm
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
115 FUNCDATA( Received
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
116 FUNCDATA( Disc
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
117 FUNCDATA( Duration
, DOUBLE
, INTPAR
, 6, FDCat_Finance
),
118 FUNCDATA( Effect
, DOUBLE
, STDPAR
, 2, FDCat_Finance
),
119 FUNCDATA( Cumprinc
, DOUBLE
, STDPAR
, 6, FDCat_Finance
),
120 FUNCDATA( Cumipmt
, DOUBLE
, STDPAR
, 6, FDCat_Finance
),
121 FUNCDATA( Price
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
122 FUNCDATA( Pricedisc
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
123 FUNCDATA( Pricemat
, UNIQUE
, INTPAR
, 6, FDCat_Finance
),
124 FUNCDATA( Mduration
, UNIQUE
, INTPAR
, 6, FDCat_Finance
),
125 FUNCDATA( Nominal
, DOUBLE
, STDPAR
, 2, FDCat_Finance
),
126 FUNCDATA( Dollarfr
, UNIQUE
, STDPAR
, 2, FDCat_Finance
),
127 FUNCDATA( Dollarde
, UNIQUE
, STDPAR
, 2, FDCat_Finance
),
128 FUNCDATA( Yield
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
129 FUNCDATA( Yielddisc
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
130 FUNCDATA( Yieldmat
, UNIQUE
, INTPAR
, 6, FDCat_Finance
),
131 FUNCDATA( Tbilleq
, UNIQUE
, INTPAR
, 3, FDCat_Finance
),
132 FUNCDATA( Tbillprice
, UNIQUE
, INTPAR
, 3, FDCat_Finance
),
133 FUNCDATA( Tbillyield
, UNIQUE
, INTPAR
, 3, FDCat_Finance
),
134 FUNCDATA( Oddfprice
, UNIQUE
, INTPAR
, 9, FDCat_Finance
),
135 FUNCDATA( Oddfyield
, UNIQUE
, INTPAR
, 9, FDCat_Finance
),
136 FUNCDATA( Oddlprice
, UNIQUE
, INTPAR
, 8, FDCat_Finance
),
137 FUNCDATA( Oddlyield
, UNIQUE
, INTPAR
, 8, FDCat_Finance
),
138 FUNCDATA( Xirr
, UNIQUE
, INTPAR
, 3, FDCat_Finance
),
139 FUNCDATA( Xnpv
, UNIQUE
, STDPAR
, 3, FDCat_Finance
),
140 FUNCDATA( Intrate
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
141 FUNCDATA( Coupncd
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
142 FUNCDATA( Coupdays
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
143 FUNCDATA( Coupdaysnc
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
144 FUNCDATA( Coupdaybs
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
145 FUNCDATA( Couppcd
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
146 FUNCDATA( Coupnum
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
147 FUNCDATA( Fvschedule
, UNIQUE
, STDPAR
, 2, FDCat_Finance
)
152 sal_uInt16
DaysInMonth( sal_uInt16 nMonth
, sal_uInt16 nYear
)
154 if( (nMonth
== 2) && IsLeapYear( nYear
) )
156 static const sal_uInt16 aDaysInMonth
[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
157 return aDaysInMonth
[ nMonth
];
162 * Convert a date to a count of days starting from 01/01/0001
164 * The internal representation of a Date used in this Addin
165 * is the number of days between 01/01/0001 and the date
166 * this function converts a Day , Month, Year representation
167 * to this internal Date value.
171 sal_Int32
DateToDays( sal_uInt16 nDay
, sal_uInt16 nMonth
, sal_uInt16 nYear
)
173 sal_Int32 nDays
= ((sal_Int32
)nYear
-1) * 365;
174 nDays
+= ((nYear
-1) / 4) - ((nYear
-1) / 100) + ((nYear
-1) / 400);
176 for( sal_uInt16 i
= 1; i
< nMonth
; i
++ )
177 nDays
+= DaysInMonth(i
,nYear
);
185 * Convert a count of days starting from 01/01/0001 to a date
187 * The internal representation of a Date used in this Addin
188 * is the number of days between 01/01/0001 and the date
189 * this function converts this internal Date value
190 * to a Day , Month, Year representation of a Date.
194 void DaysToDate( sal_Int32 nDays
, sal_uInt16
& rDay
, sal_uInt16
& rMonth
, sal_uInt16
& rYear
)
195 throw( lang::IllegalArgumentException
)
198 throw lang::IllegalArgumentException();
207 rYear
= (sal_uInt16
)((nTempDays
/ 365) - i
);
208 nTempDays
-= ((sal_Int32
) rYear
-1) * 365;
209 nTempDays
-= (( rYear
-1) / 4) - (( rYear
-1) / 100) + ((rYear
-1) / 400);
218 if ( nTempDays
> 365 )
220 if ( (nTempDays
!= 366) || !IsLeapYear( rYear
) )
231 while ( (sal_Int32
)nTempDays
> DaysInMonth( rMonth
, rYear
) )
233 nTempDays
-= DaysInMonth( rMonth
, rYear
);
236 rDay
= (sal_uInt16
)nTempDays
;
241 * Get the null date used by the spreadsheet document
243 * The internal representation of a Date used in this Addin
244 * is the number of days between 01/01/0001 and the date
245 * this function returns this internal Date value for the document null date
249 sal_Int32
GetNullDate( constREFXPS
& xOpt
) THROWDEF_RTE
255 ANY aAny
= xOpt
->getPropertyValue( STRFROMASCII( "NullDate" ) );
258 return DateToDays( aDate
.Day
, aDate
.Month
, aDate
.Year
);
260 catch( uno::Exception
& )
265 // no null date available -> no calculations possible
266 throw uno::RuntimeException();
270 sal_Int32
GetDiffDate360(
271 sal_uInt16 nDay1
, sal_uInt16 nMonth1
, sal_uInt16 nYear1
, sal_Bool bLeapYear1
,
272 sal_uInt16 nDay2
, sal_uInt16 nMonth2
, sal_uInt16 nYear2
,
273 sal_Bool bUSAMethod
)
277 else if( bUSAMethod
&& ( nMonth1
== 2 && ( nDay1
== 29 || ( nDay1
== 28 && !bLeapYear1
) ) ) )
282 if( bUSAMethod
&& nDay1
!= 30 )
284 //aDate2 += 1; -> 1.xx.yyyy
298 return nDay2
+ nMonth2
* 30 + nYear2
* 360 - nDay1
- nMonth1
* 30 - nYear1
* 360;
302 sal_Int32
GetDiffDate360( sal_Int32 nNullDate
, sal_Int32 nDate1
, sal_Int32 nDate2
, sal_Bool bUSAMethod
)
307 sal_uInt16 nDay1
, nMonth1
, nYear1
, nDay2
, nMonth2
, nYear2
;
309 DaysToDate( nDate1
, nDay1
, nMonth1
, nYear1
);
310 DaysToDate( nDate2
, nDay2
, nMonth2
, nYear2
);
312 return GetDiffDate360( nDay1
, nMonth1
, nYear1
, IsLeapYear( nYear1
), nDay2
, nMonth2
, nYear2
, bUSAMethod
);
316 sal_Int32
GetDaysInYears( sal_uInt16 nYear1
, sal_uInt16 nYear2
)
318 sal_uInt16 nLeaps
= 0;
319 for( sal_uInt16 n
= nYear1
; n
<= nYear2
; n
++ )
321 if( IsLeapYear( n
) )
335 void GetDiffParam( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
,
336 sal_uInt16
& rYears
, sal_Int32
& rDayDiffPart
, sal_Int32
& rDaysInYear
) THROWDEF_RTE_IAE
338 if( nStartDate
> nEndDate
)
340 sal_Int32 n
= nEndDate
;
341 nEndDate
= nStartDate
;
345 sal_Int32 nDate1
= nStartDate
+ nNullDate
;
346 sal_Int32 nDate2
= nEndDate
+ nNullDate
;
348 sal_uInt16 nDay1
, nDay2
;
349 sal_uInt16 nMonth1
, nMonth2
;
350 sal_uInt16 nYear1
, nYear2
;
352 DaysToDate( nDate1
, nDay1
, nMonth1
, nYear1
);
353 DaysToDate( nDate2
, nDay2
, nMonth2
, nYear2
);
357 sal_Int32 nDayDiff
, nDaysInYear
;
361 case 0: // 0=USA (NASD) 30/360
362 case 4: // 4=Europe 30/360
364 nYears
= nYear2
- nYear1
;
365 nDayDiff
= GetDiffDate360( nDay1
, nMonth1
, nYear1
, IsLeapYear( nYear1
),
366 nDay2
, nMonth2
, nYear2
, nMode
== 0 ) - nYears
* nDaysInYear
;
368 case 1: // 1=exact/exact
369 nYears
= nYear2
- nYear1
;
371 nDaysInYear
= IsLeapYear( nYear1
)? 366 : 365;
373 if( nYears
&& ( nMonth1
> nMonth2
|| ( nMonth1
== nMonth2
&& nDay1
> nDay2
) ) )
377 nDayDiff
= nDate2
- DateToDays( nDay1
, nMonth1
, nYear2
);
379 nDayDiff
= nDate2
- nDate1
;
382 nDayDiff
+= nDaysInYear
;
385 case 2: // 2=exact/360
387 nYears
= sal_uInt16( ( nDate2
- nDate1
) / nDaysInYear
);
388 nDayDiff
= nDate2
- nDate1
;
389 nDayDiff
%= nDaysInYear
;
391 case 3: //3=exact/365
393 nYears
= sal_uInt16( ( nDate2
- nDate1
) / nDaysInYear
);
394 nDayDiff
= nDate2
- nDate1
;
395 nDayDiff
%= nDaysInYear
;
402 rDayDiffPart
= nDayDiff
;
403 rDaysInYear
= nDaysInYear
;
407 sal_Int32
GetDiffDate( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
,
408 sal_Int32
* pOptDaysIn1stYear
) THROWDEF_RTE_IAE
410 sal_Bool bNeg
= nStartDate
> nEndDate
;
414 sal_Int32 n
= nEndDate
;
415 nEndDate
= nStartDate
;
423 case 0: // 0=USA (NASD) 30/360
424 case 4: // 4=Europe 30/360
426 sal_uInt16 nD1
, nM1
, nY1
, nD2
, nM2
, nY2
;
428 nStartDate
+= nNullDate
;
429 nEndDate
+= nNullDate
;
431 DaysToDate( nStartDate
, nD1
, nM1
, nY1
);
432 DaysToDate( nEndDate
, nD2
, nM2
, nY2
);
434 sal_Bool bLeap
= IsLeapYear( nY1
);
435 sal_Int32 nDays
, nMonths
/*, nYears*/;
440 nMonths
+= ( nY2
- nY1
) * 12;
442 nRet
= nMonths
* 30 + nDays
;
443 if( nMode
== 0 && nM1
== 2 && nM2
!= 2 && nY1
== nY2
)
444 nRet
-= bLeap
? 1 : 2;
446 if( pOptDaysIn1stYear
)
447 *pOptDaysIn1stYear
= 360;
450 case 1: // 1=exact/exact
451 if( pOptDaysIn1stYear
)
453 sal_uInt16 nD
, nM
, nY
;
455 DaysToDate( nStartDate
+ nNullDate
, nD
, nM
, nY
);
457 *pOptDaysIn1stYear
= IsLeapYear( nY
)? 366 : 365;
459 nRet
= nEndDate
- nStartDate
;
461 case 2: // 2=exact/360
462 nRet
= nEndDate
- nStartDate
;
463 if( pOptDaysIn1stYear
)
464 *pOptDaysIn1stYear
= 360;
466 case 3: //3=exact/365
467 nRet
= nEndDate
- nStartDate
;
468 if( pOptDaysIn1stYear
)
469 *pOptDaysIn1stYear
= 365;
475 return bNeg
? -nRet
: nRet
;
479 double GetYearDiff( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
) THROWDEF_RTE_IAE
481 sal_Int32 nDays1stYear
;
482 sal_Int32 nTotalDays
= GetDiffDate( nNullDate
, nStartDate
, nEndDate
, nMode
, &nDays1stYear
);
484 return double( nTotalDays
) / double( nDays1stYear
);
488 sal_Int32
GetDaysInYear( sal_Int32 nNullDate
, sal_Int32 nDate
, sal_Int32 nMode
) THROWDEF_RTE_IAE
492 case 0: // 0=USA (NASD) 30/360
493 case 2: // 2=exact/360
494 case 4: // 4=Europe 30/360
496 case 1: // 1=exact/exact
498 sal_uInt16 nD
, nM
, nY
;
500 DaysToDate( nDate
, nD
, nM
, nY
);
501 return IsLeapYear( nY
)? 366 : 365;
503 case 3: //3=exact/365
511 double GetYearFrac( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
) THROWDEF_RTE_IAE
513 if( nStartDate
== nEndDate
)
514 return 0.0; // nothing to do...
517 sal_Int32 nDayDiff
, nDaysInYear
;
519 GetDiffParam( nNullDate
, nStartDate
, nEndDate
, nMode
, nYears
, nDayDiff
, nDaysInYear
);
521 return double( nYears
) + double( nDayDiff
) / double( nDaysInYear
);
525 double Fak( sal_Int32 n
)
547 double GetGcd( double f1
, double f2
)
549 double f
= fmod( f1
, f2
);
561 double ConvertToDec( const STRING
& aStr
, sal_uInt16 nBase
, sal_uInt16 nCharLim
) THROWDEF_RTE_IAE
563 if ( nBase
< 2 || nBase
> 36 )
566 sal_uInt32 nStrLen
= aStr
.getLength();
567 if( nStrLen
> nCharLim
)
574 register const sal_Unicode
* p
= aStr
.getStr();
576 sal_uInt16 nFirstDig
= 0;
577 sal_Bool bFirstDig
= sal_True
;
578 double fBase
= nBase
;
584 if( '0' <= *p
&& *p
<= '9' )
586 else if( 'A' <= *p
&& *p
<= 'Z' )
587 n
= 10 + ( *p
- 'A' );
588 else if ( 'a' <= *p
&& *p
<= 'z' )
589 n
= 10 + ( *p
- 'a' );
597 bFirstDig
= sal_False
;
600 fVal
= fVal
* fBase
+ double( n
);
610 if( nStrLen
== nCharLim
&& !bFirstDig
&& (nFirstDig
>= nBase
/ 2) )
611 { // handling negativ values
612 fVal
= ( pow( double( nBase
), double( nCharLim
) ) - fVal
); // complement
620 static inline sal_Char
GetMaxChar( sal_uInt16 nBase
)
622 const sal_Char
* c
= "--123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
627 STRING
ConvertFromDec( double fNum
, double fMin
, double fMax
, sal_uInt16 nBase
,
628 sal_Int32 nPlaces
, sal_Int32 nMaxPlaces
, sal_Bool bUsePlaces
) THROWDEF_RTE_IAE
630 fNum
= ::rtl::math::approxFloor( fNum
);
631 fMin
= ::rtl::math::approxFloor( fMin
);
632 fMax
= ::rtl::math::approxFloor( fMax
);
634 if( fNum
< fMin
|| fNum
> fMax
|| ( bUsePlaces
&& ( nPlaces
<= 0 || nPlaces
> nMaxPlaces
) ) )
637 sal_Int64 nNum
= static_cast< sal_Int64
>( fNum
);
638 sal_Bool bNeg
= nNum
< 0;
640 nNum
= sal_Int64( pow( double( nBase
), double( nMaxPlaces
) ) ) + nNum
;
642 STRING
aRet( STRING::valueOf( nNum
, nBase
).toAsciiUpperCase() );
647 sal_Int32 nLen
= aRet
.getLength();
648 if( !bNeg
&& nLen
> nPlaces
)
652 else if( ( bNeg
&& nLen
< nMaxPlaces
) || ( !bNeg
&& nLen
< nPlaces
) )
654 sal_Int32 nLeft
= nPlaces
- nLen
;
655 sal_Char
* p
= new sal_Char
[ nLeft
+ 1 ];
656 memset( p
, bNeg
? GetMaxChar( nBase
) : '0', nLeft
);
658 STRING
aTmp( p
, nLeft
, RTL_TEXTENCODING_MS_1252
);
669 // implementation moved to module sal, see #i97091#
670 double Erf( double x
)
672 return ::rtl::math::erf(x
);
675 // implementation moved to module sal, see #i97091#
676 double Erfc( double x
)
678 return ::rtl::math::erfc(x
);
681 inline sal_Bool
IsNum( sal_Unicode c
)
683 return c
>= '0' && c
<= '9';
687 inline sal_Bool
IsComma( sal_Unicode c
)
689 return c
== '.' || c
== ',';
693 inline sal_Bool
IsExpStart( sal_Unicode c
)
695 return c
== 'e' || c
== 'E';
699 inline sal_Bool
IsImagUnit( sal_Unicode c
)
701 return c
== 'i' || c
== 'j';
705 inline sal_uInt16
GetVal( sal_Unicode c
)
707 return sal_uInt16( c
- '0' );
711 sal_Bool
ParseDouble( const sal_Unicode
*& rp
, double& rRet
)
715 double fMult
= 0.1; // multiplier to multiply digits with, when adding fractional ones
717 sal_Int32 nMaxExp
= 307;
718 sal_uInt16 nDigCnt
= 18; // max. number of digits to read in, rest doesn't matter
720 enum State
{ S_End
= 0, S_Sign
, S_IntStart
, S_Int
, S_IgnoreIntDigs
, S_Frac
, S_IgnoreFracDigs
, S_ExpSign
, S_Exp
};
724 sal_Bool bNegNum
= sal_False
;
725 sal_Bool bNegExp
= sal_False
;
727 const sal_Unicode
* p
= rp
;
749 else if( IsComma( c
) )
761 else if( IsComma( c
) )
763 else if( IsImagUnit( c
) )
775 fInt
+= double( GetVal( c
) );
778 eS
= S_IgnoreIntDigs
;
780 else if( IsComma( c
) )
782 else if( IsExpStart( c
) )
787 case S_IgnoreIntDigs
:
789 nExp
++; // just multiply num with 10... ;-)
790 else if( IsComma( c
) )
792 else if( IsExpStart( c
) )
800 fFrac
+= double( GetVal( c
) ) * fMult
;
805 eS
= S_IgnoreFracDigs
;
807 else if( IsExpStart( c
) )
812 case S_IgnoreFracDigs
:
813 if( IsExpStart( c
) )
815 else if( !IsNum( c
) )
843 case S_End
: // to avoid compiler warning
844 break; // loop exits anyway
850 p
--; // set pointer back to last
854 sal_Int32 nLog10
= sal_Int32( log10( fInt
) );
859 if( nLog10
+ nExp
> nMaxExp
)
862 fInt
= ::rtl::math::pow10Exp( fInt
, nExp
);
873 STRING
GetString( double f
, sal_Bool bLeadingSign
, sal_uInt16 nMaxDig
)
875 const int nBuff
= 256;
876 sal_Char aBuff
[ nBuff
+ 1 ];
877 const char* pFormStr
= bLeadingSign
? "%+.*g" : "%.*g";
878 int nLen
= snprintf( aBuff
, nBuff
, pFormStr
, int( nMaxDig
), f
);
879 // you never know which underlying implementation you get ...
881 if ( nLen
< 0 || nLen
> nBuff
)
882 nLen
= strlen( aBuff
);
884 STRING
aRet( aBuff
, nLen
, RTL_TEXTENCODING_MS_1252
);
890 double GetAmordegrc( sal_Int32 nNullDate
, double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
,
891 double fRestVal
, double fPer
, double fRate
, sal_Int32 nBase
) THROWDEF_RTE_IAE
896 sal_uInt32 nPer
= sal_uInt32( fPer
);
897 double fUsePer
= 1.0 / fRate
;
902 else if( fUsePer
< 5.0 )
904 else if( fUsePer
<= 6.0 )
910 double fNRate
= ::rtl::math::round( GetYearFrac( nNullDate
, nDate
, nFirstPer
, nBase
) * fRate
* fCost
, 0 );
912 double fRest
= fCost
- fRestVal
; // Anschaffungskosten - Restwert - Summe aller Abschreibungen
914 for( sal_uInt32 n
= 0 ; n
< nPer
; n
++ )
916 fNRate
= ::rtl::math::round( fRate
* fCost
, 0 );
925 return ::rtl::math::round( fCost
* 0.5, 0 );
938 double GetAmorlinc( sal_Int32 nNullDate
, double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
,
939 double fRestVal
, double fPer
, double fRate
, sal_Int32 nBase
) THROWDEF_RTE_IAE
944 sal_uInt32 nPer
= sal_uInt32( fPer
);
945 double fOneRate
= fCost
* fRate
;
946 double fCostDelta
= fCost
- fRestVal
;
947 double f0Rate
= GetYearFrac( nNullDate
, nDate
, nFirstPer
, nBase
) * fRate
* fCost
;
948 sal_uInt32 nNumOfFullPeriods
= sal_uInt32( ( fCost
- fRestVal
- f0Rate
) / fOneRate
);
952 else if( nPer
<= nNumOfFullPeriods
)
954 else if( nPer
== nNumOfFullPeriods
+ 1 )
955 return fCostDelta
- fOneRate
* nNumOfFullPeriods
- f0Rate
;
961 double GetDuration( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
,
962 double fYield
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
964 double fYearfrac
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
);
965 double fNumOfCoups
= GetCoupnum( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
967 const double f100
= 100.0;
968 fCoup
*= f100
/ double( nFreq
); // fCoup is used as cash flow
972 double nDiff
= fYearfrac
* nFreq
- fNumOfCoups
;
976 for( t
= 1.0 ; t
< fNumOfCoups
; t
++ )
977 fDur
+= ( t
+ nDiff
) * ( fCoup
) / pow( fYield
, t
+ nDiff
);
979 fDur
+= ( fNumOfCoups
+ nDiff
) * ( fCoup
+ f100
) / pow( fYield
, fNumOfCoups
+ nDiff
);
982 for( t
= 1.0 ; t
< fNumOfCoups
; t
++ )
983 p
+= fCoup
/ pow( fYield
, t
+ nDiff
);
985 p
+= ( fCoup
+ f100
) / pow( fYield
, fNumOfCoups
+ nDiff
);
988 fDur
/= double( nFreq
);
994 double GetYieldmat( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nIssue
,
995 double fRate
, double fPrice
, sal_Int32 nBase
) THROWDEF_RTE_IAE
997 double fIssMat
= GetYearFrac( nNullDate
, nIssue
, nMat
, nBase
);
998 double fIssSet
= GetYearFrac( nNullDate
, nIssue
, nSettle
, nBase
);
999 double fSetMat
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
);
1001 double y
= 1.0 + fIssMat
* fRate
;
1002 y
/= fPrice
/ 100.0 + fIssSet
* fRate
;
1010 double GetOddfprice( sal_Int32
/*nNullDate*/, sal_Int32
/*nSettle*/, sal_Int32
/*nMat*/, sal_Int32
/*nIssue*/,
1011 sal_Int32
/*nFirstCoup*/, double /*fRate*/, double /*fYield*/, double /*fRedemp*/, sal_Int32
/*nFreq*/,
1012 sal_Int32
/*nBase*/ ) THROWDEF_RTE_IAE
1014 THROW_RTE
; // #87380#
1016 double fN = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase ) - 1.0;
1017 double fNq = GetCoupnum( nNullDate, nSettle, nFirstCoup, nFreq, nBase ) - 1.0;
1018 double fDSC = GetCoupdaysnc( nNullDate, nSettle, nFirstCoup, nFreq, nBase );
1019 double fDSC_E = fDSC / GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase );
1020 double fNC = GetCoupnum( nNullDate, nIssue, nFirstCoup, nFreq, nBase );
1021 sal_uInt32 nNC = sal_uInt32( fNC );
1022 sal_uInt16 nMonthDelta = 12 / sal_uInt16( nFreq );
1025 double f1YieldFreq = 1.0 + fYield / double( nFreq );
1026 double f100RateFreq = 100.0 * fRate / double( nFreq );
1028 double* pDC = new double[ nNC + 1 ];
1029 double* pNL = new double[ nNC + 1 ];
1030 double* pA = new double[ nNC + 1 ];
1032 pDC[ 0 ] = pNL[ 0 ] = pA[ 0 ] = 1.0;
1034 ScaDate aStartDate( nNullDate, nSettle, nBase );
1035 ScaDate aNextCoup( nNullDate, nFirstCoup, nBase );
1038 pDC[ 1 ] = ScaDate::GetDiff( aStartDate, aNextCoup );
1039 pNL[ 1 ] = GetCoupdays( nNullDate, nSettle, nFirstCoup, nFreq, nBase );
1042 for( i = 1 ; i <= nNC ; i++ )
1045 aStartDate.addMonths( nMonthDelta );
1046 aNextCoup.addMonths( nMonthDelta );
1047 pDC[ i ] = ScaDate::GetDiff( aPre, aStartDate );
1048 pNL[ i ] = GetCoupdays( nNullDate, aStartDate.GetDate( nNullDate ), aNextCoup.GetDate( nNullDate ),
1050 pA[ i ] = ScaDate::GetDiff( aStartDate, aNextCoup );
1054 double fT1 = fRedemp / pow( f1YieldFreq, fN + fNq + fDSC_E );
1057 for( i = 1 ; i <= nNC ; i++ )
1058 fT2 += pDC[ i ] / pNL[ i ];
1059 fT2 *= f100RateFreq / pow( f1YieldFreq, fNq + fDSC_E );
1062 for( double k = 2.0 ; k <= fN ; k++ )
1063 fT3 += 1.0 / pow( f1YieldFreq, k - fNq + fDSC_E );
1064 fT3 *= f100RateFreq;
1067 for( i = 1 ; i <= nNC ; i++ )
1068 fT4 += pA[ i ] / pNL[ i ];
1069 fT4 *= f100RateFreq;
1078 return fT1 + fT2 + fT3 - fT4;
1083 double getYield_( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
, double fPrice
,
1084 double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1086 double fRate
= fCoup
;
1087 double fPriceN
= 0.0;
1088 double fYield1
= 0.0;
1089 double fYield2
= 1.0;
1090 double fPrice1
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield1
, fRedemp
, nFreq
, nBase
);
1091 double fPrice2
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield2
, fRedemp
, nFreq
, nBase
);
1092 double fYieldN
= ( fYield2
- fYield1
) * 0.5;
1094 for( sal_uInt32 nIter
= 0 ; nIter
< 100 && fPriceN
!= fPrice
; nIter
++ )
1096 fPriceN
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYieldN
, fRedemp
, nFreq
, nBase
);
1098 if( fPrice
== fPrice1
)
1100 else if( fPrice
== fPrice2
)
1102 else if( fPrice
== fPriceN
)
1104 else if( fPrice
< fPrice2
)
1107 fPrice2
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield2
, fRedemp
, nFreq
, nBase
);
1109 fYieldN
= ( fYield2
- fYield1
) * 0.5;
1113 if( fPrice
< fPriceN
)
1124 fYieldN
= fYield2
- ( fYield2
- fYield1
) * ( ( fPrice
- fPrice2
) / ( fPrice1
- fPrice2
) );
1128 if( fabs( fPrice
- fPriceN
) > fPrice
/ 100.0 )
1129 THROW_IAE
; // result not precise enough
1135 double getPrice_( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fRate
, double fYield
,
1136 double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1138 double fFreq
= nFreq
;
1140 double fE
= GetCoupdays( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1141 double fDSC_E
= GetCoupdaysnc( nNullDate
, nSettle
, nMat
, nFreq
, nBase
) / fE
;
1142 double fN
= GetCoupnum( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1143 double fA
= GetCoupdaybs( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1145 double fRet
= fRedemp
/ ( pow( 1.0 + fYield
/ fFreq
, fN
- 1.0 + fDSC_E
) );
1146 fRet
-= 100.0 * fRate
/ fFreq
* fA
/ fE
;
1148 double fT1
= 100.0 * fRate
/ fFreq
;
1149 double fT2
= 1.0 + fYield
/ fFreq
;
1151 for( double fK
= 0.0 ; fK
< fN
; fK
++ )
1152 fRet
+= fT1
/ pow( fT2
, fK
+ fDSC_E
);
1158 double GetOddfyield( sal_Int32
/*nNullDate*/, sal_Int32
/*nSettle*/, sal_Int32
/*nMat*/, sal_Int32
/*nIssue*/,
1159 sal_Int32
/*nFirstCoup*/, double /*fRate*/, double /*fPrice*/, double /*fRedemp*/, sal_Int32
/*nFreq*/,
1160 sal_Int32
/*nBase*/ ) THROWDEF_RTE_IAE
1162 THROW_RTE
; // #87380#
1164 //GetOddfprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue,
1165 //sal_Int32 nFirstCoup, double fRate, double fYield, double fRedemp, sal_Int32 nFreq,
1167 double fPriceN = 0.0;
1168 double fYield1 = 0.0;
1169 double fYield2 = 1.0;
1170 double fPrice1 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield1, fRedemp, nFreq, nBase );
1171 double fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase );
1172 double fYieldN = ( fYield2 - fYield1 ) * 0.5;
1174 for( sal_uInt32 nIter = 0 ; nIter < 100 && fPriceN != fPrice ; nIter++ )
1176 fPriceN = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYieldN, fRedemp, nFreq, nBase );
1178 if( fPrice == fPrice1 )
1180 else if( fPrice == fPrice2 )
1182 else if( fPrice == fPriceN )
1184 else if( fPrice < fPrice2 )
1187 fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase );
1189 fYieldN = ( fYield2 - fYield1 ) * 0.5;
1193 if( fPrice < fPriceN )
1204 fYieldN = fYield2 - ( fYield2 - fYield1 ) * ( ( fPrice - fPrice2 ) / ( fPrice1 - fPrice2 ) );
1208 if( fabs( fPrice - fPriceN ) > fPrice / 100.0 )
1209 THROW_IAE; // result not precise enough
1216 double GetOddlprice( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastCoup
,
1217 double fRate
, double fYield
, double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1219 double fFreq
= double( nFreq
);
1220 double fDCi
= GetYearFrac( nNullDate
, nLastCoup
, nMat
, nBase
) * fFreq
;
1221 double fDSCi
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
) * fFreq
;
1222 double fAi
= GetYearFrac( nNullDate
, nLastCoup
, nSettle
, nBase
) * fFreq
;
1224 double p
= fRedemp
+ fDCi
* 100.0 * fRate
/ fFreq
;
1225 p
/= fDSCi
* fYield
/ fFreq
+ 1.0;
1226 p
-= fAi
* 100.0 * fRate
/ fFreq
;
1232 double GetOddlyield( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastCoup
,
1233 double fRate
, double fPrice
, double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1235 double fFreq
= double( nFreq
);
1236 double fDCi
= GetYearFrac( nNullDate
, nLastCoup
, nMat
, nBase
) * fFreq
;
1237 double fDSCi
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
) * fFreq
;
1238 double fAi
= GetYearFrac( nNullDate
, nLastCoup
, nSettle
, nBase
) * fFreq
;
1240 double y
= fRedemp
+ fDCi
* 100.0 * fRate
/ fFreq
;
1241 y
/= fPrice
+ fAi
* 100.0 * fRate
/ fFreq
;
1249 double GetRmz( double fZins
, double fZzr
, double fBw
, double fZw
, sal_Int32 nF
)
1253 fRmz
= ( fBw
+ fZw
) / fZzr
;
1256 double fTerm
= pow( 1.0 + fZins
, fZzr
);
1258 fRmz
= ( fZw
* fZins
/ ( fTerm
- 1.0 ) + fBw
* fZins
/ ( 1.0 - 1.0 / fTerm
) ) / ( 1.0 + fZins
);
1260 fRmz
= fZw
* fZins
/ ( fTerm
- 1.0 ) + fBw
* fZins
/ ( 1.0 - 1.0 / fTerm
);
1267 double GetZw( double fZins
, double fZzr
, double fRmz
, double fBw
, sal_Int32 nF
)
1271 fZw
= fBw
+ fRmz
* fZzr
;
1274 double fTerm
= pow( 1.0 + fZins
, fZzr
);
1276 fZw
= fBw
* fTerm
+ fRmz
* ( 1.0 + fZins
) * ( fTerm
- 1.0 ) / fZins
;
1278 fZw
= fBw
* fTerm
+ fRmz
* ( fTerm
- 1.0 ) / fZins
;
1285 /*double TBillYield( constREFXPS& xOpt, sal_Int32 nSettle, sal_Int32 nMat, double fPrice ) THROWDEF_RTE_IAE
1287 sal_Int32 nDiff = GetDiffDate360( xOpt, nSettle, nMat, sal_True );
1289 if( fPrice <= 0.0 || nSettle >= nMat || nDiff > 360 )
1292 double fRet = 100.0;
1295 fRet *= double( nDiff );
1302 //-----------------------------------------------------------------------------
1303 // financial functions COUP***
1307 // COUPPCD: find last coupon date before settlement (can be equal to settlement)
1308 void lcl_GetCouppcd( ScaDate
& rDate
, const ScaDate
& rSettle
, const ScaDate
& rMat
, sal_Int32 nFreq
)
1309 throw( lang::IllegalArgumentException
)
1312 rDate
.setYear( rSettle
.getYear() );
1313 if( rDate
< rSettle
)
1314 rDate
.addYears( 1 );
1315 while( rDate
> rSettle
)
1316 rDate
.addMonths( -12 / nFreq
);
1319 double GetCouppcd( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1322 if( nSettle
>= nMat
|| CHK_Freq
)
1326 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1327 return aDate
.getDate( nNullDate
);
1332 // COUPNCD: find first coupon date after settlement (is never equal to settlement)
1333 void lcl_GetCoupncd( ScaDate
& rDate
, const ScaDate
& rSettle
, const ScaDate
& rMat
, sal_Int32 nFreq
)
1334 throw( lang::IllegalArgumentException
)
1337 rDate
.setYear( rSettle
.getYear() );
1338 if( rDate
> rSettle
)
1339 rDate
.addYears( -1 );
1340 while( rDate
<= rSettle
)
1341 rDate
.addMonths( 12 / nFreq
);
1344 double GetCoupncd( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1347 if( nSettle
>= nMat
|| CHK_Freq
)
1351 lcl_GetCoupncd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1352 return aDate
.getDate( nNullDate
);
1357 // COUPDAYBS: get day count: coupon date before settlement <-> settlement
1358 double GetCoupdaybs( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1361 if( nSettle
>= nMat
|| CHK_Freq
)
1364 ScaDate
aSettle( nNullDate
, nSettle
, nBase
);
1366 lcl_GetCouppcd( aDate
, aSettle
, ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1367 return ScaDate::getDiff( aDate
, aSettle
);
1372 // COUPDAYSNC: get day count: settlement <-> coupon date after settlement
1373 double GetCoupdaysnc( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1376 if( nSettle
>= nMat
|| CHK_Freq
)
1379 if( (nBase
!= 0) && (nBase
!= 4) )
1381 ScaDate
aSettle( nNullDate
, nSettle
, nBase
);
1383 lcl_GetCoupncd( aDate
, aSettle
, ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1384 return ScaDate::getDiff( aSettle
, aDate
);
1386 return GetCoupdays( nNullDate
, nSettle
, nMat
, nFreq
, nBase
) - GetCoupdaybs( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1391 // COUPDAYS: get day count: coupon date before settlement <-> coupon date after settlement
1392 double GetCoupdays( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1395 if( nSettle
>= nMat
|| CHK_Freq
)
1401 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1402 ScaDate
aNextDate( aDate
);
1403 aNextDate
.addMonths( 12 / nFreq
);
1404 return ScaDate::getDiff( aDate
, aNextDate
);
1406 return static_cast< double >( GetDaysInYear( 0, 0, nBase
) ) / nFreq
;
1411 // COUPNUM: get count of coupon dates
1412 double GetCoupnum( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1415 if( nSettle
>= nMat
|| CHK_Freq
)
1418 ScaDate
aMat( nNullDate
, nMat
, nBase
);
1420 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), aMat
, nFreq
);
1421 sal_uInt16 nMonths
= (aMat
.getYear() - aDate
.getYear()) * 12 + aMat
.getMonth() - aDate
.getMonth();
1422 return static_cast< double >( nMonths
* nFreq
/ 12 );
1431 const sal_uInt32
MyList::nStartSize
= 16;
1432 const sal_uInt32
MyList::nIncrSize
= 16;
1435 void MyList::_Grow( void )
1439 void** pNewData
= new void*[ nSize
];
1440 memcpy( pNewData
, pData
, nNew
* sizeof( void* ) );
1447 MyList::MyList( void )
1450 pData
= new void*[ nSize
];
1461 void MyList::Insert( void* p
, sal_uInt32 n
)
1469 void** pIns
= pData
+ n
;
1470 memmove( pIns
+ 1, pIns
, ( nNew
- n
) * sizeof( void* ) );
1481 StringList::~StringList()
1483 for( STRING
* p
= ( STRING
* ) First() ; p
; p
= ( STRING
* ) Next() )
1488 class AnalysisRscStrArrLoader
: public Resource
1491 ResStringArray aStrArray
;
1493 AnalysisRscStrArrLoader( sal_uInt16 nRsc
, sal_uInt16 nArrayId
, ResMgr
& rResMgr
) :
1494 Resource( AnalysisResId( nRsc
, rResMgr
) ),
1495 aStrArray( AnalysisResId( nArrayId
, rResMgr
) )
1500 const ResStringArray
& GetStringArray() const { return aStrArray
; }
1506 FuncData::FuncData( const FuncDataBase
& r
, ResMgr
& rResMgr
) :
1507 aIntName( OUString::createFromAscii( r
.pIntName
) ),
1508 nUINameID( r
.nUINameID
),
1509 nDescrID( r
.nDescrID
),
1510 bDouble( r
.bDouble
),
1511 bWithOpt( r
.bWithOpt
),
1512 nParam( r
.nNumOfParams
),
1513 nCompID( r
.nCompListID
),
1516 AnalysisRscStrArrLoader
aArrLoader( RID_ANALYSIS_DEFFUNCTION_NAMES
, nCompID
, rResMgr
);
1517 // ResStringArray aDefFuncNameArray( AnalysisResId( nCompID, rResMgr ) );
1518 const ResStringArray
& rArr
= aArrLoader
.GetStringArray();
1520 sal_uInt16 nCount
= sal::static_int_cast
<sal_uInt16
>( rArr
.Count() );
1523 for( n
= 0 ; n
< nCount
; n
++ )
1524 aCompList
.Append( rArr
.GetString( n
) );
1528 FuncData::~FuncData()
1533 sal_uInt16
FuncData::GetStrIndex( sal_uInt16 nParamNum
) const
1538 if( nParamNum
> nParam
)
1541 return nParamNum
* 2;
1547 FuncDataList::FuncDataList( ResMgr
& rResMgr
)
1549 const sal_uInt32 nNum
= sizeof( pFuncDatas
) / sizeof( FuncDataBase
);
1551 for( sal_uInt16 n
= 0 ; n
< nNum
; n
++ )
1552 Append( new FuncData( pFuncDatas
[ n
], rResMgr
) );
1556 FuncDataList::~FuncDataList()
1558 for( FuncData
* p
= ( FuncData
* ) First() ; p
; p
= ( FuncData
* ) Next() )
1563 const FuncData
* FuncDataList::Get( const OUString
& aProgrammaticName
) const
1565 if( aLastName
== aProgrammaticName
)
1566 return Get( nLast
);
1568 ( ( FuncDataList
* ) this )->aLastName
= aProgrammaticName
;
1570 sal_uInt32 nE
= Count();
1571 for( sal_uInt32 n
= 0 ; n
< nE
; n
++ )
1573 const FuncData
* p
= Get( n
);
1574 if( p
->Is( aProgrammaticName
) )
1576 ( ( FuncDataList
* ) this )->nLast
= n
;
1581 ( ( FuncDataList
* ) this )->nLast
= 0xFFFFFFFF;
1586 AnalysisResId::AnalysisResId( sal_uInt16 nId
, ResMgr
& rResMgr
) : ResId( nId
, rResMgr
)
1593 SortedIndividualInt32List::SortedIndividualInt32List()
1598 SortedIndividualInt32List::~SortedIndividualInt32List()
1603 void SortedIndividualInt32List::Insert( sal_Int32 nDay
)
1605 sal_uInt32 nIndex
= Count();
1609 sal_Int32 nRef
= Get( nIndex
);
1612 else if( nDay
> nRef
)
1614 MyList::Insert( (void*) nDay
, nIndex
+ 1 );
1618 MyList::Insert( (void*) nDay
, 0UL );
1622 void SortedIndividualInt32List::Insert( sal_Int32 nDay
, sal_Int32 nNullDate
, sal_Bool bInsertOnWeekend
)
1628 if( bInsertOnWeekend
|| (GetDayOfWeek( nDay
) < 5) )
1633 void SortedIndividualInt32List::Insert(
1634 double fDay
, sal_Int32 nNullDate
, sal_Bool bInsertOnWeekend
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1636 if( (fDay
< -2147483648.0) || (fDay
> 2147483649.0) )
1637 throw lang::IllegalArgumentException();
1638 Insert( static_cast< sal_Int32
>( fDay
), nNullDate
, bInsertOnWeekend
);
1642 sal_Bool
SortedIndividualInt32List::Find( sal_Int32 nVal
) const
1644 sal_uInt32 nE
= Count();
1646 if( !nE
|| nVal
< Get( 0 ) || nVal
> Get( nE
- 1 ) )
1651 for( sal_uInt32 n
= 0 ; n
< nE
; n
++ )
1653 sal_Int32 nRef
= Get( n
);
1657 else if( nRef
> nVal
)
1664 void SortedIndividualInt32List::InsertHolidayList(
1665 const ScaAnyConverter
& rAnyConv
,
1666 const uno::Any
& rHolAny
,
1667 sal_Int32 nNullDate
,
1668 sal_Bool bInsertOnWeekend
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1671 if( rAnyConv
.getDouble( fDay
, rHolAny
) )
1672 Insert( fDay
, nNullDate
, bInsertOnWeekend
);
1676 void SortedIndividualInt32List::InsertHolidayList(
1677 ScaAnyConverter
& rAnyConv
,
1678 const uno::Reference
< beans::XPropertySet
>& xOptions
,
1679 const uno::Any
& rHolAny
,
1680 sal_Int32 nNullDate
,
1681 sal_Bool bInsertOnWeekend
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1683 rAnyConv
.init( xOptions
);
1684 if( rHolAny
.getValueTypeClass() == uno::TypeClass_SEQUENCE
)
1686 uno::Sequence
< uno::Sequence
< uno::Any
> > aAnySeq
;
1687 if( rHolAny
>>= aAnySeq
)
1689 const uno::Sequence
< uno::Any
>* pSeqArray
= aAnySeq
.getConstArray();
1690 for( sal_Int32 nIndex1
= 0; nIndex1
< aAnySeq
.getLength(); nIndex1
++ )
1692 const uno::Sequence
< uno::Any
>& rSubSeq
= pSeqArray
[ nIndex1
];
1693 const uno::Any
* pAnyArray
= rSubSeq
.getConstArray();
1695 for( sal_Int32 nIndex2
= 0; nIndex2
< rSubSeq
.getLength(); nIndex2
++ )
1696 InsertHolidayList( rAnyConv
, pAnyArray
[ nIndex2
], nNullDate
, bInsertOnWeekend
);
1700 throw lang::IllegalArgumentException();
1703 InsertHolidayList( rAnyConv
, rHolAny
, nNullDate
, bInsertOnWeekend
);
1708 //-----------------------------------------------------------------------------
1710 ScaDoubleList::~ScaDoubleList()
1712 for( double* pDbl
= const_cast< double* >( First() ); pDbl
; pDbl
= const_cast< double* >( Next() ) )
1717 void ScaDoubleList::Append(
1718 const uno::Sequence
< uno::Sequence
< double > >& rValueSeq
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1720 const uno::Sequence
< double >* pSeqArray
= rValueSeq
.getConstArray();
1721 for( sal_Int32 nIndex1
= 0; nIndex1
< rValueSeq
.getLength(); nIndex1
++ )
1723 const uno::Sequence
< double >& rSubSeq
= pSeqArray
[ nIndex1
];
1724 const double* pArray
= rSubSeq
.getConstArray();
1725 for( sal_Int32 nIndex2
= 0; nIndex2
< rSubSeq
.getLength(); nIndex2
++ )
1726 Append( pArray
[ nIndex2
] );
1731 void ScaDoubleList::Append(
1732 const uno::Sequence
< uno::Sequence
< sal_Int32
> >& rValueSeq
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1734 const uno::Sequence
< sal_Int32
>* pSeqArray
= rValueSeq
.getConstArray();
1735 for( sal_Int32 nIndex1
= 0; nIndex1
< rValueSeq
.getLength(); nIndex1
++ )
1737 const uno::Sequence
< sal_Int32
>& rSubSeq
= pSeqArray
[ nIndex1
];
1738 const sal_Int32
* pArray
= rSubSeq
.getConstArray();
1739 for( sal_Int32 nIndex2
= 0; nIndex2
< rSubSeq
.getLength(); nIndex2
++ )
1740 Append( pArray
[ nIndex2
] );
1746 void ScaDoubleList::Append(
1747 const ScaAnyConverter
& rAnyConv
,
1748 const uno::Any
& rAny
,
1749 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1751 if( rAny
.getValueTypeClass() == uno::TypeClass_SEQUENCE
)
1752 Append( rAnyConv
, *static_cast< const uno::Sequence
< uno::Sequence
< uno::Any
> >* >( rAny
.getValue() ), bIgnoreEmpty
);
1756 if( rAnyConv
.getDouble( fValue
, rAny
) )
1758 else if( !bIgnoreEmpty
)
1764 void ScaDoubleList::Append(
1765 const ScaAnyConverter
& rAnyConv
,
1766 const uno::Sequence
< uno::Any
>& rAnySeq
,
1767 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1769 const uno::Any
* pArray
= rAnySeq
.getConstArray();
1770 for( sal_Int32 nIndex
= 0; nIndex
< rAnySeq
.getLength(); nIndex
++ )
1771 Append( rAnyConv
, pArray
[ nIndex
], bIgnoreEmpty
);
1775 void ScaDoubleList::Append(
1776 const ScaAnyConverter
& rAnyConv
,
1777 const uno::Sequence
< uno::Sequence
< uno::Any
> >& rAnySeq
,
1778 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1780 const uno::Sequence
< uno::Any
>* pArray
= rAnySeq
.getConstArray();
1781 for( sal_Int32 nIndex
= 0; nIndex
< rAnySeq
.getLength(); nIndex
++ )
1782 Append( rAnyConv
, pArray
[ nIndex
], bIgnoreEmpty
);
1787 void ScaDoubleList::Append(
1788 ScaAnyConverter
& rAnyConv
,
1789 const uno::Reference
< beans::XPropertySet
>& xOpt
,
1790 const uno::Sequence
< uno::Any
>& rAnySeq
,
1791 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1793 rAnyConv
.init( xOpt
);
1794 Append( rAnyConv
, rAnySeq
, bIgnoreEmpty
);
1798 sal_Bool
ScaDoubleList::CheckInsert( double ) const throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1805 //-----------------------------------------------------------------------------
1807 sal_Bool
ScaDoubleListGT0::CheckInsert( double fValue
) const throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1810 throw lang::IllegalArgumentException();
1811 return fValue
> 0.0;
1816 //-----------------------------------------------------------------------------
1818 sal_Bool
ScaDoubleListGE0::CheckInsert( double fValue
) const throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1821 throw lang::IllegalArgumentException();
1827 //-----------------------------------------------------------------------------
1829 Complex::Complex( const STRING
& rStr
) THROWDEF_RTE_IAE
1831 if( !ParseString( rStr
, *this ) )
1836 inline sal_Bool
Complex::IsImagUnit( sal_Unicode c
)
1838 return c
== 'i' || c
== 'j';
1841 sal_Bool
Complex::ParseString( const STRING
& rStr
, Complex
& rCompl
)
1843 rCompl
.c
= '\0'; // do not force a symbol, if only real part present
1845 const sal_Unicode
* pStr
= ( const sal_Unicode
* ) rStr
;
1847 if( IsImagUnit( *pStr
) && rStr
.getLength() == 1)
1857 if( !ParseDouble( pStr
, f
) )
1862 case '-': // imag part follows
1866 if( IsImagUnit( pStr
[ 1 ] ) )
1868 rCompl
.c
= pStr
[ 1 ];
1869 if( pStr
[ 2 ] == 0 )
1872 rCompl
.i
= ( *pStr
== '+' )? 1.0 : -1.0;
1876 else if( ParseDouble( pStr
, f
) && IsImagUnit( *pStr
) )
1900 case 0: // only real-part
1910 STRING
Complex::GetString() const THROWDEF_RTE_IAE
1912 static const String
aI( 'i' );
1913 static const String
aJ( 'j' );
1914 static const String
aPlus( '+' );
1915 static const String
aMinus( '-' );
1921 bool bHasImag
= i
!= 0.0;
1922 bool bHasReal
= !bHasImag
|| (r
!= 0.0);
1925 aRet
= ::GetString( r
);
1933 else if( i
== -1.0 )
1936 aRet
+= ::GetString( i
, bHasReal
);
1937 aRet
+= (c
!= 'j') ? aI
: aJ
;
1944 double Complex::Arg( void ) const THROWDEF_RTE_IAE
1946 if( r
== 0.0 && i
== 0.0 )
1949 double phi
= acos( r
/ Abs() );
1958 void Complex::Power( double fPower
) THROWDEF_RTE_IAE
1960 if( r
== 0.0 && i
== 0.0 )
1975 phi
= acos( r
/ p
);
1979 p
= pow( p
, fPower
);
1987 void Complex::Sqrt( void )
1989 static const double fMultConst
= 0.7071067811865475; // ...2440084436210485 = 1/sqrt(2)
1991 double i_
= sqrt( p
- r
) * fMultConst
;
1993 r
= sqrt( p
+ r
) * fMultConst
;
1994 i
= ( i
< 0.0 )? -i_
: i_
;
1998 inline sal_Bool
SinOverflow( double f
)
2000 return fabs( f
) >= 134217728;
2004 void Complex::Sin( void ) THROWDEF_RTE_IAE
2006 if( SinOverflow( r
) )
2013 r_
= sin( r
) * cosh( i
);
2014 i
= cos( r
) * sinh( i
);
2022 void Complex::Cos( void ) THROWDEF_RTE_IAE
2024 if( SinOverflow( r
) )
2031 r_
= cos( r
) * cosh( i
);
2032 i
= -( sin( r
) * sinh( i
) );
2040 void Complex::Div( const Complex
& z
) THROWDEF_RTE_IAE
2042 if( z
.r
== 0 && z
.i
== 0 )
2050 double f
= 1.0 / ( a2
* a2
+ b2
* b2
);
2052 r
= ( a1
* a2
+ b1
* b2
) * f
;
2053 i
= ( a2
* b1
- a1
* b2
) * f
;
2059 void Complex::Exp( void )
2061 double fE
= exp( r
);
2067 void Complex::Ln( void ) THROWDEF_RTE_IAE
2069 if( r
== 0.0 && i
== 0.0 )
2072 double fAbs
= Abs();
2073 sal_Bool bNegi
= i
< 0.0;
2075 i
= acos( r
/ fAbs
);
2084 void Complex::Log10( void ) THROWDEF_RTE_IAE
2087 Mult( 0.434294481903251828 ); // * log10( e )
2091 void Complex::Log2( void ) THROWDEF_RTE_IAE
2094 Mult( 1.442695040888963407 ); // * log2( e )
2100 ComplexList::~ComplexList()
2102 for( Complex
* p
= ( Complex
* ) First() ; p
; p
= ( Complex
* ) Next() )
2107 void ComplexList::Append( const SEQSEQ( STRING
)& r
, ComplListAppendHandl eAH
) THROWDEF_RTE_IAE
2110 sal_Int32 nE1
= r
.getLength();
2112 sal_Bool bEmpty0
= eAH
== AH_EmpyAs0
;
2113 sal_Bool bErrOnEmpty
= eAH
== AH_EmptyAsErr
;
2115 for( n1
= 0 ; n1
< nE1
; n1
++ )
2117 const SEQ( STRING
)& rList
= r
[ n1
];
2118 nE2
= rList
.getLength();
2120 for( n2
= 0 ; n2
< nE2
; n2
++ )
2122 const STRING
& rStr
= rList
[ n2
];
2124 if( rStr
.getLength() )
2125 Append( new Complex( rStr
) );
2127 Append( new Complex( 0.0 ) );
2128 else if( bErrOnEmpty
)
2135 void ComplexList::Append( const SEQ( ANY
)& aMultPars
, ComplListAppendHandl eAH
) THROWDEF_RTE_IAE
2137 sal_Int32 nEle
= aMultPars
.getLength();
2138 sal_Bool bEmpty0
= eAH
== AH_EmpyAs0
;
2139 sal_Bool bErrOnEmpty
= eAH
== AH_EmptyAsErr
;
2141 for( sal_Int32 i
= 0 ; i
< nEle
; i
++ )
2143 const ANY
& r
= aMultPars
[ i
];
2144 switch( r
.getValueTypeClass() )
2146 case uno::TypeClass_VOID
: break;
2147 case uno::TypeClass_STRING
:
2149 const STRING
* pStr
= ( const STRING
* ) r
.getValue();
2151 if( pStr
->getLength() )
2152 Append( new Complex( *( STRING
* ) r
.getValue() ) );
2154 Append( new Complex( 0.0 ) );
2155 else if( bErrOnEmpty
)
2159 case uno::TypeClass_DOUBLE
:
2160 Append( new Complex( *( double* ) r
.getValue(), 0.0 ) );
2162 case uno::TypeClass_SEQUENCE
:
2164 SEQSEQ( ANY
) aValArr
;
2167 sal_Int32 nE
= aValArr
.getLength();
2168 const SEQ( ANY
)* pArr
= aValArr
.getConstArray();
2169 for( sal_Int32 n
= 0 ; n
< nE
; n
++ )
2170 Append( pArr
[ n
], eAH
);
2185 ConvertData::ConvertData( const sal_Char p
[], double fC
, ConvertDataClass e
, sal_Bool bPrefSupport
) : aName( p
, strlen( p
), RTL_TEXTENCODING_MS_1252
)
2189 bPrefixSupport
= bPrefSupport
;
2192 ConvertData::~ConvertData()
2197 sal_Int16
ConvertData::GetMatchingLevel( const STRING
& rRef
) const
2200 sal_Int32 nLen
= rRef
.getLength();
2201 sal_Int32 nIndex
= rRef
.lastIndexOf( '^' );
2202 if( nIndex
> 0 && nIndex
== ( nLen
- 2 ) )
2204 const sal_Unicode
* p
= aStr
.getStr();
2205 aStr
= STRING( p
, nLen
- 2 );
2206 aStr
+= STRING( p
[ nLen
- 1 ] );
2208 if( aName
.equals( aStr
) )
2212 const sal_Unicode
* p
= aStr
.getStr();
2214 nLen
= aStr
.getLength();
2215 bool bPref
= IsPrefixSupport();
2216 bool bOneChar
= (bPref
&& nLen
> 1 && (aName
== p
+ 1));
2217 if (bOneChar
|| (bPref
&& nLen
> 2 && (aName
== p
+ 2) &&
2218 *p
== 'd' && *(p
+1) == 'a'))
2223 case 'y': n
= -24; break; // yocto
2224 case 'z': n
= -21; break; // zepto
2225 case 'a': n
= -18; break;
2226 case 'f': n
= -15; break;
2227 case 'p': n
= -12; break;
2228 case 'n': n
= -9; break;
2229 case 'u': n
= -6; break;
2230 case 'm': n
= -3; break;
2231 case 'c': n
= -2; break;
2240 case 'e': n
= 1; break;
2241 case 'h': n
= 2; break;
2242 case 'k': n
= 3; break;
2243 case 'M': n
= 6; break;
2244 case 'G': n
= 9; break;
2245 case 'T': n
= 12; break;
2246 case 'P': n
= 15; break;
2247 case 'E': n
= 18; break;
2248 case 'Z': n
= 21; break; // zetta
2249 case 'Y': n
= 24; break; // yotta
2254 // We could weed some nonsense out, ODFF doesn't say so though.
2256 if (n
< 0 && Class() == CDC_Information
)
2257 n
= INV_MATCHLEV
; // milli-bits doesn't make sense
2260 //! <HACK> #100616# "cm3" is not 10^-2 m^3 but 10^-6 m^3 !!! ------------------
2261 if( n
!= INV_MATCHLEV
)
2263 sal_Unicode cLast
= p
[ aStr
.getLength() - 1 ];
2266 else if( cLast
== '3' )
2269 //! </HACK> -------------------------------------------------------------------
2273 else if ( nLen
> 2 && ( aName
== p
+ 2 ) && ( Class() == CDC_Information
) )
2275 const sal_Unicode
* pStr
= aStr
.getStr();
2276 if ( *(pStr
+ 1) != 'i')
2277 return INV_MATCHLEV
;
2281 case 'k': n
= 10; break;
2282 case 'M': n
= 20; break;
2283 case 'G': n
= 30; break;
2284 case 'T': n
= 40; break;
2285 case 'P': n
= 50; break;
2286 case 'E': n
= 60; break;
2287 case 'Z': n
= 70; break;
2288 case 'Y': n
= 80; break;
2295 return INV_MATCHLEV
;
2300 double ConvertData::Convert(
2301 double f
, const ConvertData
& r
, sal_Int16 nLevFrom
, sal_Int16 nLevTo
) const THROWDEF_RTE_IAE
2303 if( Class() != r
.Class() )
2306 sal_Bool bBinFromLev
= ( nLevFrom
> 0 && ( nLevFrom
% 10 ) == 0 );
2307 sal_Bool bBinToLev
= ( nLevTo
> 0 && ( nLevTo
% 10 ) == 0 );
2309 if ( Class() == CDC_Information
&& ( bBinFromLev
|| bBinToLev
) )
2311 if ( bBinFromLev
&& bBinToLev
)
2313 nLevFrom
= sal::static_int_cast
<sal_Int16
>( nLevFrom
- nLevTo
);
2314 f
*= r
.fConst
/ fConst
;
2316 f
*= pow( 2.0, nLevFrom
);
2318 else if ( bBinFromLev
)
2319 f
*= ( r
.fConst
/ fConst
) * ( pow( 2.0, nLevFrom
) / pow( 10.0, nLevTo
) );
2321 f
*= ( r
.fConst
/ fConst
) * ( pow( 10.0, nLevFrom
) / pow( 2.0, nLevTo
) );
2325 nLevFrom
= sal::static_int_cast
<sal_Int16
>( nLevFrom
- nLevTo
); // effective level
2327 f
*= r
.fConst
/ fConst
;
2330 f
= ::rtl::math::pow10Exp( f
, nLevFrom
);
2336 double ConvertData::ConvertToBase( double f
, sal_Int16 n
) const
2338 return ::rtl::math::pow10Exp( f
/ fConst
, n
);
2342 double ConvertData::ConvertFromBase( double f
, sal_Int16 n
) const
2344 return ::rtl::math::pow10Exp( f
* fConst
, -n
);
2349 ConvertDataLinear::~ConvertDataLinear()
2353 double ConvertDataLinear::Convert(
2354 double f
, const ConvertData
& r
, sal_Int16 nLevFrom
, sal_Int16 nLevTo
) const THROWDEF_RTE_IAE
2356 if( Class() != r
.Class() )
2359 // return ::rtl::math::round( r.ConvertFromBase( ConvertToBase( f, nLevFrom ), nLevTo ), 13 );
2360 return r
.ConvertFromBase( ConvertToBase( f
, nLevFrom
), nLevTo
);
2364 double ConvertDataLinear::ConvertToBase( double f
, sal_Int16 n
) const
2367 f
= ::rtl::math::pow10Exp( f
, n
);
2376 double ConvertDataLinear::ConvertFromBase( double f
, sal_Int16 n
) const
2382 f
= ::rtl::math::pow10Exp( f
, -n
);
2390 ConvertDataList::ConvertDataList( void )
2392 #define NEWD(str,unit,cl) Append(new ConvertData(str,unit,cl))
2393 #define NEWDP(str,unit,cl) Append(new ConvertData(str,unit,cl,sal_True))
2394 #define NEWL(str,unit,offs,cl) Append(new ConvertDataLinear(str,unit,offs,cl))
2395 #define NEWLP(str,unit,offs,cl) Append(new ConvertDataLinear(str,unit,offs,cl,sal_True))
2397 // *** are extra and not standard Excel Analysis Addin!
2399 // MASS: 1 Gram is...
2400 NEWDP( "g", 1.0000000000000000E00
, CDC_Mass
); // Gram
2401 NEWD( "sg", 6.8522050005347800E-05, CDC_Mass
); // Pieces
2402 NEWD( "lbm", 2.2046229146913400E-03, CDC_Mass
); // Pound (commercial weight)
2403 NEWDP( "u", 6.0221370000000000E23
, CDC_Mass
); // U (atomic mass)
2404 NEWD( "ozm", 3.5273971800362700E-02, CDC_Mass
); // Ounce (commercial weight)
2405 NEWD( "stone", 1.574730e-04, CDC_Mass
); // *** Stone
2406 NEWD( "ton", 1.102311e-06, CDC_Mass
); // *** Ton
2407 NEWD( "grain", 1.543236E01
, CDC_Mass
); // *** Grain
2408 NEWD( "pweight", 7.054792E-01, CDC_Mass
); // *** Pennyweight
2409 NEWD( "hweight", 1.968413E-05, CDC_Mass
); // *** Hundredweight
2410 NEWD( "shweight", 2.204623E-05, CDC_Mass
); // *** Shorthundredweight
2411 NEWD( "brton", 9.842065E-07, CDC_Mass
); // *** Gross Registered Ton
2412 NEWD( "cwt", 2.2046226218487758E-05, CDC_Mass
); // U.S. (short) hundredweight
2413 NEWD( "shweight", 2.2046226218487758E-05, CDC_Mass
); // U.S. (short) hundredweight also
2414 NEWD( "uk_cwt", 1.9684130552221213E-05, CDC_Mass
); // Imperial hundredweight
2415 NEWD( "lcwt", 1.9684130552221213E-05, CDC_Mass
); // Imperial hundredweight also
2416 NEWD( "hweight", 1.9684130552221213E-05, CDC_Mass
); // Imperial hundredweight also
2417 NEWD( "uk_ton", 9.8420652761106063E-07, CDC_Mass
); // Imperial ton
2418 NEWD( "LTON", 9.8420652761106063E-07, CDC_Mass
); // Imperial ton also
2420 // LENGTH: 1 Meter is...
2421 NEWDP( "m", 1.0000000000000000E00
, CDC_Length
); // Meter
2422 NEWD( "mi", 6.2137119223733397E-04, CDC_Length
); // Britsh Mile 6,21371192237333969617434184363e-4
2423 NEWD( "Nmi", 5.3995680345572354E-04, CDC_Length
); // Nautical Mile 5,39956803455723542116630669546e-4
2424 NEWD( "in", 3.9370078740157480E01
, CDC_Length
); // Inch 39,37007874015748031496062992126
2425 NEWD( "ft", 3.2808398950131234E00
, CDC_Length
); // Foot 3,2808398950131233595800524934383
2426 NEWD( "yd", 1.0936132983377078E00
, CDC_Length
); // Yard 1,0936132983377077865266841644794
2427 NEWDP( "ang", 1.0000000000000000E10
, CDC_Length
); // Angstroem
2428 NEWD( "Pica", 2.8346456692913386E03
, CDC_Length
); // Pica (1/72 Inch) 2834,6456692913385826771653543307
2429 NEWD( "ell", 8.748906E-01, CDC_Length
); // *** Ell
2430 NEWDP( "parsec", 3.240779E-17, CDC_Length
); // *** Parsec
2431 NEWDP( "pc", 3.240779E-17, CDC_Length
); // *** Parsec also
2432 NEWDP( "lightyear", 1.0570234557732930E-16, CDC_Length
); // *** Light Year
2433 NEWDP( "ly", 1.0570234557732930E-16, CDC_Length
); // *** Light Year also
2434 NEWD( "survey_mi", 6.2136994949494949E-04, CDC_Length
); // U.S. survey mile
2436 // TIME: 1 Second is...
2437 NEWD( "yr", 3.1688087814028950E-08, CDC_Time
); // Year
2438 NEWD( "day", 1.1574074074074074E-05, CDC_Time
); // Day
2439 NEWD( "d", 1.1574074074074074E-05, CDC_Time
); // Day also
2440 NEWD( "hr", 2.7777777777777778E-04, CDC_Time
); // Hour
2441 NEWD( "mn", 1.6666666666666667E-02, CDC_Time
); // Minute
2442 NEWD( "min", 1.6666666666666667E-02, CDC_Time
); // Minute also
2443 NEWDP( "sec", 1.0000000000000000E00
, CDC_Time
); // Second
2444 NEWDP( "s", 1.0000000000000000E00
, CDC_Time
); // Second also
2446 // PRESSURE: 1 Pascal is...
2447 NEWDP( "Pa", 1.0000000000000000E00
, CDC_Pressure
); // Pascal
2448 NEWDP( "atm", 9.8692329999819300E-06, CDC_Pressure
); // Atmosphere
2449 NEWDP( "at", 9.8692329999819300E-06, CDC_Pressure
); // Atmosphere also
2450 NEWDP( "mmHg", 7.5006170799862700E-03, CDC_Pressure
); // mm Hg (Mercury)
2451 NEWD( "Torr", 7.5006380000000000E-03, CDC_Pressure
); // *** Torr
2452 NEWD( "psi", 1.4503770000000000E-04, CDC_Pressure
); // *** Psi
2454 // FORCE: 1 Newton is...
2455 NEWDP( "N", 1.0000000000000000E00
, CDC_Force
); // Newton
2456 NEWDP( "dyn", 1.0000000000000000E05
, CDC_Force
); // Dyn
2457 NEWDP( "dy", 1.0000000000000000E05
, CDC_Force
); // Dyn also
2458 NEWD( "lbf", 2.24808923655339E-01, CDC_Force
); // Pound-Force
2459 NEWDP( "pond", 1.019716E02
, CDC_Force
); // *** Pond
2461 // ENERGY: 1 Joule is...
2462 NEWDP( "J", 1.0000000000000000E00
, CDC_Energy
); // Joule
2463 NEWDP( "e", 1.0000000000000000E07
, CDC_Energy
); // Erg -> http://www.chemie.fu-berlin.de/chemistry/general/si.html
2464 // NEWD( "e", 9.99999519343231E06, CDC_Energy ); // Erg
2465 NEWDP( "c", 2.3900624947346700E-01, CDC_Energy
); // Thermodynamical Calorie
2466 NEWDP( "cal", 2.3884619064201700E-01, CDC_Energy
); // Calorie
2467 NEWDP( "eV", 6.2414570000000000E18
, CDC_Energy
); // Electronvolt
2468 NEWDP( "ev", 6.2414570000000000E18
, CDC_Energy
); // Electronvolt also
2469 NEWD( "HPh", 3.7250611111111111E-07, CDC_Energy
); // Horsepower Hours
2470 NEWD( "hh", 3.7250611111111111E-07, CDC_Energy
); // Horsepower Hours also
2471 // NEWD( "HPh", 3.72506430801000E-07, CDC_Energy ); // Horsepower Hours
2472 NEWDP( "Wh", 2.7777777777777778E-04, CDC_Energy
); // Watt Hours
2473 NEWDP( "wh", 2.7777777777777778E-04, CDC_Energy
); // Watt Hours also
2474 NEWD( "flb", 2.37304222192651E01
, CDC_Energy
); // Foot Pound
2475 NEWD( "BTU", 9.4781506734901500E-04, CDC_Energy
); // British Thermal Unit
2476 NEWD( "btu", 9.4781506734901500E-04, CDC_Energy
); // British Thermal Unit also
2478 // POWER: 1 Watt is...
2479 NEWDP( "W", 1.0000000000000000E00
, CDC_Power
); // Watt
2480 NEWDP( "w", 1.0000000000000000E00
, CDC_Power
); // Watt also
2481 NEWD( "HP", 1.341022E-03, CDC_Power
); // Horsepower
2482 NEWD( "h", 1.341022E-03, CDC_Power
); // Horsepower also
2483 NEWD( "PS", 1.359622E-03, CDC_Power
); // *** German Pferdestaerke
2484 // NEWD( "HP", 1.4102006031908E-03, CDC_Power ); // Excel seams to be a little bit wrong... either this doesn't fit to J -> HPh
2486 // MAGNETISM: 1 Tesla is...
2487 NEWDP( "T", 1.0000000000000000E00
, CDC_Magnetism
); // Tesla
2488 NEWDP( "ga", 1.0000000000000000E04
, CDC_Magnetism
); // Gauss
2490 // TEMERATURE: 1 Kelvin is...
2491 NEWL( "C", 1.0000000000000000E00
, -2.7315000000000000E02
, CDC_Temperature
); // Celsius
2492 NEWL( "cel", 1.0000000000000000E00
, -2.7315000000000000E02
, CDC_Temperature
); // Celsius also
2493 NEWL( "F", 1.8000000000000000E00
, -2.5537222222222222E02
, CDC_Temperature
); // Fahrenheit
2494 NEWL( "fah", 1.8000000000000000E00
, -2.5537222222222222E02
, CDC_Temperature
); // Fahrenheit also
2495 NEWLP( "K", 1.0000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // Kelvin
2496 NEWLP( "kel", 1.0000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // Kelvin also
2497 NEWL( "Reau", 8.0000000000000000E-01, -2.7315000000000000E02
, CDC_Temperature
); // *** Reaumur
2498 NEWL( "Rank", 1.8000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // *** Rankine
2500 // VOLUMNE: 1 Liter is...
2501 NEWD( "tsp", 2.0284000000000000E02
, CDC_Volume
); // Teaspoon
2502 NEWD( "tbs", 6.7613333333333333E01
, CDC_Volume
); // Tablespoon
2503 NEWD( "oz", 3.3806666666666667E01
, CDC_Volume
); // Ounce Liquid
2504 NEWD( "cup", 4.2258333333333333E00
, CDC_Volume
); // Cup
2505 NEWD( "pt", 2.1129166666666667E00
, CDC_Volume
); // US Pint
2506 NEWD( "us_pt", 2.1129166666666667E00
, CDC_Volume
); // US Pint also
2507 NEWD( "uk_pt", 1.75975569552166E00
, CDC_Volume
); // UK Pint
2508 NEWD( "qt", 1.0564583333333333E00
, CDC_Volume
); // Quart
2509 NEWD( "gal", 2.6411458333333333E-01, CDC_Volume
); // Gallone
2510 NEWDP( "l", 1.0000000000000000E00
, CDC_Volume
); // Liter
2511 NEWDP( "L", 1.0000000000000000E00
, CDC_Volume
); // Liter also
2512 NEWDP( "lt", 1.0000000000000000E00
, CDC_Volume
); // Liter also
2513 NEWDP( "m3", 1.0000000000000000E-03, CDC_Volume
); // *** Cubic Meter
2514 NEWD( "mi3", 2.3991275857892772E-13, CDC_Volume
); // *** Cubic Britsh Mile
2515 NEWD( "Nmi3", 1.5742621468581148E-13, CDC_Volume
); // *** Cubic Nautical Mile
2516 NEWD( "in3", 6.1023744094732284E01
, CDC_Volume
); // *** Cubic Inch
2517 NEWD( "ft3", 3.5314666721488590E-02, CDC_Volume
); // *** Cubic Foot
2518 NEWD( "yd3", 1.3079506193143922E-03, CDC_Volume
); // *** Cubic Yard
2519 NEWDP( "ang3", 1.0000000000000000E27
, CDC_Volume
); // *** Cubic Angstroem
2520 NEWD( "Pica3", 2.2776990435870636E07
, CDC_Volume
); // *** Cubic Pica
2521 NEWD( "barrel", 6.289811E-03, CDC_Volume
); // *** Barrel (=42gal?)
2522 NEWD( "bushel", 2.837759E-02, CDC_Volume
); // *** Bushel
2523 NEWD( "regton", 3.531467E-04, CDC_Volume
); // *** Register ton
2524 NEWD( "GRT", 3.531467E-04, CDC_Volume
); // *** Register ton also
2525 NEWD( "Schooner", 2.3529411764705882E00
, CDC_Volume
); // *** austr. Schooner
2526 NEWD( "Middy", 3.5087719298245614E00
, CDC_Volume
); // *** austr. Middy
2527 NEWD( "Glass", 5.0000000000000000E00
, CDC_Volume
); // *** austr. Glass
2528 NEWD( "Sixpack", 0.5, CDC_Volume
); // ***
2529 NEWD( "Humpen", 2.0, CDC_Volume
); // ***
2530 NEWD( "ly3", 1.1810108125623799E-51, CDC_Volume
); // *** Cubic light-year
2531 NEWD( "MTON", 1.4125866688595436E00
, CDC_Volume
); // *** Measurement ton
2532 NEWD( "tspm", 5.0000000000000000E02
, CDC_Volume
); // *** Modern teaspoon
2533 NEWD( "uk_gal", 2.199694619402070E-01, CDC_Volume
); // U.K. / Imperial gallon
2534 NEWD( "uk_qt", 8.798778477608300E-01, CDC_Volume
); // U.K. / Imperial quart
2536 // 1 Square Meter is...
2537 NEWDP( "m2", 1.0000000000000000E00
, CDC_Area
); // *** Square Meter
2538 NEWD( "mi2", 3.8610215854244585E-07, CDC_Area
); // *** Square Britsh Mile
2539 NEWD( "Nmi2", 2.9155334959812286E-07, CDC_Area
); // *** Square Nautical Mile
2540 NEWD( "in2", 1.5500031000062000E03
, CDC_Area
); // *** Square Inch
2541 NEWD( "ft2", 1.0763910416709722E01
, CDC_Area
); // *** Square Foot
2542 NEWD( "yd2", 1.1959900463010803E00
, CDC_Area
); // *** Square Yard
2543 NEWDP( "ang2", 1.0000000000000000E20
, CDC_Area
); // *** Square Angstroem
2544 NEWD( "Pica2", 8.0352160704321409E06
, CDC_Area
); // *** Square Pica
2545 NEWD( "Morgen", 4.0000000000000000E-04, CDC_Area
); // *** Morgen
2546 NEWDP( "ar", 1.000000E-02, CDC_Area
); // *** Ar
2547 NEWD( "acre", 2.471053815E-04, CDC_Area
); // *** Acre
2548 NEWD( "uk_acre", 2.4710538146716534E-04, CDC_Area
); // *** International acre
2549 NEWD( "us_acre", 2.4710439304662790E-04, CDC_Area
); // *** U.S. survey/statute acre
2550 NEWD( "ly2", 1.1172985860549147E-32, CDC_Area
); // *** Square Light-year
2551 NEWD( "ha", 1.000000E-04, CDC_Area
); // *** Hectare
2552 NEWD( "Quadratlatschen",5.6689342403628117914,CDC_Area
); // ***
2554 // SPEED: 1 Meter per Second is...
2555 NEWDP( "m/s", 1.0000000000000000E00
, CDC_Speed
); // *** Meters per Second
2556 NEWDP( "m/sec", 1.0000000000000000E00
, CDC_Speed
); // *** Meters per Second also
2557 NEWDP( "m/h", 3.6000000000000000E03
, CDC_Speed
); // *** Meters per Hour
2558 NEWDP( "m/hr", 3.6000000000000000E03
, CDC_Speed
); // *** Meters per Hour also
2559 NEWD( "mph", 2.2369362920544023E00
, CDC_Speed
); // *** Britsh Miles per Hour
2560 NEWD( "kn", 1.9438444924406048E00
, CDC_Speed
); // *** Knot = Nautical Miles per Hour
2561 NEWD( "admkn", 1.9438446603753486E00
, CDC_Speed
); // *** Admiralty Knot
2562 NEWD( "wahnsinnige Geschwindigkeit", 2.0494886343432328E-14, CDC_Speed
); // ***
2563 NEWD( "ludicrous speed", 2.0494886343432328E-14, CDC_Speed
); // ***
2564 NEWD( "laecherliche Geschwindigkeit", 4.0156958471424288E-06, CDC_Speed
); // ***
2565 NEWD( "ridiculous speed", 4.0156958471424288E-06, CDC_Speed
); // ***
2567 // INFORMATION: 1 Bit is...
2568 NEWDP( "bit", 1.00E00
, CDC_Information
); // *** Bit
2569 NEWDP( "byte", 1.25E-01, CDC_Information
); // *** Byte
2573 ConvertDataList::~ConvertDataList()
2575 for( ConvertData
* p
= First() ; p
; p
= Next() )
2580 double ConvertDataList::Convert( double fVal
, const STRING
& rFrom
, const STRING
& rTo
) THROWDEF_RTE_IAE
2582 // This will not catch illegal units
2583 // if( rFrom == rTo )
2586 ConvertData
* pFrom
= NULL
;
2587 ConvertData
* pTo
= NULL
;
2588 sal_Bool bSearchFrom
= sal_True
;
2589 sal_Bool bSearchTo
= sal_True
;
2590 sal_Int16 nLevelFrom
= 0;
2591 sal_Int16 nLevelTo
= 0;
2593 ConvertData
* p
= First();
2594 while( p
&& ( bSearchFrom
|| bSearchTo
) )
2598 sal_Int16 n
= p
->GetMatchingLevel( rFrom
);
2599 if( n
!= INV_MATCHLEV
)
2602 { // only first match for partial equality rulz a little bit more
2607 { // ... but exact match rulz most
2609 bSearchFrom
= sal_False
;
2617 sal_Int16 n
= p
->GetMatchingLevel( rTo
);
2618 if( n
!= INV_MATCHLEV
)
2621 { // only first match for partial equality rulz a little bit more
2626 { // ... but exact match rulz most
2628 bSearchTo
= sal_False
;
2638 return pFrom
->Convert( fVal
, *pTo
, nLevelFrom
, nLevelTo
);
2645 //-----------------------------------------------------------------------------
2647 ScaDate::ScaDate() :
2652 bLastDayMode( sal_True
),
2653 bLastDay( sal_False
),
2654 b30Days( sal_False
),
2655 bUSMode( sal_False
)
2659 ScaDate::ScaDate( sal_Int32 nNullDate
, sal_Int32 nDate
, sal_Int32 nBase
)
2661 DaysToDate( nNullDate
+ nDate
, nOrigDay
, nMonth
, nYear
);
2662 bLastDayMode
= (nBase
!= 5);
2663 bLastDay
= (nOrigDay
>= ::DaysInMonth( nMonth
, nYear
));
2664 b30Days
= (nBase
== 0) || (nBase
== 4);
2665 bUSMode
= (nBase
== 0);
2669 ScaDate::ScaDate( const ScaDate
& rCopy
) :
2670 nOrigDay( rCopy
.nOrigDay
),
2672 nMonth( rCopy
.nMonth
),
2673 nYear( rCopy
.nYear
),
2674 bLastDayMode( rCopy
.bLastDayMode
),
2675 bLastDay( rCopy
.bLastDay
),
2676 b30Days( rCopy
.b30Days
),
2677 bUSMode( rCopy
.bUSMode
)
2681 ScaDate
& ScaDate::operator=( const ScaDate
& rCopy
)
2683 if( this != &rCopy
)
2685 nOrigDay
= rCopy
.nOrigDay
;
2687 nMonth
= rCopy
.nMonth
;
2688 nYear
= rCopy
.nYear
;
2689 bLastDayMode
= rCopy
.bLastDayMode
;
2690 bLastDay
= rCopy
.bLastDay
;
2691 b30Days
= rCopy
.b30Days
;
2692 bUSMode
= rCopy
.bUSMode
;
2697 void ScaDate::setDay()
2701 // 30-days-mode: set nDay to 30 if original was last day in month
2702 nDay
= Min( nOrigDay
, static_cast< sal_uInt16
>( 30 ) );
2703 if( bLastDay
|| (nDay
>= ::DaysInMonth( nMonth
, nYear
)) )
2708 // set nDay to last day in this month if original was last day
2709 sal_uInt16 nLastDay
= ::DaysInMonth( nMonth
, nYear
);
2710 nDay
= bLastDay
? nLastDay
: Min( nOrigDay
, nLastDay
);
2714 sal_Int32
ScaDate::getDaysInMonthRange( sal_uInt16 nFrom
, sal_uInt16 nTo
) const
2721 nRet
= (nTo
- nFrom
+ 1) * 30;
2724 for( sal_uInt16 nMonthIx
= nFrom
; nMonthIx
<= nTo
; ++nMonthIx
)
2725 nRet
+= getDaysInMonth( nMonthIx
);
2730 sal_Int32
ScaDate::getDaysInYearRange( sal_uInt16 nFrom
, sal_uInt16 nTo
) const
2735 return b30Days
? ((nTo
- nFrom
+ 1) * 360) : ::GetDaysInYears( nFrom
, nTo
);
2738 void ScaDate::doAddYears( sal_Int32 nYearCount
) throw( lang::IllegalArgumentException
)
2740 sal_Int32 nNewYear
= nYearCount
+ nYear
;
2741 if( (nNewYear
< 0) || (nNewYear
> 0x7FFF) )
2742 throw lang::IllegalArgumentException();
2743 nYear
= static_cast< sal_uInt16
>( nNewYear
);
2746 void ScaDate::addMonths( sal_Int32 nMonthCount
) throw( lang::IllegalArgumentException
)
2748 sal_Int32 nNewMonth
= nMonthCount
+ nMonth
;
2749 if( nNewMonth
> 12 )
2752 doAddYears( nNewMonth
/ 12 );
2753 nMonth
= static_cast< sal_uInt16
>( nNewMonth
% 12 ) + 1;
2755 else if( nNewMonth
< 1 )
2757 doAddYears( nNewMonth
/ 12 - 1 );
2758 nMonth
= static_cast< sal_uInt16
>( nNewMonth
% 12 + 12 );
2761 nMonth
= static_cast< sal_uInt16
>( nNewMonth
);
2765 sal_Int32
ScaDate::getDate( sal_Int32 nNullDate
) const
2767 sal_uInt16 nLastDay
= ::DaysInMonth( nMonth
, nYear
);
2768 sal_uInt16 nRealDay
= (bLastDayMode
&& bLastDay
) ? nLastDay
: Min( nLastDay
, nOrigDay
);
2769 return ::DateToDays( nRealDay
, nMonth
, nYear
) - nNullDate
;
2772 sal_Int32
ScaDate::getDiff( const ScaDate
& rFrom
, const ScaDate
& rTo
) throw( lang::IllegalArgumentException
)
2775 return getDiff( rTo
, rFrom
);
2777 sal_Int32 nDiff
= 0;
2778 ScaDate
aFrom( rFrom
);
2783 // corrections for base 0 (US NASD)
2786 if( ((rFrom
.nMonth
== 2) || (rFrom
.nDay
< 30)) && (aTo
.nOrigDay
== 31) )
2788 else if( (aTo
.nMonth
== 2) && aTo
.bLastDay
)
2789 aTo
.nDay
= ::DaysInMonth( 2, aTo
.nYear
);
2791 // corrections for base 4 (Europe)
2794 if( (aFrom
.nMonth
== 2) && (aFrom
.nDay
== 30) )
2795 aFrom
.nDay
= ::DaysInMonth( 2, aFrom
.nYear
);
2796 if( (aTo
.nMonth
== 2) && (aTo
.nDay
== 30) )
2797 aTo
.nDay
= ::DaysInMonth( 2, aTo
.nYear
);
2801 if( (aFrom
.nYear
< aTo
.nYear
) || ((aFrom
.nYear
== aTo
.nYear
) && (aFrom
.nMonth
< aTo
.nMonth
)) )
2803 // move aFrom to 1st day of next month
2804 nDiff
= aFrom
.getDaysInMonth() - aFrom
.nDay
+ 1;
2805 aFrom
.nOrigDay
= aFrom
.nDay
= 1;
2806 aFrom
.bLastDay
= sal_False
;
2807 aFrom
.addMonths( 1 );
2809 if( aFrom
.nYear
< aTo
.nYear
)
2811 // move aFrom to 1st day of next year
2812 nDiff
+= aFrom
.getDaysInMonthRange( aFrom
.nMonth
, 12 );
2813 aFrom
.addMonths( 13 - aFrom
.nMonth
);
2815 // move aFrom to 1st day of this year
2816 nDiff
+= aFrom
.getDaysInYearRange( aFrom
.nYear
, aTo
.nYear
- 1 );
2817 aFrom
.addYears( aTo
.nYear
- aFrom
.nYear
);
2820 // move aFrom to 1st day of this month
2821 nDiff
+= aFrom
.getDaysInMonthRange( aFrom
.nMonth
, aTo
.nMonth
- 1 );
2822 aFrom
.addMonths( aTo
.nMonth
- aFrom
.nMonth
);
2824 // finally add remaining days in this month
2825 nDiff
+= aTo
.nDay
- aFrom
.nDay
;
2826 return nDiff
> 0 ? nDiff
: 0;
2829 sal_Bool
ScaDate::operator<( const ScaDate
& rCmp
) const
2831 if( nYear
!= rCmp
.nYear
)
2832 return nYear
< rCmp
.nYear
;
2833 if( nMonth
!= rCmp
.nMonth
)
2834 return nMonth
< rCmp
.nMonth
;
2835 if( nDay
!= rCmp
.nDay
)
2836 return nDay
< rCmp
.nDay
;
2837 if( bLastDay
|| rCmp
.bLastDay
)
2838 return !bLastDay
&& rCmp
.bLastDay
;
2839 return nOrigDay
< rCmp
.nOrigDay
;
2844 //-----------------------------------------------------------------------------
2846 ScaAnyConverter::ScaAnyConverter( const uno::Reference
< lang::XMultiServiceFactory
>& xServiceFact
) :
2847 bHasValidFormat( sal_False
)
2849 if( xServiceFact
.is() )
2851 uno::Reference
< uno::XInterface
> xInstance
= xServiceFact
->createInstance(
2852 OUString::createFromAscii( "com.sun.star.util.NumberFormatter" ) );
2853 xFormatter
= uno::Reference
< util::XNumberFormatter
>( xInstance
, uno::UNO_QUERY
);
2857 ScaAnyConverter::~ScaAnyConverter()
2861 void ScaAnyConverter::init( const uno::Reference
< beans::XPropertySet
>& xPropSet
) throw( uno::RuntimeException
)
2863 // try to get default number format
2864 bHasValidFormat
= sal_False
;
2865 if( xFormatter
.is() )
2867 // get XFormatsSupplier from outer XPropertySet
2868 uno::Reference
< util::XNumberFormatsSupplier
> xFormatsSupp( xPropSet
, uno::UNO_QUERY
);
2869 if( xFormatsSupp
.is() )
2871 // get XNumberFormatTypes from XNumberFormatsSupplier to get standard index
2872 uno::Reference
< util::XNumberFormats
> xFormats( xFormatsSupp
->getNumberFormats() );
2873 uno::Reference
< util::XNumberFormatTypes
> xFormatTypes( xFormats
, uno::UNO_QUERY
);
2874 if( xFormatTypes
.is() )
2876 lang::Locale eLocale
;
2877 nDefaultFormat
= xFormatTypes
->getStandardIndex( eLocale
);
2878 xFormatter
->attachNumberFormatsSupplier( xFormatsSupp
);
2879 bHasValidFormat
= sal_True
;
2885 double ScaAnyConverter::convertToDouble( const OUString
& rString
) const throw( lang::IllegalArgumentException
)
2887 double fValue
= 0.0;
2888 if( bHasValidFormat
)
2892 fValue
= xFormatter
->convertStringToNumber( nDefaultFormat
, rString
);
2894 catch( uno::Exception
& )
2896 throw lang::IllegalArgumentException();
2901 rtl_math_ConversionStatus eStatus
;
2903 fValue
= ::rtl::math::stringToDouble( rString
, '.', ',', &eStatus
, &nEnd
);
2904 if( (eStatus
!= rtl_math_ConversionStatus_Ok
) || (nEnd
< rString
.getLength()) )
2905 throw lang::IllegalArgumentException();
2910 sal_Bool
ScaAnyConverter::getDouble(
2912 const uno::Any
& rAny
) const throw( lang::IllegalArgumentException
)
2915 sal_Bool bContainsVal
= sal_True
;
2916 switch( rAny
.getValueTypeClass() )
2918 case uno::TypeClass_VOID
:
2919 bContainsVal
= sal_False
;
2921 case uno::TypeClass_DOUBLE
:
2924 case uno::TypeClass_STRING
:
2926 const OUString
* pString
= static_cast< const OUString
* >( rAny
.getValue() );
2927 if( pString
->getLength() )
2928 rfResult
= convertToDouble( *pString
);
2930 bContainsVal
= sal_False
;
2934 throw lang::IllegalArgumentException();
2936 return bContainsVal
;
2939 sal_Bool
ScaAnyConverter::getDouble(
2941 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2942 const uno::Any
& rAny
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2945 return getDouble( rfResult
, rAny
);
2948 double ScaAnyConverter::getDouble(
2949 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2950 const uno::Any
& rAny
,
2951 double fDefault
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2954 if( !getDouble( fResult
, xPropSet
, rAny
) )
2959 sal_Bool
ScaAnyConverter::getInt32(
2960 sal_Int32
& rnResult
,
2961 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2962 const uno::Any
& rAny
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2965 sal_Bool bContainsVal
= getDouble( fResult
, xPropSet
, rAny
);
2966 if( (fResult
<= -2147483649.0) || (fResult
>= 2147483648.0) )
2967 throw lang::IllegalArgumentException();
2969 rnResult
= static_cast< sal_Int32
>( fResult
);
2970 return bContainsVal
;
2973 sal_Int32
ScaAnyConverter::getInt32(
2974 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2975 const uno::Any
& rAny
,
2976 sal_Int32 nDefault
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2979 if( !getInt32( nResult
, xPropSet
, rAny
) )
2986 //-----------------------------------------------------------------------------