1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: analysishelper.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include <com/sun/star/util/XNumberFormatTypes.hpp>
35 #include <tools/resary.hxx>
36 #include <rtl/math.hxx>
37 #include "analysishelper.hxx"
38 #include "analysis.hrc"
40 using namespace ::rtl
;
41 using namespace ::com::sun::star
;
45 #define UNIQUE sal_False // function name does not exist in Calc
46 #define DOUBLE sal_True // function name exists in Calc
48 #define STDPAR sal_False // all parameters are described
49 #define INTPAR sal_True // first parameter is internal
51 #define FUNCDATA( FUNCNAME, DBL, OPT, NUMOFPAR, CAT ) \
52 { "get" #FUNCNAME, ANALYSIS_FUNCNAME_##FUNCNAME, ANALYSIS_##FUNCNAME, DBL, OPT, ANALYSIS_DEFFUNCNAME_##FUNCNAME, NUMOFPAR, CAT }
54 const FuncDataBase pFuncDatas
[] =
56 // UNIQUE or INTPAR or
57 // function name DOUBLE STDPAR # of param category
58 FUNCDATA( Workday
, UNIQUE
, INTPAR
, 3, FDCat_DateTime
),
59 FUNCDATA( Yearfrac
, UNIQUE
, INTPAR
, 3, FDCat_DateTime
),
60 FUNCDATA( Edate
, UNIQUE
, INTPAR
, 2, FDCat_DateTime
),
61 FUNCDATA( Weeknum
, DOUBLE
, INTPAR
, 2, FDCat_DateTime
),
62 FUNCDATA( Eomonth
, UNIQUE
, INTPAR
, 2, FDCat_DateTime
),
63 FUNCDATA( Networkdays
, UNIQUE
, INTPAR
, 3, FDCat_DateTime
),
64 FUNCDATA( Iseven
, DOUBLE
, STDPAR
, 1, FDCat_Inf
),
65 FUNCDATA( Isodd
, DOUBLE
, STDPAR
, 1, FDCat_Inf
),
66 FUNCDATA( Multinomial
, UNIQUE
, STDPAR
, 1, FDCat_Math
),
67 FUNCDATA( Seriessum
, UNIQUE
, STDPAR
, 4, FDCat_Math
),
68 FUNCDATA( Quotient
, UNIQUE
, STDPAR
, 2, FDCat_Math
),
69 FUNCDATA( Mround
, UNIQUE
, STDPAR
, 2, FDCat_Math
),
70 FUNCDATA( Sqrtpi
, UNIQUE
, STDPAR
, 1, FDCat_Math
),
71 FUNCDATA( Randbetween
, UNIQUE
, STDPAR
, 2, FDCat_Math
),
72 FUNCDATA( Gcd
, DOUBLE
, INTPAR
, 1, FDCat_Math
),
73 FUNCDATA( Lcm
, DOUBLE
, INTPAR
, 1, FDCat_Math
),
74 FUNCDATA( Besseli
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
75 FUNCDATA( Besselj
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
76 FUNCDATA( Besselk
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
77 FUNCDATA( Bessely
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
78 FUNCDATA( Bin2Oct
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
79 FUNCDATA( Bin2Dec
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
80 FUNCDATA( Bin2Hex
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
81 FUNCDATA( Oct2Bin
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
82 FUNCDATA( Oct2Dec
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
83 FUNCDATA( Oct2Hex
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
84 FUNCDATA( Dec2Bin
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
85 FUNCDATA( Dec2Hex
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
86 FUNCDATA( Dec2Oct
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
87 FUNCDATA( Hex2Bin
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
88 FUNCDATA( Hex2Dec
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
89 FUNCDATA( Hex2Oct
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
90 FUNCDATA( Delta
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
91 FUNCDATA( Erf
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
92 FUNCDATA( Erfc
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
93 FUNCDATA( Gestep
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
94 FUNCDATA( Factdouble
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
95 FUNCDATA( Imabs
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
96 FUNCDATA( Imaginary
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
97 FUNCDATA( Impower
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
98 FUNCDATA( Imargument
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
99 FUNCDATA( Imcos
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
100 FUNCDATA( Imdiv
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
101 FUNCDATA( Imexp
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
102 FUNCDATA( Imconjugate
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
103 FUNCDATA( Imln
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
104 FUNCDATA( Imlog10
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
105 FUNCDATA( Imlog2
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
106 FUNCDATA( Improduct
, UNIQUE
, INTPAR
, 2, FDCat_Tech
),
107 FUNCDATA( Imreal
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
108 FUNCDATA( Imsin
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
109 FUNCDATA( Imsub
, UNIQUE
, STDPAR
, 2, FDCat_Tech
),
110 FUNCDATA( Imsqrt
, UNIQUE
, STDPAR
, 1, FDCat_Tech
),
111 FUNCDATA( Imsum
, UNIQUE
, INTPAR
, 1, FDCat_Tech
),
112 FUNCDATA( Complex
, UNIQUE
, STDPAR
, 3, FDCat_Tech
),
113 FUNCDATA( Convert
, DOUBLE
, STDPAR
, 3, FDCat_Tech
),
114 FUNCDATA( Amordegrc
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
115 FUNCDATA( Amorlinc
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
116 FUNCDATA( Accrint
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
117 FUNCDATA( Accrintm
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
118 FUNCDATA( Received
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
119 FUNCDATA( Disc
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
120 FUNCDATA( Duration
, DOUBLE
, INTPAR
, 6, FDCat_Finance
),
121 FUNCDATA( Effect
, DOUBLE
, STDPAR
, 2, FDCat_Finance
),
122 FUNCDATA( Cumprinc
, DOUBLE
, STDPAR
, 6, FDCat_Finance
),
123 FUNCDATA( Cumipmt
, DOUBLE
, STDPAR
, 6, FDCat_Finance
),
124 FUNCDATA( Price
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
125 FUNCDATA( Pricedisc
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
126 FUNCDATA( Pricemat
, UNIQUE
, INTPAR
, 6, FDCat_Finance
),
127 FUNCDATA( Mduration
, UNIQUE
, INTPAR
, 6, FDCat_Finance
),
128 FUNCDATA( Nominal
, DOUBLE
, STDPAR
, 2, FDCat_Finance
),
129 FUNCDATA( Dollarfr
, UNIQUE
, STDPAR
, 2, FDCat_Finance
),
130 FUNCDATA( Dollarde
, UNIQUE
, STDPAR
, 2, FDCat_Finance
),
131 FUNCDATA( Yield
, UNIQUE
, INTPAR
, 7, FDCat_Finance
),
132 FUNCDATA( Yielddisc
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
133 FUNCDATA( Yieldmat
, UNIQUE
, INTPAR
, 6, FDCat_Finance
),
134 FUNCDATA( Tbilleq
, UNIQUE
, INTPAR
, 3, FDCat_Finance
),
135 FUNCDATA( Tbillprice
, UNIQUE
, INTPAR
, 3, FDCat_Finance
),
136 FUNCDATA( Tbillyield
, UNIQUE
, INTPAR
, 3, FDCat_Finance
),
137 FUNCDATA( Oddfprice
, UNIQUE
, INTPAR
, 9, FDCat_Finance
),
138 FUNCDATA( Oddfyield
, UNIQUE
, INTPAR
, 9, FDCat_Finance
),
139 FUNCDATA( Oddlprice
, UNIQUE
, INTPAR
, 8, FDCat_Finance
),
140 FUNCDATA( Oddlyield
, UNIQUE
, INTPAR
, 8, FDCat_Finance
),
141 FUNCDATA( Xirr
, UNIQUE
, INTPAR
, 3, FDCat_Finance
),
142 FUNCDATA( Xnpv
, UNIQUE
, STDPAR
, 3, FDCat_Finance
),
143 FUNCDATA( Intrate
, UNIQUE
, INTPAR
, 5, FDCat_Finance
),
144 FUNCDATA( Coupncd
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
145 FUNCDATA( Coupdays
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
146 FUNCDATA( Coupdaysnc
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
147 FUNCDATA( Coupdaybs
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
148 FUNCDATA( Couppcd
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
149 FUNCDATA( Coupnum
, UNIQUE
, INTPAR
, 4, FDCat_Finance
),
150 FUNCDATA( Fvschedule
, UNIQUE
, STDPAR
, 2, FDCat_Finance
)
155 sal_uInt16
DaysInMonth( sal_uInt16 nMonth
, sal_uInt16 nYear
)
157 if( (nMonth
== 2) && IsLeapYear( nYear
) )
159 static const sal_uInt16 aDaysInMonth
[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
160 return aDaysInMonth
[ nMonth
];
165 * Convert a date to a count of days starting from 01/01/0001
167 * The internal representation of a Date used in this Addin
168 * is the number of days between 01/01/0001 and the date
169 * this function converts a Day , Month, Year representation
170 * to this internal Date value.
174 sal_Int32
DateToDays( sal_uInt16 nDay
, sal_uInt16 nMonth
, sal_uInt16 nYear
)
176 sal_Int32 nDays
= ((sal_Int32
)nYear
-1) * 365;
177 nDays
+= ((nYear
-1) / 4) - ((nYear
-1) / 100) + ((nYear
-1) / 400);
179 for( sal_uInt16 i
= 1; i
< nMonth
; i
++ )
180 nDays
+= DaysInMonth(i
,nYear
);
188 * Convert a count of days starting from 01/01/0001 to a date
190 * The internal representation of a Date used in this Addin
191 * is the number of days between 01/01/0001 and the date
192 * this function converts this internal Date value
193 * to a Day , Month, Year representation of a Date.
197 void DaysToDate( sal_Int32 nDays
, sal_uInt16
& rDay
, sal_uInt16
& rMonth
, sal_uInt16
& rYear
)
198 throw( lang::IllegalArgumentException
)
201 throw lang::IllegalArgumentException();
210 rYear
= (sal_uInt16
)((nTempDays
/ 365) - i
);
211 nTempDays
-= ((sal_Int32
) rYear
-1) * 365;
212 nTempDays
-= (( rYear
-1) / 4) - (( rYear
-1) / 100) + ((rYear
-1) / 400);
221 if ( nTempDays
> 365 )
223 if ( (nTempDays
!= 366) || !IsLeapYear( rYear
) )
234 while ( (sal_Int32
)nTempDays
> DaysInMonth( rMonth
, rYear
) )
236 nTempDays
-= DaysInMonth( rMonth
, rYear
);
239 rDay
= (sal_uInt16
)nTempDays
;
244 * Get the null date used by the spreadsheet document
246 * The internal representation of a Date used in this Addin
247 * is the number of days between 01/01/0001 and the date
248 * this function returns this internal Date value for the document null date
252 sal_Int32
GetNullDate( constREFXPS
& xOpt
) THROWDEF_RTE
258 ANY aAny
= xOpt
->getPropertyValue( STRFROMASCII( "NullDate" ) );
261 return DateToDays( aDate
.Day
, aDate
.Month
, aDate
.Year
);
263 catch( uno::Exception
& )
268 // no null date available -> no calculations possible
269 throw uno::RuntimeException();
273 sal_Int32
GetDiffDate360(
274 sal_uInt16 nDay1
, sal_uInt16 nMonth1
, sal_uInt16 nYear1
, sal_Bool bLeapYear1
,
275 sal_uInt16 nDay2
, sal_uInt16 nMonth2
, sal_uInt16 nYear2
,
276 sal_Bool bUSAMethod
)
280 else if( bUSAMethod
&& ( nMonth1
== 2 && ( nDay1
== 29 || ( nDay1
== 28 && !bLeapYear1
) ) ) )
285 if( bUSAMethod
&& nDay1
!= 30 )
287 //aDate2 += 1; -> 1.xx.yyyy
301 return nDay2
+ nMonth2
* 30 + nYear2
* 360 - nDay1
- nMonth1
* 30 - nYear1
* 360;
305 sal_Int32
GetDiffDate360( sal_Int32 nNullDate
, sal_Int32 nDate1
, sal_Int32 nDate2
, sal_Bool bUSAMethod
)
310 sal_uInt16 nDay1
, nMonth1
, nYear1
, nDay2
, nMonth2
, nYear2
;
312 DaysToDate( nDate1
, nDay1
, nMonth1
, nYear1
);
313 DaysToDate( nDate2
, nDay2
, nMonth2
, nYear2
);
315 return GetDiffDate360( nDay1
, nMonth1
, nYear1
, IsLeapYear( nYear1
), nDay2
, nMonth2
, nYear2
, bUSAMethod
);
319 sal_Int32
GetDaysInYears( sal_uInt16 nYear1
, sal_uInt16 nYear2
)
321 sal_uInt16 nLeaps
= 0;
322 for( sal_uInt16 n
= nYear1
; n
<= nYear2
; n
++ )
324 if( IsLeapYear( n
) )
338 void GetDiffParam( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
,
339 sal_uInt16
& rYears
, sal_Int32
& rDayDiffPart
, sal_Int32
& rDaysInYear
) THROWDEF_RTE_IAE
341 if( nStartDate
> nEndDate
)
343 sal_Int32 n
= nEndDate
;
344 nEndDate
= nStartDate
;
348 sal_Int32 nDate1
= nStartDate
+ nNullDate
;
349 sal_Int32 nDate2
= nEndDate
+ nNullDate
;
351 sal_uInt16 nDay1
, nDay2
;
352 sal_uInt16 nMonth1
, nMonth2
;
353 sal_uInt16 nYear1
, nYear2
;
355 DaysToDate( nDate1
, nDay1
, nMonth1
, nYear1
);
356 DaysToDate( nDate2
, nDay2
, nMonth2
, nYear2
);
360 sal_Int32 nDayDiff
, nDaysInYear
;
364 case 0: // 0=USA (NASD) 30/360
365 case 4: // 4=Europe 30/360
367 nYears
= nYear2
- nYear1
;
368 nDayDiff
= GetDiffDate360( nDay1
, nMonth1
, nYear1
, IsLeapYear( nYear1
),
369 nDay2
, nMonth2
, nYear2
, nMode
== 0 ) - nYears
* nDaysInYear
;
371 case 1: // 1=exact/exact
372 nYears
= nYear2
- nYear1
;
374 nDaysInYear
= IsLeapYear( nYear1
)? 366 : 365;
376 if( nYears
&& ( nMonth1
> nMonth2
|| ( nMonth1
== nMonth2
&& nDay1
> nDay2
) ) )
380 nDayDiff
= nDate2
- DateToDays( nDay1
, nMonth1
, nYear2
);
382 nDayDiff
= nDate2
- nDate1
;
385 nDayDiff
+= nDaysInYear
;
388 case 2: // 2=exact/360
390 nYears
= sal_uInt16( ( nDate2
- nDate1
) / nDaysInYear
);
391 nDayDiff
= nDate2
- nDate1
;
392 nDayDiff
%= nDaysInYear
;
394 case 3: //3=exact/365
396 nYears
= sal_uInt16( ( nDate2
- nDate1
) / nDaysInYear
);
397 nDayDiff
= nDate2
- nDate1
;
398 nDayDiff
%= nDaysInYear
;
405 rDayDiffPart
= nDayDiff
;
406 rDaysInYear
= nDaysInYear
;
410 sal_Int32
GetDiffDate( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
,
411 sal_Int32
* pOptDaysIn1stYear
) THROWDEF_RTE_IAE
413 sal_Bool bNeg
= nStartDate
> nEndDate
;
417 sal_Int32 n
= nEndDate
;
418 nEndDate
= nStartDate
;
426 case 0: // 0=USA (NASD) 30/360
427 case 4: // 4=Europe 30/360
429 sal_uInt16 nD1
, nM1
, nY1
, nD2
, nM2
, nY2
;
431 nStartDate
+= nNullDate
;
432 nEndDate
+= nNullDate
;
434 DaysToDate( nStartDate
, nD1
, nM1
, nY1
);
435 DaysToDate( nEndDate
, nD2
, nM2
, nY2
);
437 sal_Bool bLeap
= IsLeapYear( nY1
);
438 sal_Int32 nDays
, nMonths
/*, nYears*/;
443 nMonths
+= ( nY2
- nY1
) * 12;
445 nRet
= nMonths
* 30 + nDays
;
446 if( nMode
== 0 && nM1
== 2 && nM2
!= 2 && nY1
== nY2
)
447 nRet
-= bLeap
? 1 : 2;
449 if( pOptDaysIn1stYear
)
450 *pOptDaysIn1stYear
= 360;
453 case 1: // 1=exact/exact
454 if( pOptDaysIn1stYear
)
456 sal_uInt16 nD
, nM
, nY
;
458 DaysToDate( nStartDate
+ nNullDate
, nD
, nM
, nY
);
460 *pOptDaysIn1stYear
= IsLeapYear( nY
)? 366 : 365;
462 nRet
= nEndDate
- nStartDate
;
464 case 2: // 2=exact/360
465 nRet
= nEndDate
- nStartDate
;
466 if( pOptDaysIn1stYear
)
467 *pOptDaysIn1stYear
= 360;
469 case 3: //3=exact/365
470 nRet
= nEndDate
- nStartDate
;
471 if( pOptDaysIn1stYear
)
472 *pOptDaysIn1stYear
= 365;
478 return bNeg
? -nRet
: nRet
;
482 double GetYearDiff( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
) THROWDEF_RTE_IAE
484 sal_Int32 nDays1stYear
;
485 sal_Int32 nTotalDays
= GetDiffDate( nNullDate
, nStartDate
, nEndDate
, nMode
, &nDays1stYear
);
487 return double( nTotalDays
) / double( nDays1stYear
);
491 sal_Int32
GetDaysInYear( sal_Int32 nNullDate
, sal_Int32 nDate
, sal_Int32 nMode
) THROWDEF_RTE_IAE
495 case 0: // 0=USA (NASD) 30/360
496 case 2: // 2=exact/360
497 case 4: // 4=Europe 30/360
499 case 1: // 1=exact/exact
501 sal_uInt16 nD
, nM
, nY
;
503 DaysToDate( nDate
, nD
, nM
, nY
);
504 return IsLeapYear( nY
)? 366 : 365;
506 case 3: //3=exact/365
514 double GetYearFrac( sal_Int32 nNullDate
, sal_Int32 nStartDate
, sal_Int32 nEndDate
, sal_Int32 nMode
) THROWDEF_RTE_IAE
516 if( nStartDate
== nEndDate
)
517 return 0.0; // nothing to do...
520 sal_Int32 nDayDiff
, nDaysInYear
;
522 GetDiffParam( nNullDate
, nStartDate
, nEndDate
, nMode
, nYears
, nDayDiff
, nDaysInYear
);
524 return double( nYears
) + double( nDayDiff
) / double( nDaysInYear
);
528 double Fak( sal_Int32 n
)
550 double GetGcd( double f1
, double f2
)
552 double f
= fmod( f1
, f2
);
564 double ConvertToDec( const STRING
& aStr
, sal_uInt16 nBase
, sal_uInt16 nCharLim
) THROWDEF_RTE_IAE
566 if ( nBase
< 2 || nBase
> 36 )
569 sal_uInt32 nStrLen
= aStr
.getLength();
570 if( nStrLen
> nCharLim
)
577 register const sal_Unicode
* p
= aStr
.getStr();
579 sal_uInt16 nFirstDig
= 0;
580 sal_Bool bFirstDig
= sal_True
;
581 double fBase
= nBase
;
587 if( '0' <= *p
&& *p
<= '9' )
589 else if( 'A' <= *p
&& *p
<= 'Z' )
590 n
= 10 + ( *p
- 'A' );
591 else if ( 'a' <= *p
&& *p
<= 'z' )
592 n
= 10 + ( *p
- 'a' );
600 bFirstDig
= sal_False
;
603 fVal
= fVal
* fBase
+ double( n
);
613 if( nStrLen
== nCharLim
&& !bFirstDig
&& (nFirstDig
>= nBase
/ 2) )
614 { // handling negativ values
615 fVal
= ( pow( double( nBase
), double( nCharLim
) ) - fVal
); // complement
623 static inline sal_Char
GetMaxChar( sal_uInt16 nBase
)
625 const sal_Char
* c
= "--123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
630 STRING
ConvertFromDec( double fNum
, double fMin
, double fMax
, sal_uInt16 nBase
,
631 sal_Int32 nPlaces
, sal_Int32 nMaxPlaces
, sal_Bool bUsePlaces
) THROWDEF_RTE_IAE
633 fNum
= ::rtl::math::approxFloor( fNum
);
634 fMin
= ::rtl::math::approxFloor( fMin
);
635 fMax
= ::rtl::math::approxFloor( fMax
);
637 if( fNum
< fMin
|| fNum
> fMax
|| ( bUsePlaces
&& ( nPlaces
<= 0 || nPlaces
> nMaxPlaces
) ) )
640 sal_Int64 nNum
= static_cast< sal_Int64
>( fNum
);
641 sal_Bool bNeg
= nNum
< 0;
643 nNum
= sal_Int64( pow( double( nBase
), double( nMaxPlaces
) ) ) + nNum
;
645 STRING
aRet( STRING::valueOf( nNum
, nBase
).toAsciiUpperCase() );
650 sal_Int32 nLen
= aRet
.getLength();
651 if( !bNeg
&& nLen
> nPlaces
)
655 else if( ( bNeg
&& nLen
< nMaxPlaces
) || ( !bNeg
&& nLen
< nPlaces
) )
657 sal_Int32 nLeft
= nPlaces
- nLen
;
658 sal_Char
* p
= new sal_Char
[ nLeft
+ 1 ];
659 memset( p
, bNeg
? GetMaxChar( nBase
) : '0', nLeft
);
661 STRING
aTmp( p
, nLeft
, RTL_TEXTENCODING_MS_1252
);
672 // implementation moved to module sal, see #i97091#
673 double Erf( double x
)
675 return ::rtl::math::erf(x
);
678 // implementation moved to module sal, see #i97091#
679 double Erfc( double x
)
681 return ::rtl::math::erfc(x
);
684 inline sal_Bool
IsNum( sal_Unicode c
)
686 return c
>= '0' && c
<= '9';
690 inline sal_Bool
IsComma( sal_Unicode c
)
692 return c
== '.' || c
== ',';
696 inline sal_Bool
IsExpStart( sal_Unicode c
)
698 return c
== 'e' || c
== 'E';
702 inline sal_Bool
IsImagUnit( sal_Unicode c
)
704 return c
== 'i' || c
== 'j';
708 inline sal_uInt16
GetVal( sal_Unicode c
)
710 return sal_uInt16( c
- '0' );
714 sal_Bool
ParseDouble( const sal_Unicode
*& rp
, double& rRet
)
718 double fMult
= 0.1; // multiplier to multiply digits with, when adding fractional ones
720 sal_Int32 nMaxExp
= 307;
721 sal_uInt16 nDigCnt
= 18; // max. number of digits to read in, rest doesn't matter
723 enum State
{ S_End
= 0, S_Sign
, S_IntStart
, S_Int
, S_IgnoreIntDigs
, S_Frac
, S_IgnoreFracDigs
, S_ExpSign
, S_Exp
};
727 sal_Bool bNegNum
= sal_False
;
728 sal_Bool bNegExp
= sal_False
;
730 const sal_Unicode
* p
= rp
;
752 else if( IsComma( c
) )
764 else if( IsComma( c
) )
766 else if( IsImagUnit( c
) )
778 fInt
+= double( GetVal( c
) );
781 eS
= S_IgnoreIntDigs
;
783 else if( IsComma( c
) )
785 else if( IsExpStart( c
) )
790 case S_IgnoreIntDigs
:
792 nExp
++; // just multiply num with 10... ;-)
793 else if( IsComma( c
) )
795 else if( IsExpStart( c
) )
803 fFrac
+= double( GetVal( c
) ) * fMult
;
808 eS
= S_IgnoreFracDigs
;
810 else if( IsExpStart( c
) )
815 case S_IgnoreFracDigs
:
816 if( IsExpStart( c
) )
818 else if( !IsNum( c
) )
846 case S_End
: // to avoid compiler warning
847 break; // loop exits anyway
853 p
--; // set pointer back to last
857 sal_Int32 nLog10
= sal_Int32( log10( fInt
) );
862 if( nLog10
+ nExp
> nMaxExp
)
865 fInt
= ::rtl::math::pow10Exp( fInt
, nExp
);
876 STRING
GetString( double f
, sal_Bool bLeadingSign
, sal_uInt16 nMaxDig
)
878 const int nBuff
= 256;
879 sal_Char aBuff
[ nBuff
+ 1 ];
880 const char* pFormStr
= bLeadingSign
? "%+.*g" : "%.*g";
881 int nLen
= snprintf( aBuff
, nBuff
, pFormStr
, int( nMaxDig
), f
);
882 // you never know which underlying implementation you get ...
884 if ( nLen
< 0 || nLen
> nBuff
)
885 nLen
= strlen( aBuff
);
887 STRING
aRet( aBuff
, nLen
, RTL_TEXTENCODING_MS_1252
);
893 double GetAmordegrc( sal_Int32 nNullDate
, double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
,
894 double fRestVal
, double fPer
, double fRate
, sal_Int32 nBase
) THROWDEF_RTE_IAE
899 sal_uInt32 nPer
= sal_uInt32( fPer
);
900 double fUsePer
= 1.0 / fRate
;
905 else if( fUsePer
< 5.0 )
907 else if( fUsePer
<= 6.0 )
913 double fNRate
= ::rtl::math::round( GetYearFrac( nNullDate
, nDate
, nFirstPer
, nBase
) * fRate
* fCost
, 0 );
915 double fRest
= fCost
- fRestVal
; // Anschaffungskosten - Restwert - Summe aller Abschreibungen
917 for( sal_uInt32 n
= 0 ; n
< nPer
; n
++ )
919 fNRate
= ::rtl::math::round( fRate
* fCost
, 0 );
928 return ::rtl::math::round( fCost
* 0.5, 0 );
941 double GetAmorlinc( sal_Int32 nNullDate
, double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
,
942 double fRestVal
, double fPer
, double fRate
, sal_Int32 nBase
) THROWDEF_RTE_IAE
947 sal_uInt32 nPer
= sal_uInt32( fPer
);
948 double fOneRate
= fCost
* fRate
;
949 double fCostDelta
= fCost
- fRestVal
;
950 double f0Rate
= GetYearFrac( nNullDate
, nDate
, nFirstPer
, nBase
) * fRate
* fCost
;
951 sal_uInt32 nNumOfFullPeriods
= sal_uInt32( ( fCost
- fRestVal
- f0Rate
) / fOneRate
);
955 else if( nPer
<= nNumOfFullPeriods
)
957 else if( nPer
== nNumOfFullPeriods
+ 1 )
958 return fCostDelta
- fOneRate
* nNumOfFullPeriods
- f0Rate
;
964 double GetDuration( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
,
965 double fYield
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
967 double fYearfrac
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
);
968 double fNumOfCoups
= GetCoupnum( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
970 const double f100
= 100.0;
971 fCoup
*= f100
/ double( nFreq
); // fCoup is used as cash flow
975 double nDiff
= fYearfrac
* nFreq
- fNumOfCoups
;
979 for( t
= 1.0 ; t
< fNumOfCoups
; t
++ )
980 fDur
+= ( t
+ nDiff
) * ( fCoup
) / pow( fYield
, t
+ nDiff
);
982 fDur
+= ( fNumOfCoups
+ nDiff
) * ( fCoup
+ f100
) / pow( fYield
, fNumOfCoups
+ nDiff
);
985 for( t
= 1.0 ; t
< fNumOfCoups
; t
++ )
986 p
+= fCoup
/ pow( fYield
, t
+ nDiff
);
988 p
+= ( fCoup
+ f100
) / pow( fYield
, fNumOfCoups
+ nDiff
);
991 fDur
/= double( nFreq
);
997 double GetYieldmat( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nIssue
,
998 double fRate
, double fPrice
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1000 double fIssMat
= GetYearFrac( nNullDate
, nIssue
, nMat
, nBase
);
1001 double fIssSet
= GetYearFrac( nNullDate
, nIssue
, nSettle
, nBase
);
1002 double fSetMat
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
);
1004 double y
= 1.0 + fIssMat
* fRate
;
1005 y
/= fPrice
/ 100.0 + fIssSet
* fRate
;
1013 double GetOddfprice( sal_Int32
/*nNullDate*/, sal_Int32
/*nSettle*/, sal_Int32
/*nMat*/, sal_Int32
/*nIssue*/,
1014 sal_Int32
/*nFirstCoup*/, double /*fRate*/, double /*fYield*/, double /*fRedemp*/, sal_Int32
/*nFreq*/,
1015 sal_Int32
/*nBase*/ ) THROWDEF_RTE_IAE
1017 THROW_RTE
; // #87380#
1019 double fN = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase ) - 1.0;
1020 double fNq = GetCoupnum( nNullDate, nSettle, nFirstCoup, nFreq, nBase ) - 1.0;
1021 double fDSC = GetCoupdaysnc( nNullDate, nSettle, nFirstCoup, nFreq, nBase );
1022 double fDSC_E = fDSC / GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase );
1023 double fNC = GetCoupnum( nNullDate, nIssue, nFirstCoup, nFreq, nBase );
1024 sal_uInt32 nNC = sal_uInt32( fNC );
1025 sal_uInt16 nMonthDelta = 12 / sal_uInt16( nFreq );
1028 double f1YieldFreq = 1.0 + fYield / double( nFreq );
1029 double f100RateFreq = 100.0 * fRate / double( nFreq );
1031 double* pDC = new double[ nNC + 1 ];
1032 double* pNL = new double[ nNC + 1 ];
1033 double* pA = new double[ nNC + 1 ];
1035 pDC[ 0 ] = pNL[ 0 ] = pA[ 0 ] = 1.0;
1037 ScaDate aStartDate( nNullDate, nSettle, nBase );
1038 ScaDate aNextCoup( nNullDate, nFirstCoup, nBase );
1041 pDC[ 1 ] = ScaDate::GetDiff( aStartDate, aNextCoup );
1042 pNL[ 1 ] = GetCoupdays( nNullDate, nSettle, nFirstCoup, nFreq, nBase );
1045 for( i = 1 ; i <= nNC ; i++ )
1048 aStartDate.addMonths( nMonthDelta );
1049 aNextCoup.addMonths( nMonthDelta );
1050 pDC[ i ] = ScaDate::GetDiff( aPre, aStartDate );
1051 pNL[ i ] = GetCoupdays( nNullDate, aStartDate.GetDate( nNullDate ), aNextCoup.GetDate( nNullDate ),
1053 pA[ i ] = ScaDate::GetDiff( aStartDate, aNextCoup );
1057 double fT1 = fRedemp / pow( f1YieldFreq, fN + fNq + fDSC_E );
1060 for( i = 1 ; i <= nNC ; i++ )
1061 fT2 += pDC[ i ] / pNL[ i ];
1062 fT2 *= f100RateFreq / pow( f1YieldFreq, fNq + fDSC_E );
1065 for( double k = 2.0 ; k <= fN ; k++ )
1066 fT3 += 1.0 / pow( f1YieldFreq, k - fNq + fDSC_E );
1067 fT3 *= f100RateFreq;
1070 for( i = 1 ; i <= nNC ; i++ )
1071 fT4 += pA[ i ] / pNL[ i ];
1072 fT4 *= f100RateFreq;
1081 return fT1 + fT2 + fT3 - fT4;
1086 double getYield_( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
, double fPrice
,
1087 double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1089 double fRate
= fCoup
;
1090 double fPriceN
= 0.0;
1091 double fYield1
= 0.0;
1092 double fYield2
= 1.0;
1093 double fPrice1
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield1
, fRedemp
, nFreq
, nBase
);
1094 double fPrice2
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield2
, fRedemp
, nFreq
, nBase
);
1095 double fYieldN
= ( fYield2
- fYield1
) * 0.5;
1097 for( sal_uInt32 nIter
= 0 ; nIter
< 100 && fPriceN
!= fPrice
; nIter
++ )
1099 fPriceN
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYieldN
, fRedemp
, nFreq
, nBase
);
1101 if( fPrice
== fPrice1
)
1103 else if( fPrice
== fPrice2
)
1105 else if( fPrice
== fPriceN
)
1107 else if( fPrice
< fPrice2
)
1110 fPrice2
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield2
, fRedemp
, nFreq
, nBase
);
1112 fYieldN
= ( fYield2
- fYield1
) * 0.5;
1116 if( fPrice
< fPriceN
)
1127 fYieldN
= fYield2
- ( fYield2
- fYield1
) * ( ( fPrice
- fPrice2
) / ( fPrice1
- fPrice2
) );
1131 if( fabs( fPrice
- fPriceN
) > fPrice
/ 100.0 )
1132 THROW_IAE
; // result not precise enough
1138 double getPrice_( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fRate
, double fYield
,
1139 double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1141 double fFreq
= nFreq
;
1143 double fE
= GetCoupdays( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1144 double fDSC_E
= GetCoupdaysnc( nNullDate
, nSettle
, nMat
, nFreq
, nBase
) / fE
;
1145 double fN
= GetCoupnum( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1146 double fA
= GetCoupdaybs( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1148 double fRet
= fRedemp
/ ( pow( 1.0 + fYield
/ fFreq
, fN
- 1.0 + fDSC_E
) );
1149 fRet
-= 100.0 * fRate
/ fFreq
* fA
/ fE
;
1151 double fT1
= 100.0 * fRate
/ fFreq
;
1152 double fT2
= 1.0 + fYield
/ fFreq
;
1154 for( double fK
= 0.0 ; fK
< fN
; fK
++ )
1155 fRet
+= fT1
/ pow( fT2
, fK
+ fDSC_E
);
1161 double GetOddfyield( sal_Int32
/*nNullDate*/, sal_Int32
/*nSettle*/, sal_Int32
/*nMat*/, sal_Int32
/*nIssue*/,
1162 sal_Int32
/*nFirstCoup*/, double /*fRate*/, double /*fPrice*/, double /*fRedemp*/, sal_Int32
/*nFreq*/,
1163 sal_Int32
/*nBase*/ ) THROWDEF_RTE_IAE
1165 THROW_RTE
; // #87380#
1167 //GetOddfprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue,
1168 //sal_Int32 nFirstCoup, double fRate, double fYield, double fRedemp, sal_Int32 nFreq,
1170 double fPriceN = 0.0;
1171 double fYield1 = 0.0;
1172 double fYield2 = 1.0;
1173 double fPrice1 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield1, fRedemp, nFreq, nBase );
1174 double fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase );
1175 double fYieldN = ( fYield2 - fYield1 ) * 0.5;
1177 for( sal_uInt32 nIter = 0 ; nIter < 100 && fPriceN != fPrice ; nIter++ )
1179 fPriceN = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYieldN, fRedemp, nFreq, nBase );
1181 if( fPrice == fPrice1 )
1183 else if( fPrice == fPrice2 )
1185 else if( fPrice == fPriceN )
1187 else if( fPrice < fPrice2 )
1190 fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase );
1192 fYieldN = ( fYield2 - fYield1 ) * 0.5;
1196 if( fPrice < fPriceN )
1207 fYieldN = fYield2 - ( fYield2 - fYield1 ) * ( ( fPrice - fPrice2 ) / ( fPrice1 - fPrice2 ) );
1211 if( fabs( fPrice - fPriceN ) > fPrice / 100.0 )
1212 THROW_IAE; // result not precise enough
1219 double GetOddlprice( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastCoup
,
1220 double fRate
, double fYield
, double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1222 double fFreq
= double( nFreq
);
1223 double fDCi
= GetYearFrac( nNullDate
, nLastCoup
, nMat
, nBase
) * fFreq
;
1224 double fDSCi
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
) * fFreq
;
1225 double fAi
= GetYearFrac( nNullDate
, nLastCoup
, nSettle
, nBase
) * fFreq
;
1227 double p
= fRedemp
+ fDCi
* 100.0 * fRate
/ fFreq
;
1228 p
/= fDSCi
* fYield
/ fFreq
+ 1.0;
1229 p
-= fAi
* 100.0 * fRate
/ fFreq
;
1235 double GetOddlyield( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastCoup
,
1236 double fRate
, double fPrice
, double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1238 double fFreq
= double( nFreq
);
1239 double fDCi
= GetYearFrac( nNullDate
, nLastCoup
, nMat
, nBase
) * fFreq
;
1240 double fDSCi
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
) * fFreq
;
1241 double fAi
= GetYearFrac( nNullDate
, nLastCoup
, nSettle
, nBase
) * fFreq
;
1243 double y
= fRedemp
+ fDCi
* 100.0 * fRate
/ fFreq
;
1244 y
/= fPrice
+ fAi
* 100.0 * fRate
/ fFreq
;
1252 double GetRmz( double fZins
, double fZzr
, double fBw
, double fZw
, sal_Int32 nF
)
1256 fRmz
= ( fBw
+ fZw
) / fZzr
;
1259 double fTerm
= pow( 1.0 + fZins
, fZzr
);
1261 fRmz
= ( fZw
* fZins
/ ( fTerm
- 1.0 ) + fBw
* fZins
/ ( 1.0 - 1.0 / fTerm
) ) / ( 1.0 + fZins
);
1263 fRmz
= fZw
* fZins
/ ( fTerm
- 1.0 ) + fBw
* fZins
/ ( 1.0 - 1.0 / fTerm
);
1270 double GetZw( double fZins
, double fZzr
, double fRmz
, double fBw
, sal_Int32 nF
)
1274 fZw
= fBw
+ fRmz
* fZzr
;
1277 double fTerm
= pow( 1.0 + fZins
, fZzr
);
1279 fZw
= fBw
* fTerm
+ fRmz
* ( 1.0 + fZins
) * ( fTerm
- 1.0 ) / fZins
;
1281 fZw
= fBw
* fTerm
+ fRmz
* ( fTerm
- 1.0 ) / fZins
;
1288 /*double TBillYield( constREFXPS& xOpt, sal_Int32 nSettle, sal_Int32 nMat, double fPrice ) THROWDEF_RTE_IAE
1290 sal_Int32 nDiff = GetDiffDate360( xOpt, nSettle, nMat, sal_True );
1292 if( fPrice <= 0.0 || nSettle >= nMat || nDiff > 360 )
1295 double fRet = 100.0;
1298 fRet *= double( nDiff );
1305 //-----------------------------------------------------------------------------
1306 // financial functions COUP***
1310 // COUPPCD: find last coupon date before settlement (can be equal to settlement)
1311 void lcl_GetCouppcd( ScaDate
& rDate
, const ScaDate
& rSettle
, const ScaDate
& rMat
, sal_Int32 nFreq
)
1312 throw( lang::IllegalArgumentException
)
1315 rDate
.setYear( rSettle
.getYear() );
1316 if( rDate
< rSettle
)
1317 rDate
.addYears( 1 );
1318 while( rDate
> rSettle
)
1319 rDate
.addMonths( -12 / nFreq
);
1322 double GetCouppcd( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1325 if( nSettle
>= nMat
|| CHK_Freq
)
1329 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1330 return aDate
.getDate( nNullDate
);
1335 // COUPNCD: find first coupon date after settlement (is never equal to settlement)
1336 void lcl_GetCoupncd( ScaDate
& rDate
, const ScaDate
& rSettle
, const ScaDate
& rMat
, sal_Int32 nFreq
)
1337 throw( lang::IllegalArgumentException
)
1340 rDate
.setYear( rSettle
.getYear() );
1341 if( rDate
> rSettle
)
1342 rDate
.addYears( -1 );
1343 while( rDate
<= rSettle
)
1344 rDate
.addMonths( 12 / nFreq
);
1347 double GetCoupncd( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1350 if( nSettle
>= nMat
|| CHK_Freq
)
1354 lcl_GetCoupncd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1355 return aDate
.getDate( nNullDate
);
1360 // COUPDAYBS: get day count: coupon date before settlement <-> settlement
1361 double GetCoupdaybs( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1364 if( nSettle
>= nMat
|| CHK_Freq
)
1367 ScaDate
aSettle( nNullDate
, nSettle
, nBase
);
1369 lcl_GetCouppcd( aDate
, aSettle
, ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1370 return ScaDate::getDiff( aDate
, aSettle
);
1375 // COUPDAYSNC: get day count: settlement <-> coupon date after settlement
1376 double GetCoupdaysnc( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1379 if( nSettle
>= nMat
|| CHK_Freq
)
1382 if( (nBase
!= 0) && (nBase
!= 4) )
1384 ScaDate
aSettle( nNullDate
, nSettle
, nBase
);
1386 lcl_GetCoupncd( aDate
, aSettle
, ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1387 return ScaDate::getDiff( aSettle
, aDate
);
1389 return GetCoupdays( nNullDate
, nSettle
, nMat
, nFreq
, nBase
) - GetCoupdaybs( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1394 // COUPDAYS: get day count: coupon date before settlement <-> coupon date after settlement
1395 double GetCoupdays( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1398 if( nSettle
>= nMat
|| CHK_Freq
)
1404 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1405 ScaDate
aNextDate( aDate
);
1406 aNextDate
.addMonths( 12 / nFreq
);
1407 return ScaDate::getDiff( aDate
, aNextDate
);
1409 return static_cast< double >( GetDaysInYear( 0, 0, nBase
) ) / nFreq
;
1414 // COUPNUM: get count of coupon dates
1415 double GetCoupnum( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1418 if( nSettle
>= nMat
|| CHK_Freq
)
1421 ScaDate
aMat( nNullDate
, nMat
, nBase
);
1423 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), aMat
, nFreq
);
1424 sal_uInt16 nMonths
= (aMat
.getYear() - aDate
.getYear()) * 12 + aMat
.getMonth() - aDate
.getMonth();
1425 return static_cast< double >( nMonths
* nFreq
/ 12 );
1434 const sal_uInt32
MyList::nStartSize
= 16;
1435 const sal_uInt32
MyList::nIncrSize
= 16;
1438 void MyList::_Grow( void )
1442 void** pNewData
= new void*[ nSize
];
1443 memcpy( pNewData
, pData
, nNew
* sizeof( void* ) );
1450 MyList::MyList( void )
1453 pData
= new void*[ nSize
];
1464 void MyList::Insert( void* p
, sal_uInt32 n
)
1472 void** pIns
= pData
+ n
;
1473 memmove( pIns
+ 1, pIns
, ( nNew
- n
) * sizeof( void* ) );
1484 StringList::~StringList()
1486 for( STRING
* p
= ( STRING
* ) First() ; p
; p
= ( STRING
* ) Next() )
1491 class AnalysisRscStrArrLoader
: public Resource
1494 ResStringArray aStrArray
;
1496 AnalysisRscStrArrLoader( sal_uInt16 nRsc
, sal_uInt16 nArrayId
, ResMgr
& rResMgr
) :
1497 Resource( AnalysisResId( nRsc
, rResMgr
) ),
1498 aStrArray( AnalysisResId( nArrayId
, rResMgr
) )
1503 const ResStringArray
& GetStringArray() const { return aStrArray
; }
1509 FuncData::FuncData( const FuncDataBase
& r
, ResMgr
& rResMgr
) :
1510 aIntName( OUString::createFromAscii( r
.pIntName
) ),
1511 nUINameID( r
.nUINameID
),
1512 nDescrID( r
.nDescrID
),
1513 bDouble( r
.bDouble
),
1514 bWithOpt( r
.bWithOpt
),
1515 nParam( r
.nNumOfParams
),
1516 nCompID( r
.nCompListID
),
1519 AnalysisRscStrArrLoader
aArrLoader( RID_ANALYSIS_DEFFUNCTION_NAMES
, nCompID
, rResMgr
);
1520 // ResStringArray aDefFuncNameArray( AnalysisResId( nCompID, rResMgr ) );
1521 const ResStringArray
& rArr
= aArrLoader
.GetStringArray();
1523 sal_uInt16 nCount
= sal::static_int_cast
<sal_uInt16
>( rArr
.Count() );
1526 for( n
= 0 ; n
< nCount
; n
++ )
1527 aCompList
.Append( rArr
.GetString( n
) );
1531 FuncData::~FuncData()
1536 sal_uInt16
FuncData::GetStrIndex( sal_uInt16 nParamNum
) const
1541 if( nParamNum
> nParam
)
1544 return nParamNum
* 2;
1550 FuncDataList::FuncDataList( ResMgr
& rResMgr
)
1552 const sal_uInt32 nNum
= sizeof( pFuncDatas
) / sizeof( FuncDataBase
);
1554 for( sal_uInt16 n
= 0 ; n
< nNum
; n
++ )
1555 Append( new FuncData( pFuncDatas
[ n
], rResMgr
) );
1559 FuncDataList::~FuncDataList()
1561 for( FuncData
* p
= ( FuncData
* ) First() ; p
; p
= ( FuncData
* ) Next() )
1566 const FuncData
* FuncDataList::Get( const OUString
& aProgrammaticName
) const
1568 if( aLastName
== aProgrammaticName
)
1569 return Get( nLast
);
1571 ( ( FuncDataList
* ) this )->aLastName
= aProgrammaticName
;
1573 sal_uInt32 nE
= Count();
1574 for( sal_uInt32 n
= 0 ; n
< nE
; n
++ )
1576 const FuncData
* p
= Get( n
);
1577 if( p
->Is( aProgrammaticName
) )
1579 ( ( FuncDataList
* ) this )->nLast
= n
;
1584 ( ( FuncDataList
* ) this )->nLast
= 0xFFFFFFFF;
1589 AnalysisResId::AnalysisResId( sal_uInt16 nId
, ResMgr
& rResMgr
) : ResId( nId
, rResMgr
)
1596 SortedIndividualInt32List::SortedIndividualInt32List()
1601 SortedIndividualInt32List::~SortedIndividualInt32List()
1606 void SortedIndividualInt32List::Insert( sal_Int32 nDay
)
1608 sal_uInt32 nIndex
= Count();
1612 sal_Int32 nRef
= Get( nIndex
);
1615 else if( nDay
> nRef
)
1617 MyList::Insert( (void*) nDay
, nIndex
+ 1 );
1621 MyList::Insert( (void*) nDay
, 0UL );
1625 void SortedIndividualInt32List::Insert( sal_Int32 nDay
, sal_Int32 nNullDate
, sal_Bool bInsertOnWeekend
)
1631 if( bInsertOnWeekend
|| (GetDayOfWeek( nDay
) < 5) )
1636 void SortedIndividualInt32List::Insert(
1637 double fDay
, sal_Int32 nNullDate
, sal_Bool bInsertOnWeekend
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1639 if( (fDay
< -2147483648.0) || (fDay
> 2147483649.0) )
1640 throw lang::IllegalArgumentException();
1641 Insert( static_cast< sal_Int32
>( fDay
), nNullDate
, bInsertOnWeekend
);
1645 sal_Bool
SortedIndividualInt32List::Find( sal_Int32 nVal
) const
1647 sal_uInt32 nE
= Count();
1649 if( !nE
|| nVal
< Get( 0 ) || nVal
> Get( nE
- 1 ) )
1654 for( sal_uInt32 n
= 0 ; n
< nE
; n
++ )
1656 sal_Int32 nRef
= Get( n
);
1660 else if( nRef
> nVal
)
1667 void SortedIndividualInt32List::InsertHolidayList(
1668 const ScaAnyConverter
& rAnyConv
,
1669 const uno::Any
& rHolAny
,
1670 sal_Int32 nNullDate
,
1671 sal_Bool bInsertOnWeekend
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1674 if( rAnyConv
.getDouble( fDay
, rHolAny
) )
1675 Insert( fDay
, nNullDate
, bInsertOnWeekend
);
1679 void SortedIndividualInt32List::InsertHolidayList(
1680 ScaAnyConverter
& rAnyConv
,
1681 const uno::Reference
< beans::XPropertySet
>& xOptions
,
1682 const uno::Any
& rHolAny
,
1683 sal_Int32 nNullDate
,
1684 sal_Bool bInsertOnWeekend
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1686 rAnyConv
.init( xOptions
);
1687 if( rHolAny
.getValueTypeClass() == uno::TypeClass_SEQUENCE
)
1689 uno::Sequence
< uno::Sequence
< uno::Any
> > aAnySeq
;
1690 if( rHolAny
>>= aAnySeq
)
1692 const uno::Sequence
< uno::Any
>* pSeqArray
= aAnySeq
.getConstArray();
1693 for( sal_Int32 nIndex1
= 0; nIndex1
< aAnySeq
.getLength(); nIndex1
++ )
1695 const uno::Sequence
< uno::Any
>& rSubSeq
= pSeqArray
[ nIndex1
];
1696 const uno::Any
* pAnyArray
= rSubSeq
.getConstArray();
1698 for( sal_Int32 nIndex2
= 0; nIndex2
< rSubSeq
.getLength(); nIndex2
++ )
1699 InsertHolidayList( rAnyConv
, pAnyArray
[ nIndex2
], nNullDate
, bInsertOnWeekend
);
1703 throw lang::IllegalArgumentException();
1706 InsertHolidayList( rAnyConv
, rHolAny
, nNullDate
, bInsertOnWeekend
);
1711 //-----------------------------------------------------------------------------
1713 ScaDoubleList::~ScaDoubleList()
1715 for( double* pDbl
= const_cast< double* >( First() ); pDbl
; pDbl
= const_cast< double* >( Next() ) )
1720 void ScaDoubleList::Append(
1721 const uno::Sequence
< uno::Sequence
< double > >& rValueSeq
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1723 const uno::Sequence
< double >* pSeqArray
= rValueSeq
.getConstArray();
1724 for( sal_Int32 nIndex1
= 0; nIndex1
< rValueSeq
.getLength(); nIndex1
++ )
1726 const uno::Sequence
< double >& rSubSeq
= pSeqArray
[ nIndex1
];
1727 const double* pArray
= rSubSeq
.getConstArray();
1728 for( sal_Int32 nIndex2
= 0; nIndex2
< rSubSeq
.getLength(); nIndex2
++ )
1729 Append( pArray
[ nIndex2
] );
1734 void ScaDoubleList::Append(
1735 const uno::Sequence
< uno::Sequence
< sal_Int32
> >& rValueSeq
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1737 const uno::Sequence
< sal_Int32
>* pSeqArray
= rValueSeq
.getConstArray();
1738 for( sal_Int32 nIndex1
= 0; nIndex1
< rValueSeq
.getLength(); nIndex1
++ )
1740 const uno::Sequence
< sal_Int32
>& rSubSeq
= pSeqArray
[ nIndex1
];
1741 const sal_Int32
* pArray
= rSubSeq
.getConstArray();
1742 for( sal_Int32 nIndex2
= 0; nIndex2
< rSubSeq
.getLength(); nIndex2
++ )
1743 Append( pArray
[ nIndex2
] );
1749 void ScaDoubleList::Append(
1750 const ScaAnyConverter
& rAnyConv
,
1751 const uno::Any
& rAny
,
1752 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1754 if( rAny
.getValueTypeClass() == uno::TypeClass_SEQUENCE
)
1755 Append( rAnyConv
, *static_cast< const uno::Sequence
< uno::Sequence
< uno::Any
> >* >( rAny
.getValue() ), bIgnoreEmpty
);
1759 if( rAnyConv
.getDouble( fValue
, rAny
) )
1761 else if( !bIgnoreEmpty
)
1767 void ScaDoubleList::Append(
1768 const ScaAnyConverter
& rAnyConv
,
1769 const uno::Sequence
< uno::Any
>& rAnySeq
,
1770 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1772 const uno::Any
* pArray
= rAnySeq
.getConstArray();
1773 for( sal_Int32 nIndex
= 0; nIndex
< rAnySeq
.getLength(); nIndex
++ )
1774 Append( rAnyConv
, pArray
[ nIndex
], bIgnoreEmpty
);
1778 void ScaDoubleList::Append(
1779 const ScaAnyConverter
& rAnyConv
,
1780 const uno::Sequence
< uno::Sequence
< uno::Any
> >& rAnySeq
,
1781 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1783 const uno::Sequence
< uno::Any
>* pArray
= rAnySeq
.getConstArray();
1784 for( sal_Int32 nIndex
= 0; nIndex
< rAnySeq
.getLength(); nIndex
++ )
1785 Append( rAnyConv
, pArray
[ nIndex
], bIgnoreEmpty
);
1790 void ScaDoubleList::Append(
1791 ScaAnyConverter
& rAnyConv
,
1792 const uno::Reference
< beans::XPropertySet
>& xOpt
,
1793 const uno::Sequence
< uno::Any
>& rAnySeq
,
1794 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1796 rAnyConv
.init( xOpt
);
1797 Append( rAnyConv
, rAnySeq
, bIgnoreEmpty
);
1801 sal_Bool
ScaDoubleList::CheckInsert( double ) const throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1808 //-----------------------------------------------------------------------------
1810 sal_Bool
ScaDoubleListGT0::CheckInsert( double fValue
) const throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1813 throw lang::IllegalArgumentException();
1814 return fValue
> 0.0;
1819 //-----------------------------------------------------------------------------
1821 sal_Bool
ScaDoubleListGE0::CheckInsert( double fValue
) const throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1824 throw lang::IllegalArgumentException();
1830 //-----------------------------------------------------------------------------
1832 Complex::Complex( const STRING
& rStr
) THROWDEF_RTE_IAE
1834 if( !ParseString( rStr
, *this ) )
1839 inline sal_Bool
Complex::IsImagUnit( sal_Unicode c
)
1841 return c
== 'i' || c
== 'j';
1844 sal_Bool
Complex::ParseString( const STRING
& rStr
, Complex
& rCompl
)
1846 rCompl
.c
= '\0'; // do not force a symbol, if only real part present
1848 const sal_Unicode
* pStr
= ( const sal_Unicode
* ) rStr
;
1850 if( IsImagUnit( *pStr
) && rStr
.getLength() == 1)
1860 if( !ParseDouble( pStr
, f
) )
1865 case '-': // imag part follows
1869 if( IsImagUnit( pStr
[ 1 ] ) )
1871 rCompl
.c
= pStr
[ 1 ];
1872 if( pStr
[ 2 ] == 0 )
1875 rCompl
.i
= ( *pStr
== '+' )? 1.0 : -1.0;
1879 else if( ParseDouble( pStr
, f
) && IsImagUnit( *pStr
) )
1903 case 0: // only real-part
1913 STRING
Complex::GetString() const THROWDEF_RTE_IAE
1915 static const String
aI( 'i' );
1916 static const String
aJ( 'j' );
1917 static const String
aPlus( '+' );
1918 static const String
aMinus( '-' );
1924 bool bHasImag
= i
!= 0.0;
1925 bool bHasReal
= !bHasImag
|| (r
!= 0.0);
1928 aRet
= ::GetString( r
);
1936 else if( i
== -1.0 )
1939 aRet
+= ::GetString( i
, bHasReal
);
1940 aRet
+= (c
!= 'j') ? aI
: aJ
;
1947 double Complex::Arg( void ) const THROWDEF_RTE_IAE
1949 if( r
== 0.0 && i
== 0.0 )
1952 double phi
= acos( r
/ Abs() );
1961 void Complex::Power( double fPower
) THROWDEF_RTE_IAE
1963 if( r
== 0.0 && i
== 0.0 )
1978 phi
= acos( r
/ p
);
1982 p
= pow( p
, fPower
);
1990 void Complex::Sqrt( void )
1992 static const double fMultConst
= 0.7071067811865475; // ...2440084436210485 = 1/sqrt(2)
1994 double i_
= sqrt( p
- r
) * fMultConst
;
1996 r
= sqrt( p
+ r
) * fMultConst
;
1997 i
= ( i
< 0.0 )? -i_
: i_
;
2001 inline BOOL
SinOverflow( double f
)
2003 return fabs( f
) >= 134217728;
2007 void Complex::Sin( void ) THROWDEF_RTE_IAE
2009 if( SinOverflow( r
) )
2016 r_
= sin( r
) * cosh( i
);
2017 i
= cos( r
) * sinh( i
);
2025 void Complex::Cos( void ) THROWDEF_RTE_IAE
2027 if( SinOverflow( r
) )
2034 r_
= cos( r
) * cosh( i
);
2035 i
= -( sin( r
) * sinh( i
) );
2043 void Complex::Div( const Complex
& z
) THROWDEF_RTE_IAE
2045 if( z
.r
== 0 && z
.i
== 0 )
2053 double f
= 1.0 / ( a2
* a2
+ b2
* b2
);
2055 r
= ( a1
* a2
+ b1
* b2
) * f
;
2056 i
= ( a2
* b1
- a1
* b2
) * f
;
2062 void Complex::Exp( void )
2064 double fE
= exp( r
);
2070 void Complex::Ln( void ) THROWDEF_RTE_IAE
2072 if( r
== 0.0 && i
== 0.0 )
2075 double fAbs
= Abs();
2076 sal_Bool bNegi
= i
< 0.0;
2078 i
= acos( r
/ fAbs
);
2087 void Complex::Log10( void ) THROWDEF_RTE_IAE
2090 Mult( 0.434294481903251828 ); // * log10( e )
2094 void Complex::Log2( void ) THROWDEF_RTE_IAE
2097 Mult( 1.442695040888963407 ); // * log2( e )
2103 ComplexList::~ComplexList()
2105 for( Complex
* p
= ( Complex
* ) First() ; p
; p
= ( Complex
* ) Next() )
2110 void ComplexList::Append( const SEQSEQ( STRING
)& r
, ComplListAppendHandl eAH
) THROWDEF_RTE_IAE
2113 sal_Int32 nE1
= r
.getLength();
2115 sal_Bool bEmpty0
= eAH
== AH_EmpyAs0
;
2116 sal_Bool bErrOnEmpty
= eAH
== AH_EmptyAsErr
;
2118 for( n1
= 0 ; n1
< nE1
; n1
++ )
2120 const SEQ( STRING
)& rList
= r
[ n1
];
2121 nE2
= rList
.getLength();
2123 for( n2
= 0 ; n2
< nE2
; n2
++ )
2125 const STRING
& rStr
= rList
[ n2
];
2127 if( rStr
.getLength() )
2128 Append( new Complex( rStr
) );
2130 Append( new Complex( 0.0 ) );
2131 else if( bErrOnEmpty
)
2138 void ComplexList::Append( const SEQ( ANY
)& aMultPars
, ComplListAppendHandl eAH
) THROWDEF_RTE_IAE
2140 sal_Int32 nEle
= aMultPars
.getLength();
2141 sal_Bool bEmpty0
= eAH
== AH_EmpyAs0
;
2142 sal_Bool bErrOnEmpty
= eAH
== AH_EmptyAsErr
;
2144 for( sal_Int32 i
= 0 ; i
< nEle
; i
++ )
2146 const ANY
& r
= aMultPars
[ i
];
2147 switch( r
.getValueTypeClass() )
2149 case uno::TypeClass_VOID
: break;
2150 case uno::TypeClass_STRING
:
2152 const STRING
* pStr
= ( const STRING
* ) r
.getValue();
2154 if( pStr
->getLength() )
2155 Append( new Complex( *( STRING
* ) r
.getValue() ) );
2157 Append( new Complex( 0.0 ) );
2158 else if( bErrOnEmpty
)
2162 case uno::TypeClass_DOUBLE
:
2163 Append( new Complex( *( double* ) r
.getValue(), 0.0 ) );
2165 case uno::TypeClass_SEQUENCE
:
2167 SEQSEQ( ANY
) aValArr
;
2170 sal_Int32 nE
= aValArr
.getLength();
2171 const SEQ( ANY
)* pArr
= aValArr
.getConstArray();
2172 for( sal_Int32 n
= 0 ; n
< nE
; n
++ )
2173 Append( pArr
[ n
], eAH
);
2188 ConvertData::ConvertData( const sal_Char p
[], double fC
, ConvertDataClass e
, sal_Bool bPrefSupport
) : aName( p
, strlen( p
), RTL_TEXTENCODING_MS_1252
)
2192 bPrefixSupport
= bPrefSupport
;
2195 ConvertData::~ConvertData()
2200 sal_Int16
ConvertData::GetMatchingLevel( const STRING
& rRef
) const
2203 sal_Int32 nLen
= rRef
.getLength();
2204 sal_Int32 nIndex
= rRef
.lastIndexOf( '^' );
2205 if( nIndex
> 0 && nIndex
== ( nLen
- 2 ) )
2207 const sal_Unicode
* p
= aStr
.getStr();
2208 aStr
= STRING( p
, nLen
- 2 );
2209 aStr
+= STRING( p
[ nLen
- 1 ] );
2211 if( aName
.equals( aStr
) )
2215 const sal_Unicode
* p
= aStr
.getStr();
2217 nLen
= aStr
.getLength();
2218 bool bPref
= IsPrefixSupport();
2219 bool bOneChar
= (bPref
&& nLen
> 1 && (aName
== p
+ 1));
2220 if (bOneChar
|| (bPref
&& nLen
> 2 && (aName
== p
+ 2) &&
2221 *p
== 'd' && *(p
+1) == 'a'))
2226 case 'y': n
= -24; break; // yocto
2227 case 'z': n
= -21; break; // zepto
2228 case 'a': n
= -18; break;
2229 case 'f': n
= -15; break;
2230 case 'p': n
= -12; break;
2231 case 'n': n
= -9; break;
2232 case 'u': n
= -6; break;
2233 case 'm': n
= -3; break;
2234 case 'c': n
= -2; break;
2243 case 'e': n
= 1; break;
2244 case 'h': n
= 2; break;
2245 case 'k': n
= 3; break;
2246 case 'M': n
= 6; break;
2247 case 'G': n
= 9; break;
2248 case 'T': n
= 12; break;
2249 case 'P': n
= 15; break;
2250 case 'E': n
= 18; break;
2251 case 'Z': n
= 21; break; // zetta
2252 case 'Y': n
= 24; break; // yotta
2257 // We could weed some nonsense out, ODFF doesn't say so though.
2259 if (n
< 0 && Class() == CDC_Information
)
2260 n
= INV_MATCHLEV
; // milli-bits doesn't make sense
2263 //! <HACK> #100616# "cm3" is not 10^-2 m^3 but 10^-6 m^3 !!! ------------------
2264 if( n
!= INV_MATCHLEV
)
2266 sal_Unicode cLast
= p
[ aStr
.getLength() - 1 ];
2269 else if( cLast
== '3' )
2272 //! </HACK> -------------------------------------------------------------------
2276 else if ( nLen
> 2 && ( aName
== p
+ 2 ) && ( Class() == CDC_Information
) )
2278 const sal_Unicode
* pStr
= aStr
.getStr();
2279 if ( *(pStr
+ 1) != 'i')
2280 return INV_MATCHLEV
;
2284 case 'k': n
= 10; break;
2285 case 'M': n
= 20; break;
2286 case 'G': n
= 30; break;
2287 case 'T': n
= 40; break;
2288 case 'P': n
= 50; break;
2289 case 'E': n
= 60; break;
2290 case 'Z': n
= 70; break;
2291 case 'Y': n
= 80; break;
2298 return INV_MATCHLEV
;
2303 double ConvertData::Convert(
2304 double f
, const ConvertData
& r
, sal_Int16 nLevFrom
, sal_Int16 nLevTo
) const THROWDEF_RTE_IAE
2306 if( Class() != r
.Class() )
2309 sal_Bool bBinFromLev
= ( nLevFrom
> 0 && ( nLevFrom
% 10 ) == 0 );
2310 sal_Bool bBinToLev
= ( nLevTo
> 0 && ( nLevTo
% 10 ) == 0 );
2312 if ( Class() == CDC_Information
&& ( bBinFromLev
|| bBinToLev
) )
2314 if ( bBinFromLev
&& bBinToLev
)
2316 nLevFrom
= sal::static_int_cast
<sal_Int16
>( nLevFrom
- nLevTo
);
2317 f
*= r
.fConst
/ fConst
;
2319 f
*= pow( 2.0, nLevFrom
);
2321 else if ( bBinFromLev
)
2322 f
*= ( r
.fConst
/ fConst
) * ( pow( 2.0, nLevFrom
) / pow( 10.0, nLevTo
) );
2324 f
*= ( r
.fConst
/ fConst
) * ( pow( 10.0, nLevFrom
) / pow( 2.0, nLevTo
) );
2328 nLevFrom
= sal::static_int_cast
<sal_Int16
>( nLevFrom
- nLevTo
); // effective level
2330 f
*= r
.fConst
/ fConst
;
2333 f
= ::rtl::math::pow10Exp( f
, nLevFrom
);
2339 double ConvertData::ConvertToBase( double f
, sal_Int16 n
) const
2341 return ::rtl::math::pow10Exp( f
/ fConst
, n
);
2345 double ConvertData::ConvertFromBase( double f
, sal_Int16 n
) const
2347 return ::rtl::math::pow10Exp( f
* fConst
, -n
);
2352 ConvertDataLinear::~ConvertDataLinear()
2356 double ConvertDataLinear::Convert(
2357 double f
, const ConvertData
& r
, sal_Int16 nLevFrom
, sal_Int16 nLevTo
) const THROWDEF_RTE_IAE
2359 if( Class() != r
.Class() )
2362 // return ::rtl::math::round( r.ConvertFromBase( ConvertToBase( f, nLevFrom ), nLevTo ), 13 );
2363 return r
.ConvertFromBase( ConvertToBase( f
, nLevFrom
), nLevTo
);
2367 double ConvertDataLinear::ConvertToBase( double f
, sal_Int16 n
) const
2370 f
= ::rtl::math::pow10Exp( f
, n
);
2379 double ConvertDataLinear::ConvertFromBase( double f
, sal_Int16 n
) const
2385 f
= ::rtl::math::pow10Exp( f
, -n
);
2393 ConvertDataList::ConvertDataList( void )
2395 #define NEWD(str,unit,cl) Append(new ConvertData(str,unit,cl))
2396 #define NEWDP(str,unit,cl) Append(new ConvertData(str,unit,cl,sal_True))
2397 #define NEWL(str,unit,offs,cl) Append(new ConvertDataLinear(str,unit,offs,cl))
2398 #define NEWLP(str,unit,offs,cl) Append(new ConvertDataLinear(str,unit,offs,cl,sal_True))
2400 // *** are extra and not standard Excel Analysis Addin!
2402 // MASS: 1 Gram is...
2403 NEWDP( "g", 1.0000000000000000E00
, CDC_Mass
); // Gram
2404 NEWD( "sg", 6.8522050005347800E-05, CDC_Mass
); // Pieces
2405 NEWD( "lbm", 2.2046229146913400E-03, CDC_Mass
); // Pound (commercial weight)
2406 NEWDP( "u", 6.0221370000000000E23
, CDC_Mass
); // U (atomic mass)
2407 NEWD( "ozm", 3.5273971800362700E-02, CDC_Mass
); // Ounce (commercial weight)
2408 NEWD( "stone", 1.574730e-04, CDC_Mass
); // *** Stone
2409 NEWD( "ton", 1.102311e-06, CDC_Mass
); // *** Ton
2410 NEWD( "grain", 1.543236E01
, CDC_Mass
); // *** Grain
2411 NEWD( "pweight", 7.054792E-01, CDC_Mass
); // *** Pennyweight
2412 NEWD( "hweight", 1.968413E-05, CDC_Mass
); // *** Hundredweight
2413 NEWD( "shweight", 2.204623E-05, CDC_Mass
); // *** Shorthundredweight
2414 NEWD( "brton", 9.842065E-07, CDC_Mass
); // *** Gross Registered Ton
2415 NEWD( "cwt", 2.2046226218487758E-05, CDC_Mass
); // U.S. (short) hundredweight
2416 NEWD( "shweight", 2.2046226218487758E-05, CDC_Mass
); // U.S. (short) hundredweight also
2417 NEWD( "uk_cwt", 1.9684130552221213E-05, CDC_Mass
); // Imperial hundredweight
2418 NEWD( "lcwt", 1.9684130552221213E-05, CDC_Mass
); // Imperial hundredweight also
2419 NEWD( "hweight", 1.9684130552221213E-05, CDC_Mass
); // Imperial hundredweight also
2420 NEWD( "uk_ton", 9.8420652761106063E-07, CDC_Mass
); // Imperial ton
2421 NEWD( "LTON", 9.8420652761106063E-07, CDC_Mass
); // Imperial ton also
2423 // LENGTH: 1 Meter is...
2424 NEWDP( "m", 1.0000000000000000E00
, CDC_Length
); // Meter
2425 NEWD( "mi", 6.2137119223733397E-04, CDC_Length
); // Britsh Mile 6,21371192237333969617434184363e-4
2426 NEWD( "Nmi", 5.3995680345572354E-04, CDC_Length
); // Nautical Mile 5,39956803455723542116630669546e-4
2427 NEWD( "in", 3.9370078740157480E01
, CDC_Length
); // Inch 39,37007874015748031496062992126
2428 NEWD( "ft", 3.2808398950131234E00
, CDC_Length
); // Foot 3,2808398950131233595800524934383
2429 NEWD( "yd", 1.0936132983377078E00
, CDC_Length
); // Yard 1,0936132983377077865266841644794
2430 NEWD( "ang", 1.0000000000000000E10
, CDC_Length
); // Angstroem
2431 NEWD( "Pica", 2.8346456692913386E03
, CDC_Length
); // Pica (1/72 Inch) 2834,6456692913385826771653543307
2432 NEWD( "ell", 8.748906E-01, CDC_Length
); // *** Ell
2433 NEWDP( "parsec", 3.240779E-17, CDC_Length
); // *** Parsec
2434 NEWDP( "pc", 3.240779E-17, CDC_Length
); // *** Parsec also
2435 NEWDP( "lightyear", 1.0570234557732930E-16, CDC_Length
); // *** Light Year
2436 NEWDP( "ly", 1.0570234557732930E-16, CDC_Length
); // *** Light Year also
2437 NEWD( "survey_mi", 6.2136994949494949E-04, CDC_Length
); // U.S. survey mile
2439 // TIME: 1 Second is...
2440 NEWD( "yr", 3.1688087814028950E-08, CDC_Time
); // Year
2441 NEWD( "day", 1.1574074074074074E-05, CDC_Time
); // Day
2442 NEWD( "d", 1.1574074074074074E-05, CDC_Time
); // Day also
2443 NEWD( "hr", 2.7777777777777778E-04, CDC_Time
); // Hour
2444 NEWD( "mn", 1.6666666666666667E-02, CDC_Time
); // Minute
2445 NEWD( "min", 1.6666666666666667E-02, CDC_Time
); // Minute also
2446 NEWDP( "sec", 1.0000000000000000E00
, CDC_Time
); // Second
2447 NEWDP( "s", 1.0000000000000000E00
, CDC_Time
); // Second also
2449 // PRESSURE: 1 Pascal is...
2450 NEWDP( "Pa", 1.0000000000000000E00
, CDC_Pressure
); // Pascal
2451 NEWDP( "atm", 9.8692329999819300E-06, CDC_Pressure
); // Atmosphere
2452 NEWDP( "at", 9.8692329999819300E-06, CDC_Pressure
); // Atmosphere also
2453 NEWDP( "mmHg", 7.5006170799862700E-03, CDC_Pressure
); // mm Hg (Mercury)
2454 NEWD( "Torr", 7.5006380000000000E-03, CDC_Pressure
); // *** Torr
2455 NEWD( "psi", 1.4503770000000000E-04, CDC_Pressure
); // *** Psi
2457 // FORCE: 1 Newton is...
2458 NEWDP( "N", 1.0000000000000000E00
, CDC_Force
); // Newton
2459 NEWDP( "dyn", 1.0000000000000000E05
, CDC_Force
); // Dyn
2460 NEWDP( "dy", 1.0000000000000000E05
, CDC_Force
); // Dyn also
2461 NEWD( "lbf", 2.24808923655339E-01, CDC_Force
); // Pound-Force
2462 NEWDP( "pond", 1.019716E02
, CDC_Force
); // *** Pond
2464 // ENERGY: 1 Joule is...
2465 NEWDP( "J", 1.0000000000000000E00
, CDC_Energy
); // Joule
2466 NEWDP( "e", 1.0000000000000000E07
, CDC_Energy
); // Erg -> http://www.chemie.fu-berlin.de/chemistry/general/si.html
2467 // NEWD( "e", 9.99999519343231E06, CDC_Energy ); // Erg
2468 NEWDP( "c", 2.3900624947346700E-01, CDC_Energy
); // Thermodynamical Calorie
2469 NEWDP( "cal", 2.3884619064201700E-01, CDC_Energy
); // Calorie
2470 NEWDP( "eV", 6.2414570000000000E18
, CDC_Energy
); // Electronvolt
2471 NEWDP( "ev", 6.2414570000000000E18
, CDC_Energy
); // Electronvolt also
2472 NEWD( "HPh", 3.7250611111111111E-07, CDC_Energy
); // Horsepower Hours
2473 NEWD( "hh", 3.7250611111111111E-07, CDC_Energy
); // Horsepower Hours also
2474 // NEWD( "HPh", 3.72506430801000E-07, CDC_Energy ); // Horsepower Hours
2475 NEWDP( "Wh", 2.7777777777777778E-04, CDC_Energy
); // Watt Hours
2476 NEWDP( "wh", 2.7777777777777778E-04, CDC_Energy
); // Watt Hours also
2477 NEWD( "flb", 2.37304222192651E01
, CDC_Energy
); // Foot Pound
2478 NEWD( "BTU", 9.4781506734901500E-04, CDC_Energy
); // British Thermal Unit
2479 NEWD( "btu", 9.4781506734901500E-04, CDC_Energy
); // British Thermal Unit also
2481 // POWER: 1 Watt is...
2482 NEWDP( "W", 1.0000000000000000E00
, CDC_Power
); // Watt
2483 NEWDP( "w", 1.0000000000000000E00
, CDC_Power
); // Watt also
2484 NEWD( "HP", 1.341022E-03, CDC_Power
); // Horsepower
2485 NEWD( "h", 1.341022E-03, CDC_Power
); // Horsepower also
2486 NEWD( "PS", 1.359622E-03, CDC_Power
); // *** German Pferdestaerke
2487 // NEWD( "HP", 1.4102006031908E-03, CDC_Power ); // Excel seams to be a little bit wrong... either this doesn't fit to J -> HPh
2489 // MAGNETISM: 1 Tesla is...
2490 NEWDP( "T", 1.0000000000000000E00
, CDC_Magnetism
); // Tesla
2491 NEWDP( "ga", 1.0000000000000000E04
, CDC_Magnetism
); // Gauss
2493 // TEMERATURE: 1 Kelvin is...
2494 NEWL( "C", 1.0000000000000000E00
, -2.7315000000000000E02
, CDC_Temperature
); // Celsius
2495 NEWL( "cel", 1.0000000000000000E00
, -2.7315000000000000E02
, CDC_Temperature
); // Celsius also
2496 NEWL( "F", 1.8000000000000000E00
, -2.5537222222222222E02
, CDC_Temperature
); // Fahrenheit
2497 NEWL( "fah", 1.8000000000000000E00
, -2.5537222222222222E02
, CDC_Temperature
); // Fahrenheit also
2498 NEWLP( "K", 1.0000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // Kelvin
2499 NEWLP( "kel", 1.0000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // Kelvin also
2500 NEWL( "Reau", 8.0000000000000000E-01, -2.7315000000000000E02
, CDC_Temperature
); // *** Reaumur
2501 NEWL( "Rank", 1.8000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // *** Rankine
2503 // VOLUMNE: 1 Liter is...
2504 NEWD( "tsp", 2.0284000000000000E02
, CDC_Volume
); // Teaspoon
2505 NEWD( "tbs", 6.7613333333333333E01
, CDC_Volume
); // Tablespoon
2506 NEWD( "oz", 3.3806666666666667E01
, CDC_Volume
); // Ounce Liquid
2507 NEWD( "cup", 4.2258333333333333E00
, CDC_Volume
); // Cup
2508 NEWD( "pt", 2.1129166666666667E00
, CDC_Volume
); // US Pint
2509 NEWD( "us_pt", 2.1129166666666667E00
, CDC_Volume
); // US Pint also
2510 NEWD( "uk_pt", 1.75975569552166E00
, CDC_Volume
); // UK Pint
2511 NEWD( "qt", 1.0564583333333333E00
, CDC_Volume
); // Quart
2512 NEWD( "gal", 2.6411458333333333E-01, CDC_Volume
); // Gallone
2513 NEWDP( "l", 1.0000000000000000E00
, CDC_Volume
); // Liter
2514 NEWDP( "L", 1.0000000000000000E00
, CDC_Volume
); // Liter also
2515 NEWDP( "lt", 1.0000000000000000E00
, CDC_Volume
); // Liter also
2516 NEWDP( "m3", 1.0000000000000000E-03, CDC_Volume
); // *** Cubic Meter
2517 NEWD( "mi3", 2.3991275857892772E-13, CDC_Volume
); // *** Cubic Britsh Mile
2518 NEWD( "Nmi3", 1.5742621468581148E-13, CDC_Volume
); // *** Cubic Nautical Mile
2519 NEWD( "in3", 6.1023744094732284E01
, CDC_Volume
); // *** Cubic Inch
2520 NEWD( "ft3", 3.5314666721488590E-02, CDC_Volume
); // *** Cubic Foot
2521 NEWD( "yd3", 1.3079506193143922E-03, CDC_Volume
); // *** Cubic Yard
2522 NEWD( "ang3", 1.0000000000000000E27
, CDC_Volume
); // *** Cubic Angstroem
2523 NEWD( "Pica3", 2.2776990435870636E07
, CDC_Volume
); // *** Cubic Pica
2524 NEWD( "barrel", 6.289811E-03, CDC_Volume
); // *** Barrel (=42gal?)
2525 NEWD( "bushel", 2.837759E-02, CDC_Volume
); // *** Bushel
2526 NEWD( "regton", 3.531467E-04, CDC_Volume
); // *** Register ton
2527 NEWD( "GRT", 3.531467E-04, CDC_Volume
); // *** Register ton also
2528 NEWD( "Schooner", 2.3529411764705882E00
, CDC_Volume
); // *** austr. Schooner
2529 NEWD( "Middy", 3.5087719298245614E00
, CDC_Volume
); // *** austr. Middy
2530 NEWD( "Glass", 5.0000000000000000E00
, CDC_Volume
); // *** austr. Glass
2531 NEWD( "Sixpack", 0.5, CDC_Volume
); // ***
2532 NEWD( "Humpen", 2.0, CDC_Volume
); // ***
2533 NEWD( "ly3", 1.1810108125623799E-51, CDC_Volume
); // *** Cubic light-year
2534 NEWD( "MTON", 1.4125866688595436E00
, CDC_Volume
); // *** Measurement ton
2535 NEWD( "tspm", 5.0000000000000000E02
, CDC_Volume
); // *** Modern teaspoon
2536 NEWD( "uk_gal", 2.6411458333333333E-01, CDC_Volume
); // U.K. / Imperial gallon ??
2537 NEWD( "uk_qt", 1.0564583333333333E00
, CDC_Volume
); // U.K. / Imperial quart ??
2539 // 1 Square Meter is...
2540 NEWDP( "m2", 1.0000000000000000E00
, CDC_Area
); // *** Square Meter
2541 NEWD( "mi2", 3.8610215854244585E-07, CDC_Area
); // *** Square Britsh Mile
2542 NEWD( "Nmi2", 2.9155334959812286E-07, CDC_Area
); // *** Square Nautical Mile
2543 NEWD( "in2", 1.5500031000062000E03
, CDC_Area
); // *** Square Inch
2544 NEWD( "ft2", 1.0763910416709722E01
, CDC_Area
); // *** Square Foot
2545 NEWD( "yd2", 1.1959900463010803E00
, CDC_Area
); // *** Square Yard
2546 NEWDP( "ang2", 1.0000000000000000E20
, CDC_Area
); // *** Square Angstroem
2547 NEWD( "Pica2", 8.0352160704321409E06
, CDC_Area
); // *** Square Pica
2548 NEWD( "Morgen", 4.0000000000000000E-04, CDC_Area
); // *** Morgen
2549 NEWDP( "ar", 1.000000E-02, CDC_Area
); // *** Ar
2550 NEWD( "acre", 2.471053815E-04, CDC_Area
); // *** Acre
2551 NEWD( "uk_acre", 2.4710538146716534E-04, CDC_Area
); // *** International acre
2552 NEWD( "us_acre", 2.4710439304662790E-04, CDC_Area
); // *** U.S. survey/statute acre
2553 NEWD( "ly2", 1.1172985860549147E-32, CDC_Area
); // *** Square Light-year
2554 NEWD( "ha", 1.000000E-04, CDC_Area
); // *** Hectare
2555 NEWD( "Quadratlatschen",5.6689342403628117914,CDC_Area
); // ***
2557 // SPEED: 1 Meter per Second is...
2558 NEWDP( "m/s", 1.0000000000000000E00
, CDC_Speed
); // *** Meters per Second
2559 NEWDP( "m/sec", 1.0000000000000000E00
, CDC_Speed
); // *** Meters per Second also
2560 NEWD( "m/h", 3.6000000000000000E03
, CDC_Speed
); // *** Meters per Hour
2561 NEWD( "m/hr", 3.6000000000000000E03
, CDC_Speed
); // *** Meters per Hour also
2562 NEWD( "mph", 2.2369362920544023E00
, CDC_Speed
); // *** Britsh Miles per Hour
2563 NEWD( "kn", 1.9438444924406048E00
, CDC_Speed
); // *** Knot = Nautical Miles per Hour
2564 NEWD( "admkn", 1.9438446603753486E00
, CDC_Speed
); // *** Admiralty Knot
2565 NEWD( "wahnsinnige Geschwindigkeit", 2.0494886343432328E-14, CDC_Speed
); // ***
2566 NEWD( "ludicrous speed", 2.0494886343432328E-14, CDC_Speed
); // ***
2567 NEWD( "laecherliche Geschwindigkeit", 4.0156958471424288E-06, CDC_Speed
); // ***
2568 NEWD( "ridiculous speed", 4.0156958471424288E-06, CDC_Speed
); // ***
2570 // INFORMATION: 1 Bit is...
2571 NEWDP( "bit", 1.00E00
, CDC_Information
); // *** Bit
2572 NEWDP( "byte", 1.25E-01, CDC_Information
); // *** Byte
2576 ConvertDataList::~ConvertDataList()
2578 for( ConvertData
* p
= First() ; p
; p
= Next() )
2583 double ConvertDataList::Convert( double fVal
, const STRING
& rFrom
, const STRING
& rTo
) THROWDEF_RTE_IAE
2585 // This will not catch illegal units
2586 // if( rFrom == rTo )
2589 ConvertData
* pFrom
= NULL
;
2590 ConvertData
* pTo
= NULL
;
2591 sal_Bool bSearchFrom
= sal_True
;
2592 sal_Bool bSearchTo
= sal_True
;
2593 sal_Int16 nLevelFrom
= 0;
2594 sal_Int16 nLevelTo
= 0;
2596 ConvertData
* p
= First();
2597 while( p
&& ( bSearchFrom
|| bSearchTo
) )
2601 sal_Int16 n
= p
->GetMatchingLevel( rFrom
);
2602 if( n
!= INV_MATCHLEV
)
2605 { // only first match for partial equality rulz a little bit more
2610 { // ... but exact match rulz most
2612 bSearchFrom
= sal_False
;
2620 sal_Int16 n
= p
->GetMatchingLevel( rTo
);
2621 if( n
!= INV_MATCHLEV
)
2624 { // only first match for partial equality rulz a little bit more
2629 { // ... but exact match rulz most
2631 bSearchTo
= sal_False
;
2641 return pFrom
->Convert( fVal
, *pTo
, nLevelFrom
, nLevelTo
);
2648 //-----------------------------------------------------------------------------
2650 ScaDate::ScaDate() :
2655 bLastDayMode( sal_True
),
2656 bLastDay( sal_False
),
2657 b30Days( sal_False
),
2658 bUSMode( sal_False
)
2662 ScaDate::ScaDate( sal_Int32 nNullDate
, sal_Int32 nDate
, sal_Int32 nBase
)
2664 DaysToDate( nNullDate
+ nDate
, nOrigDay
, nMonth
, nYear
);
2665 bLastDayMode
= (nBase
!= 5);
2666 bLastDay
= (nOrigDay
>= ::DaysInMonth( nMonth
, nYear
));
2667 b30Days
= (nBase
== 0) || (nBase
== 4);
2668 bUSMode
= (nBase
== 0);
2672 ScaDate::ScaDate( const ScaDate
& rCopy
) :
2673 nOrigDay( rCopy
.nOrigDay
),
2675 nMonth( rCopy
.nMonth
),
2676 nYear( rCopy
.nYear
),
2677 bLastDayMode( rCopy
.bLastDayMode
),
2678 bLastDay( rCopy
.bLastDay
),
2679 b30Days( rCopy
.b30Days
),
2680 bUSMode( rCopy
.bUSMode
)
2684 ScaDate
& ScaDate::operator=( const ScaDate
& rCopy
)
2686 if( this != &rCopy
)
2688 nOrigDay
= rCopy
.nOrigDay
;
2690 nMonth
= rCopy
.nMonth
;
2691 nYear
= rCopy
.nYear
;
2692 bLastDayMode
= rCopy
.bLastDayMode
;
2693 bLastDay
= rCopy
.bLastDay
;
2694 b30Days
= rCopy
.b30Days
;
2695 bUSMode
= rCopy
.bUSMode
;
2700 void ScaDate::setDay()
2704 // 30-days-mode: set nDay to 30 if original was last day in month
2705 nDay
= Min( nOrigDay
, static_cast< sal_uInt16
>( 30 ) );
2706 if( bLastDay
|| (nDay
>= ::DaysInMonth( nMonth
, nYear
)) )
2711 // set nDay to last day in this month if original was last day
2712 sal_uInt16 nLastDay
= ::DaysInMonth( nMonth
, nYear
);
2713 nDay
= bLastDay
? nLastDay
: Min( nOrigDay
, nLastDay
);
2717 sal_Int32
ScaDate::getDaysInMonthRange( sal_uInt16 nFrom
, sal_uInt16 nTo
) const
2724 nRet
= (nTo
- nFrom
+ 1) * 30;
2727 for( sal_uInt16 nMonthIx
= nFrom
; nMonthIx
<= nTo
; ++nMonthIx
)
2728 nRet
+= getDaysInMonth( nMonthIx
);
2733 sal_Int32
ScaDate::getDaysInYearRange( sal_uInt16 nFrom
, sal_uInt16 nTo
) const
2738 return b30Days
? ((nTo
- nFrom
+ 1) * 360) : ::GetDaysInYears( nFrom
, nTo
);
2741 void ScaDate::doAddYears( sal_Int32 nYearCount
) throw( lang::IllegalArgumentException
)
2743 sal_Int32 nNewYear
= nYearCount
+ nYear
;
2744 if( (nNewYear
< 0) || (nNewYear
> 0x7FFF) )
2745 throw lang::IllegalArgumentException();
2746 nYear
= static_cast< sal_uInt16
>( nNewYear
);
2749 void ScaDate::addMonths( sal_Int32 nMonthCount
) throw( lang::IllegalArgumentException
)
2751 sal_Int32 nNewMonth
= nMonthCount
+ nMonth
;
2752 if( nNewMonth
> 12 )
2755 doAddYears( nNewMonth
/ 12 );
2756 nMonth
= static_cast< sal_uInt16
>( nNewMonth
% 12 ) + 1;
2758 else if( nNewMonth
< 1 )
2760 doAddYears( nNewMonth
/ 12 - 1 );
2761 nMonth
= static_cast< sal_uInt16
>( nNewMonth
% 12 + 12 );
2764 nMonth
= static_cast< sal_uInt16
>( nNewMonth
);
2768 sal_Int32
ScaDate::getDate( sal_Int32 nNullDate
) const
2770 sal_uInt16 nLastDay
= ::DaysInMonth( nMonth
, nYear
);
2771 sal_uInt16 nRealDay
= (bLastDayMode
&& bLastDay
) ? nLastDay
: Min( nLastDay
, nOrigDay
);
2772 return ::DateToDays( nRealDay
, nMonth
, nYear
) - nNullDate
;
2775 sal_Int32
ScaDate::getDiff( const ScaDate
& rFrom
, const ScaDate
& rTo
) throw( lang::IllegalArgumentException
)
2778 return getDiff( rTo
, rFrom
);
2780 sal_Int32 nDiff
= 0;
2781 ScaDate
aFrom( rFrom
);
2786 // corrections for base 0 (US NASD)
2789 if( ((rFrom
.nMonth
== 2) || (rFrom
.nDay
< 30)) && (aTo
.nOrigDay
== 31) )
2791 else if( (aTo
.nMonth
== 2) && aTo
.bLastDay
)
2792 aTo
.nDay
= ::DaysInMonth( 2, aTo
.nYear
);
2794 // corrections for base 4 (Europe)
2797 if( (aFrom
.nMonth
== 2) && (aFrom
.nDay
== 30) )
2798 aFrom
.nDay
= ::DaysInMonth( 2, aFrom
.nYear
);
2799 if( (aTo
.nMonth
== 2) && (aTo
.nDay
== 30) )
2800 aTo
.nDay
= ::DaysInMonth( 2, aTo
.nYear
);
2804 if( (aFrom
.nYear
< aTo
.nYear
) || ((aFrom
.nYear
== aTo
.nYear
) && (aFrom
.nMonth
< aTo
.nMonth
)) )
2806 // move aFrom to 1st day of next month
2807 nDiff
= aFrom
.getDaysInMonth() - aFrom
.nDay
+ 1;
2808 aFrom
.nOrigDay
= aFrom
.nDay
= 1;
2809 aFrom
.bLastDay
= sal_False
;
2810 aFrom
.addMonths( 1 );
2812 if( aFrom
.nYear
< aTo
.nYear
)
2814 // move aFrom to 1st day of next year
2815 nDiff
+= aFrom
.getDaysInMonthRange( aFrom
.nMonth
, 12 );
2816 aFrom
.addMonths( 13 - aFrom
.nMonth
);
2818 // move aFrom to 1st day of this year
2819 nDiff
+= aFrom
.getDaysInYearRange( aFrom
.nYear
, aTo
.nYear
- 1 );
2820 aFrom
.addYears( aTo
.nYear
- aFrom
.nYear
);
2823 // move aFrom to 1st day of this month
2824 nDiff
+= aFrom
.getDaysInMonthRange( aFrom
.nMonth
, aTo
.nMonth
- 1 );
2825 aFrom
.addMonths( aTo
.nMonth
- aFrom
.nMonth
);
2827 // finally add remaining days in this month
2828 nDiff
+= aTo
.nDay
- aFrom
.nDay
;
2829 return nDiff
> 0 ? nDiff
: 0;
2832 sal_Bool
ScaDate::operator<( const ScaDate
& rCmp
) const
2834 if( nYear
!= rCmp
.nYear
)
2835 return nYear
< rCmp
.nYear
;
2836 if( nMonth
!= rCmp
.nMonth
)
2837 return nMonth
< rCmp
.nMonth
;
2838 if( nDay
!= rCmp
.nDay
)
2839 return nDay
< rCmp
.nDay
;
2840 if( bLastDay
|| rCmp
.bLastDay
)
2841 return !bLastDay
&& rCmp
.bLastDay
;
2842 return nOrigDay
< rCmp
.nOrigDay
;
2847 //-----------------------------------------------------------------------------
2849 ScaAnyConverter::ScaAnyConverter( const uno::Reference
< lang::XMultiServiceFactory
>& xServiceFact
) :
2850 bHasValidFormat( sal_False
)
2852 if( xServiceFact
.is() )
2854 uno::Reference
< uno::XInterface
> xInstance
= xServiceFact
->createInstance(
2855 OUString::createFromAscii( "com.sun.star.util.NumberFormatter" ) );
2856 xFormatter
= uno::Reference
< util::XNumberFormatter
>( xInstance
, uno::UNO_QUERY
);
2860 ScaAnyConverter::~ScaAnyConverter()
2864 void ScaAnyConverter::init( const uno::Reference
< beans::XPropertySet
>& xPropSet
) throw( uno::RuntimeException
)
2866 // try to get default number format
2867 bHasValidFormat
= sal_False
;
2868 if( xFormatter
.is() )
2870 // get XFormatsSupplier from outer XPropertySet
2871 uno::Reference
< util::XNumberFormatsSupplier
> xFormatsSupp( xPropSet
, uno::UNO_QUERY
);
2872 if( xFormatsSupp
.is() )
2874 // get XNumberFormatTypes from XNumberFormatsSupplier to get standard index
2875 uno::Reference
< util::XNumberFormats
> xFormats( xFormatsSupp
->getNumberFormats() );
2876 uno::Reference
< util::XNumberFormatTypes
> xFormatTypes( xFormats
, uno::UNO_QUERY
);
2877 if( xFormatTypes
.is() )
2879 lang::Locale eLocale
;
2880 nDefaultFormat
= xFormatTypes
->getStandardIndex( eLocale
);
2881 xFormatter
->attachNumberFormatsSupplier( xFormatsSupp
);
2882 bHasValidFormat
= sal_True
;
2888 double ScaAnyConverter::convertToDouble( const OUString
& rString
) const throw( lang::IllegalArgumentException
)
2890 double fValue
= 0.0;
2891 if( bHasValidFormat
)
2895 fValue
= xFormatter
->convertStringToNumber( nDefaultFormat
, rString
);
2897 catch( uno::Exception
& )
2899 throw lang::IllegalArgumentException();
2904 rtl_math_ConversionStatus eStatus
;
2906 fValue
= ::rtl::math::stringToDouble( rString
, '.', ',', &eStatus
, &nEnd
);
2907 if( (eStatus
!= rtl_math_ConversionStatus_Ok
) || (nEnd
< rString
.getLength()) )
2908 throw lang::IllegalArgumentException();
2913 sal_Bool
ScaAnyConverter::getDouble(
2915 const uno::Any
& rAny
) const throw( lang::IllegalArgumentException
)
2918 sal_Bool bContainsVal
= sal_True
;
2919 switch( rAny
.getValueTypeClass() )
2921 case uno::TypeClass_VOID
:
2922 bContainsVal
= sal_False
;
2924 case uno::TypeClass_DOUBLE
:
2927 case uno::TypeClass_STRING
:
2929 const OUString
* pString
= static_cast< const OUString
* >( rAny
.getValue() );
2930 if( pString
->getLength() )
2931 rfResult
= convertToDouble( *pString
);
2933 bContainsVal
= sal_False
;
2937 throw lang::IllegalArgumentException();
2939 return bContainsVal
;
2942 sal_Bool
ScaAnyConverter::getDouble(
2944 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2945 const uno::Any
& rAny
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2948 return getDouble( rfResult
, rAny
);
2951 double ScaAnyConverter::getDouble(
2952 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2953 const uno::Any
& rAny
,
2954 double fDefault
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2957 if( !getDouble( fResult
, xPropSet
, rAny
) )
2962 sal_Bool
ScaAnyConverter::getInt32(
2963 sal_Int32
& rnResult
,
2964 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2965 const uno::Any
& rAny
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2968 sal_Bool bContainsVal
= getDouble( fResult
, xPropSet
, rAny
);
2969 if( (fResult
<= -2147483649.0) || (fResult
>= 2147483648.0) )
2970 throw lang::IllegalArgumentException();
2972 rnResult
= static_cast< sal_Int32
>( fResult
);
2973 return bContainsVal
;
2976 sal_Int32
ScaAnyConverter::getInt32(
2977 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
2978 const uno::Any
& rAny
,
2979 sal_Int32 nDefault
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2982 if( !getInt32( nResult
, xPropSet
, rAny
) )
2989 //-----------------------------------------------------------------------------