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 /** Approximation algorithm for erf for 0 < x < 0.65. */
673 void Erf0065( double x
, double& fVal
)
675 static const double pn
[] = {
677 1.35894887627277916E-1,
678 4.03259488531795274E-2,
679 1.20339380863079457E-3,
680 6.49254556481904354E-5
682 static const double qn
[] = {
684 4.53767041780002545E-1,
685 8.69936222615385890E-2,
686 8.49717371168693357E-3,
687 3.64915280629351082E-4
693 for ( unsigned int i
= 0; i
<= 4; ++i
)
695 fPSum
+= pn
[i
]*fXPow
;
696 fQSum
+= qn
[i
]*fXPow
;
699 fVal
= x
* fPSum
/ fQSum
;
702 /** Approximation algorithm for erfc for 0.65 < x < 6.0. */
703 void Erfc0600( double x
, double& fVal
)
713 static const double pn22
[] = {
714 9.99999992049799098E-1,
716 8.78115804155881782E-1,
717 3.31899559578213215E-1,
718 7.14193832506776067E-2,
719 7.06940843763253131E-3
721 static const double qn22
[] = {
726 5.94651311286481502E-1,
727 1.26579413030177940E-1,
728 1.25304936549413393E-2
733 else /* if ( x < 6.0 ) this is true, but the compiler does not know */
735 static const double pn60
[] = {
736 9.99921140009714409E-1,
739 5.81528574177741135E-1,
740 1.57289620742838702E-1,
741 2.25716982919217555E-2
743 static const double qn60
[] = {
749 2.78788439273628983E-1,
750 4.00072964526861362E-2
756 for ( unsigned int i
= 0; i
< 6; ++i
)
758 fPSum
+= pn
[i
]*fXPow
;
759 fQSum
+= qn
[i
]*fXPow
;
762 fQSum
+= qn
[6]*fXPow
;
763 fVal
= exp( -1.0*x
*x
)* fPSum
/ fQSum
;
766 /** Approximation algorithm for erfc for 6.0 < x < 26.54 (but used for all
768 void Erfc2654( double x
, double& fVal
)
770 static const double pn
[] = {
771 5.64189583547756078E-1,
773 3.84683103716117320E1
,
774 4.77209965874436377E1
,
777 static const double qn
[] = {
779 1.61020914205869003E1
,
780 7.54843505665954743E1
,
781 1.12123870801026015E2
,
782 3.73997570145040850E1
789 for ( unsigned int i
= 0; i
<= 4; ++i
)
791 fPSum
+= pn
[i
]*fXPow
;
792 fQSum
+= qn
[i
]*fXPow
;
795 fVal
= exp(-1.0*x
*x
)*fPSum
/ (x
*fQSum
);
798 double Erfc( double );
800 /** Parent error function (erf) that calls different algorithms based on the
801 value of x. It takes care of cases where x is negative as erf is an odd
802 function i.e. erf(-x) = -erf(x).
804 Kramer, W., and Blomquist, F., 2000, Algorithms with Guaranteed Error Bounds
805 for the Error Function and the Complementary Error Function
807 http://www.math.uni-wuppertal.de/wrswt/literatur_en.html
809 @author Kohei Yoshida <kohei@openoffice.org>
813 double Erf( double x
)
818 bool bNegative
= false;
827 fErf
= (double) (x
*1.1283791670955125738961589031215452L);
831 fErf
= 1.0 - Erfc( x
);
839 /** Parent complementary error function (erfc) that calls different algorithms
840 based on the value of x. It takes care of cases where x is negative as erfc
841 satisfies relationship erfc(-x) = 2 - erfc(x). See the comment for Erf(x)
842 for the source publication.
844 @author Kohei Yoshida <kohei@openoffice.org>
848 double Erfc( double x
)
853 bool bNegative
= false;
864 Erfc0600( x
, fErfc
);
866 Erfc2654( x
, fErfc
);
869 fErfc
= 1.0 - Erf( x
);
877 inline sal_Bool
IsNum( sal_Unicode c
)
879 return c
>= '0' && c
<= '9';
883 inline sal_Bool
IsComma( sal_Unicode c
)
885 return c
== '.' || c
== ',';
889 inline sal_Bool
IsExpStart( sal_Unicode c
)
891 return c
== 'e' || c
== 'E';
895 inline sal_Bool
IsImagUnit( sal_Unicode c
)
897 return c
== 'i' || c
== 'j';
901 inline sal_uInt16
GetVal( sal_Unicode c
)
903 return sal_uInt16( c
- '0' );
907 sal_Bool
ParseDouble( const sal_Unicode
*& rp
, double& rRet
)
911 double fMult
= 0.1; // multiplier to multiply digits with, when adding fractional ones
913 sal_Int32 nMaxExp
= 307;
914 sal_uInt16 nDigCnt
= 18; // max. number of digits to read in, rest doesn't matter
916 enum State
{ S_End
= 0, S_Sign
, S_IntStart
, S_Int
, S_IgnoreIntDigs
, S_Frac
, S_IgnoreFracDigs
, S_ExpSign
, S_Exp
};
920 sal_Bool bNegNum
= sal_False
;
921 sal_Bool bNegExp
= sal_False
;
923 const sal_Unicode
* p
= rp
;
945 else if( IsComma( c
) )
957 else if( IsComma( c
) )
959 else if( IsImagUnit( c
) )
971 fInt
+= double( GetVal( c
) );
974 eS
= S_IgnoreIntDigs
;
976 else if( IsComma( c
) )
978 else if( IsExpStart( c
) )
983 case S_IgnoreIntDigs
:
985 nExp
++; // just multiply num with 10... ;-)
986 else if( IsComma( c
) )
988 else if( IsExpStart( c
) )
996 fFrac
+= double( GetVal( c
) ) * fMult
;
1001 eS
= S_IgnoreFracDigs
;
1003 else if( IsExpStart( c
) )
1008 case S_IgnoreFracDigs
:
1009 if( IsExpStart( c
) )
1011 else if( !IsNum( c
) )
1032 nExp
+= GetVal( c
);
1033 if( nExp
> nMaxExp
)
1039 case S_End
: // to avoid compiler warning
1040 break; // loop exits anyway
1046 p
--; // set pointer back to last
1050 sal_Int32 nLog10
= sal_Int32( log10( fInt
) );
1055 if( nLog10
+ nExp
> nMaxExp
)
1058 fInt
= ::rtl::math::pow10Exp( fInt
, nExp
);
1069 STRING
GetString( double f
, sal_Bool bLeadingSign
, sal_uInt16 nMaxDig
)
1071 const int nBuff
= 256;
1072 sal_Char aBuff
[ nBuff
+ 1 ];
1073 const char* pFormStr
= bLeadingSign
? "%+.*g" : "%.*g";
1074 int nLen
= snprintf( aBuff
, nBuff
, pFormStr
, int( nMaxDig
), f
);
1075 // you never know which underlying implementation you get ...
1077 if ( nLen
< 0 || nLen
> nBuff
)
1078 nLen
= strlen( aBuff
);
1080 STRING
aRet( aBuff
, nLen
, RTL_TEXTENCODING_MS_1252
);
1086 double GetAmordegrc( sal_Int32 nNullDate
, double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
,
1087 double fRestVal
, double fPer
, double fRate
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1092 sal_uInt32 nPer
= sal_uInt32( fPer
);
1093 double fUsePer
= 1.0 / fRate
;
1098 else if( fUsePer
< 5.0 )
1100 else if( fUsePer
<= 6.0 )
1105 fRate
*= fAmorCoeff
;
1106 double fNRate
= ::rtl::math::round( GetYearFrac( nNullDate
, nDate
, nFirstPer
, nBase
) * fRate
* fCost
, 0 );
1108 double fRest
= fCost
- fRestVal
; // Anschaffungskosten - Restwert - Summe aller Abschreibungen
1110 for( sal_uInt32 n
= 0 ; n
< nPer
; n
++ )
1112 fNRate
= ::rtl::math::round( fRate
* fCost
, 0 );
1121 return ::rtl::math::round( fCost
* 0.5, 0 );
1134 double GetAmorlinc( sal_Int32 nNullDate
, double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
,
1135 double fRestVal
, double fPer
, double fRate
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1140 sal_uInt32 nPer
= sal_uInt32( fPer
);
1141 double fOneRate
= fCost
* fRate
;
1142 double fCostDelta
= fCost
- fRestVal
;
1143 double f0Rate
= GetYearFrac( nNullDate
, nDate
, nFirstPer
, nBase
) * fRate
* fCost
;
1144 sal_uInt32 nNumOfFullPeriods
= sal_uInt32( ( fCost
- fRestVal
- f0Rate
) / fOneRate
);
1148 else if( nPer
<= nNumOfFullPeriods
)
1150 else if( nPer
== nNumOfFullPeriods
+ 1 )
1151 return fCostDelta
- fOneRate
* nNumOfFullPeriods
- f0Rate
;
1157 double GetDuration( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
,
1158 double fYield
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1160 double fYearfrac
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
);
1161 double fNumOfCoups
= GetCoupnum( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1163 const double f100
= 100.0;
1164 fCoup
*= f100
/ double( nFreq
); // fCoup is used as cash flow
1168 double nDiff
= fYearfrac
* nFreq
- fNumOfCoups
;
1172 for( t
= 1.0 ; t
< fNumOfCoups
; t
++ )
1173 fDur
+= ( t
+ nDiff
) * ( fCoup
) / pow( fYield
, t
+ nDiff
);
1175 fDur
+= ( fNumOfCoups
+ nDiff
) * ( fCoup
+ f100
) / pow( fYield
, fNumOfCoups
+ nDiff
);
1178 for( t
= 1.0 ; t
< fNumOfCoups
; t
++ )
1179 p
+= fCoup
/ pow( fYield
, t
+ nDiff
);
1181 p
+= ( fCoup
+ f100
) / pow( fYield
, fNumOfCoups
+ nDiff
);
1184 fDur
/= double( nFreq
);
1190 double GetYieldmat( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nIssue
,
1191 double fRate
, double fPrice
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1193 double fIssMat
= GetYearFrac( nNullDate
, nIssue
, nMat
, nBase
);
1194 double fIssSet
= GetYearFrac( nNullDate
, nIssue
, nSettle
, nBase
);
1195 double fSetMat
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
);
1197 double y
= 1.0 + fIssMat
* fRate
;
1198 y
/= fPrice
/ 100.0 + fIssSet
* fRate
;
1206 double GetOddfprice( sal_Int32
/*nNullDate*/, sal_Int32
/*nSettle*/, sal_Int32
/*nMat*/, sal_Int32
/*nIssue*/,
1207 sal_Int32
/*nFirstCoup*/, double /*fRate*/, double /*fYield*/, double /*fRedemp*/, sal_Int32
/*nFreq*/,
1208 sal_Int32
/*nBase*/ ) THROWDEF_RTE_IAE
1210 THROW_RTE
; // #87380#
1212 double fN = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase ) - 1.0;
1213 double fNq = GetCoupnum( nNullDate, nSettle, nFirstCoup, nFreq, nBase ) - 1.0;
1214 double fDSC = GetCoupdaysnc( nNullDate, nSettle, nFirstCoup, nFreq, nBase );
1215 double fDSC_E = fDSC / GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase );
1216 double fNC = GetCoupnum( nNullDate, nIssue, nFirstCoup, nFreq, nBase );
1217 sal_uInt32 nNC = sal_uInt32( fNC );
1218 sal_uInt16 nMonthDelta = 12 / sal_uInt16( nFreq );
1221 double f1YieldFreq = 1.0 + fYield / double( nFreq );
1222 double f100RateFreq = 100.0 * fRate / double( nFreq );
1224 double* pDC = new double[ nNC + 1 ];
1225 double* pNL = new double[ nNC + 1 ];
1226 double* pA = new double[ nNC + 1 ];
1228 pDC[ 0 ] = pNL[ 0 ] = pA[ 0 ] = 1.0;
1230 ScaDate aStartDate( nNullDate, nSettle, nBase );
1231 ScaDate aNextCoup( nNullDate, nFirstCoup, nBase );
1234 pDC[ 1 ] = ScaDate::GetDiff( aStartDate, aNextCoup );
1235 pNL[ 1 ] = GetCoupdays( nNullDate, nSettle, nFirstCoup, nFreq, nBase );
1238 for( i = 1 ; i <= nNC ; i++ )
1241 aStartDate.addMonths( nMonthDelta );
1242 aNextCoup.addMonths( nMonthDelta );
1243 pDC[ i ] = ScaDate::GetDiff( aPre, aStartDate );
1244 pNL[ i ] = GetCoupdays( nNullDate, aStartDate.GetDate( nNullDate ), aNextCoup.GetDate( nNullDate ),
1246 pA[ i ] = ScaDate::GetDiff( aStartDate, aNextCoup );
1250 double fT1 = fRedemp / pow( f1YieldFreq, fN + fNq + fDSC_E );
1253 for( i = 1 ; i <= nNC ; i++ )
1254 fT2 += pDC[ i ] / pNL[ i ];
1255 fT2 *= f100RateFreq / pow( f1YieldFreq, fNq + fDSC_E );
1258 for( double k = 2.0 ; k <= fN ; k++ )
1259 fT3 += 1.0 / pow( f1YieldFreq, k - fNq + fDSC_E );
1260 fT3 *= f100RateFreq;
1263 for( i = 1 ; i <= nNC ; i++ )
1264 fT4 += pA[ i ] / pNL[ i ];
1265 fT4 *= f100RateFreq;
1274 return fT1 + fT2 + fT3 - fT4;
1279 double getYield_( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
, double fPrice
,
1280 double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1282 double fRate
= fCoup
;
1283 double fPriceN
= 0.0;
1284 double fYield1
= 0.0;
1285 double fYield2
= 1.0;
1286 double fPrice1
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield1
, fRedemp
, nFreq
, nBase
);
1287 double fPrice2
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield2
, fRedemp
, nFreq
, nBase
);
1288 double fYieldN
= ( fYield2
- fYield1
) * 0.5;
1290 for( sal_uInt32 nIter
= 0 ; nIter
< 100 && fPriceN
!= fPrice
; nIter
++ )
1292 fPriceN
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYieldN
, fRedemp
, nFreq
, nBase
);
1294 if( fPrice
== fPrice1
)
1296 else if( fPrice
== fPrice2
)
1298 else if( fPrice
== fPriceN
)
1300 else if( fPrice
< fPrice2
)
1303 fPrice2
= getPrice_( nNullDate
, nSettle
, nMat
, fRate
, fYield2
, fRedemp
, nFreq
, nBase
);
1305 fYieldN
= ( fYield2
- fYield1
) * 0.5;
1309 if( fPrice
< fPriceN
)
1320 fYieldN
= fYield2
- ( fYield2
- fYield1
) * ( ( fPrice
- fPrice2
) / ( fPrice1
- fPrice2
) );
1324 if( fabs( fPrice
- fPriceN
) > fPrice
/ 100.0 )
1325 THROW_IAE
; // result not precise enough
1331 double getPrice_( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, double fRate
, double fYield
,
1332 double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1334 double fFreq
= nFreq
;
1336 double fE
= GetCoupdays( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1337 double fDSC_E
= GetCoupdaysnc( nNullDate
, nSettle
, nMat
, nFreq
, nBase
) / fE
;
1338 double fN
= GetCoupnum( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1339 double fA
= GetCoupdaybs( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1341 double fRet
= fRedemp
/ ( pow( 1.0 + fYield
/ fFreq
, fN
- 1.0 + fDSC_E
) );
1342 fRet
-= 100.0 * fRate
/ fFreq
* fA
/ fE
;
1344 double fT1
= 100.0 * fRate
/ fFreq
;
1345 double fT2
= 1.0 + fYield
/ fFreq
;
1347 for( double fK
= 0.0 ; fK
< fN
; fK
++ )
1348 fRet
+= fT1
/ pow( fT2
, fK
+ fDSC_E
);
1354 double GetOddfyield( sal_Int32
/*nNullDate*/, sal_Int32
/*nSettle*/, sal_Int32
/*nMat*/, sal_Int32
/*nIssue*/,
1355 sal_Int32
/*nFirstCoup*/, double /*fRate*/, double /*fPrice*/, double /*fRedemp*/, sal_Int32
/*nFreq*/,
1356 sal_Int32
/*nBase*/ ) THROWDEF_RTE_IAE
1358 THROW_RTE
; // #87380#
1360 //GetOddfprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue,
1361 //sal_Int32 nFirstCoup, double fRate, double fYield, double fRedemp, sal_Int32 nFreq,
1363 double fPriceN = 0.0;
1364 double fYield1 = 0.0;
1365 double fYield2 = 1.0;
1366 double fPrice1 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield1, fRedemp, nFreq, nBase );
1367 double fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase );
1368 double fYieldN = ( fYield2 - fYield1 ) * 0.5;
1370 for( sal_uInt32 nIter = 0 ; nIter < 100 && fPriceN != fPrice ; nIter++ )
1372 fPriceN = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYieldN, fRedemp, nFreq, nBase );
1374 if( fPrice == fPrice1 )
1376 else if( fPrice == fPrice2 )
1378 else if( fPrice == fPriceN )
1380 else if( fPrice < fPrice2 )
1383 fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase );
1385 fYieldN = ( fYield2 - fYield1 ) * 0.5;
1389 if( fPrice < fPriceN )
1400 fYieldN = fYield2 - ( fYield2 - fYield1 ) * ( ( fPrice - fPrice2 ) / ( fPrice1 - fPrice2 ) );
1404 if( fabs( fPrice - fPriceN ) > fPrice / 100.0 )
1405 THROW_IAE; // result not precise enough
1412 double GetOddlprice( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastCoup
,
1413 double fRate
, double fYield
, double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1415 double fFreq
= double( nFreq
);
1416 double fDCi
= GetYearFrac( nNullDate
, nLastCoup
, nMat
, nBase
) * fFreq
;
1417 double fDSCi
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
) * fFreq
;
1418 double fAi
= GetYearFrac( nNullDate
, nLastCoup
, nSettle
, nBase
) * fFreq
;
1420 double p
= fRedemp
+ fDCi
* 100.0 * fRate
/ fFreq
;
1421 p
/= fDSCi
* fYield
/ fFreq
+ 1.0;
1422 p
-= fAi
* 100.0 * fRate
/ fFreq
;
1428 double GetOddlyield( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastCoup
,
1429 double fRate
, double fPrice
, double fRedemp
, sal_Int32 nFreq
, sal_Int32 nBase
) THROWDEF_RTE_IAE
1431 double fFreq
= double( nFreq
);
1432 double fDCi
= GetYearFrac( nNullDate
, nLastCoup
, nMat
, nBase
) * fFreq
;
1433 double fDSCi
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
) * fFreq
;
1434 double fAi
= GetYearFrac( nNullDate
, nLastCoup
, nSettle
, nBase
) * fFreq
;
1436 double y
= fRedemp
+ fDCi
* 100.0 * fRate
/ fFreq
;
1437 y
/= fPrice
+ fAi
* 100.0 * fRate
/ fFreq
;
1445 double GetRmz( double fZins
, double fZzr
, double fBw
, double fZw
, sal_Int32 nF
)
1449 fRmz
= ( fBw
+ fZw
) / fZzr
;
1452 double fTerm
= pow( 1.0 + fZins
, fZzr
);
1454 fRmz
= ( fZw
* fZins
/ ( fTerm
- 1.0 ) + fBw
* fZins
/ ( 1.0 - 1.0 / fTerm
) ) / ( 1.0 + fZins
);
1456 fRmz
= fZw
* fZins
/ ( fTerm
- 1.0 ) + fBw
* fZins
/ ( 1.0 - 1.0 / fTerm
);
1463 double GetZw( double fZins
, double fZzr
, double fRmz
, double fBw
, sal_Int32 nF
)
1467 fZw
= fBw
+ fRmz
* fZzr
;
1470 double fTerm
= pow( 1.0 + fZins
, fZzr
);
1472 fZw
= fBw
* fTerm
+ fRmz
* ( 1.0 + fZins
) * ( fTerm
- 1.0 ) / fZins
;
1474 fZw
= fBw
* fTerm
+ fRmz
* ( fTerm
- 1.0 ) / fZins
;
1481 /*double TBillYield( constREFXPS& xOpt, sal_Int32 nSettle, sal_Int32 nMat, double fPrice ) THROWDEF_RTE_IAE
1483 sal_Int32 nDiff = GetDiffDate360( xOpt, nSettle, nMat, sal_True );
1485 if( fPrice <= 0.0 || nSettle >= nMat || nDiff > 360 )
1488 double fRet = 100.0;
1491 fRet *= double( nDiff );
1498 //-----------------------------------------------------------------------------
1499 // financial functions COUP***
1503 // COUPPCD: find last coupon date before settlement (can be equal to settlement)
1504 void lcl_GetCouppcd( ScaDate
& rDate
, const ScaDate
& rSettle
, const ScaDate
& rMat
, sal_Int32 nFreq
)
1505 throw( lang::IllegalArgumentException
)
1508 rDate
.setYear( rSettle
.getYear() );
1509 if( rDate
< rSettle
)
1510 rDate
.addYears( 1 );
1511 while( rDate
> rSettle
)
1512 rDate
.addMonths( -12 / nFreq
);
1515 double GetCouppcd( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1518 if( nSettle
>= nMat
|| CHK_Freq
)
1522 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1523 return aDate
.getDate( nNullDate
);
1528 // COUPNCD: find first coupon date after settlement (is never equal to settlement)
1529 void lcl_GetCoupncd( ScaDate
& rDate
, const ScaDate
& rSettle
, const ScaDate
& rMat
, sal_Int32 nFreq
)
1530 throw( lang::IllegalArgumentException
)
1533 rDate
.setYear( rSettle
.getYear() );
1534 if( rDate
> rSettle
)
1535 rDate
.addYears( -1 );
1536 while( rDate
<= rSettle
)
1537 rDate
.addMonths( 12 / nFreq
);
1540 double GetCoupncd( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1543 if( nSettle
>= nMat
|| CHK_Freq
)
1547 lcl_GetCoupncd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1548 return aDate
.getDate( nNullDate
);
1553 // COUPDAYBS: get day count: coupon date before settlement <-> settlement
1554 double GetCoupdaybs( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1557 if( nSettle
>= nMat
|| CHK_Freq
)
1560 ScaDate
aSettle( nNullDate
, nSettle
, nBase
);
1562 lcl_GetCouppcd( aDate
, aSettle
, ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1563 return ScaDate::getDiff( aDate
, aSettle
);
1568 // COUPDAYSNC: get day count: settlement <-> coupon date after settlement
1569 double GetCoupdaysnc( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1572 if( nSettle
>= nMat
|| CHK_Freq
)
1575 if( (nBase
!= 0) && (nBase
!= 4) )
1577 ScaDate
aSettle( nNullDate
, nSettle
, nBase
);
1579 lcl_GetCoupncd( aDate
, aSettle
, ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1580 return ScaDate::getDiff( aSettle
, aDate
);
1582 return GetCoupdays( nNullDate
, nSettle
, nMat
, nFreq
, nBase
) - GetCoupdaybs( nNullDate
, nSettle
, nMat
, nFreq
, nBase
);
1587 // COUPDAYS: get day count: coupon date before settlement <-> coupon date after settlement
1588 double GetCoupdays( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1591 if( nSettle
>= nMat
|| CHK_Freq
)
1597 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), ScaDate( nNullDate
, nMat
, nBase
), nFreq
);
1598 ScaDate
aNextDate( aDate
);
1599 aNextDate
.addMonths( 12 / nFreq
);
1600 return ScaDate::getDiff( aDate
, aNextDate
);
1602 return static_cast< double >( GetDaysInYear( 0, 0, nBase
) ) / nFreq
;
1607 // COUPNUM: get count of coupon dates
1608 double GetCoupnum( sal_Int32 nNullDate
, sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, sal_Int32 nBase
)
1611 if( nSettle
>= nMat
|| CHK_Freq
)
1614 ScaDate
aMat( nNullDate
, nMat
, nBase
);
1616 lcl_GetCouppcd( aDate
, ScaDate( nNullDate
, nSettle
, nBase
), aMat
, nFreq
);
1617 sal_uInt16 nMonths
= (aMat
.getYear() - aDate
.getYear()) * 12 + aMat
.getMonth() - aDate
.getMonth();
1618 return static_cast< double >( nMonths
* nFreq
/ 12 );
1627 const sal_uInt32
MyList::nStartSize
= 16;
1628 const sal_uInt32
MyList::nIncrSize
= 16;
1631 void MyList::_Grow( void )
1635 void** pNewData
= new void*[ nSize
];
1636 memcpy( pNewData
, pData
, nNew
* sizeof( void* ) );
1643 MyList::MyList( void )
1646 pData
= new void*[ nSize
];
1657 void MyList::Insert( void* p
, sal_uInt32 n
)
1665 void** pIns
= pData
+ n
;
1666 memmove( pIns
+ 1, pIns
, ( nNew
- n
) * sizeof( void* ) );
1677 StringList::~StringList()
1679 for( STRING
* p
= ( STRING
* ) First() ; p
; p
= ( STRING
* ) Next() )
1684 class AnalysisRscStrArrLoader
: public Resource
1687 ResStringArray aStrArray
;
1689 AnalysisRscStrArrLoader( sal_uInt16 nRsc
, sal_uInt16 nArrayId
, ResMgr
& rResMgr
) :
1690 Resource( AnalysisResId( nRsc
, rResMgr
) ),
1691 aStrArray( AnalysisResId( nArrayId
, rResMgr
) )
1696 const ResStringArray
& GetStringArray() const { return aStrArray
; }
1702 FuncData::FuncData( const FuncDataBase
& r
, ResMgr
& rResMgr
) :
1703 aIntName( OUString::createFromAscii( r
.pIntName
) ),
1704 nUINameID( r
.nUINameID
),
1705 nDescrID( r
.nDescrID
),
1706 bDouble( r
.bDouble
),
1707 bWithOpt( r
.bWithOpt
),
1708 nParam( r
.nNumOfParams
),
1709 nCompID( r
.nCompListID
),
1712 AnalysisRscStrArrLoader
aArrLoader( RID_ANALYSIS_DEFFUNCTION_NAMES
, nCompID
, rResMgr
);
1713 // ResStringArray aDefFuncNameArray( AnalysisResId( nCompID, rResMgr ) );
1714 const ResStringArray
& rArr
= aArrLoader
.GetStringArray();
1716 sal_uInt16 nCount
= sal::static_int_cast
<sal_uInt16
>( rArr
.Count() );
1719 for( n
= 0 ; n
< nCount
; n
++ )
1720 aCompList
.Append( rArr
.GetString( n
) );
1724 FuncData::~FuncData()
1729 sal_uInt16
FuncData::GetStrIndex( sal_uInt16 nParamNum
) const
1734 if( nParamNum
> nParam
)
1737 return nParamNum
* 2;
1743 FuncDataList::FuncDataList( ResMgr
& rResMgr
)
1745 const sal_uInt32 nNum
= sizeof( pFuncDatas
) / sizeof( FuncDataBase
);
1747 for( sal_uInt16 n
= 0 ; n
< nNum
; n
++ )
1748 Append( new FuncData( pFuncDatas
[ n
], rResMgr
) );
1752 FuncDataList::~FuncDataList()
1754 for( FuncData
* p
= ( FuncData
* ) First() ; p
; p
= ( FuncData
* ) Next() )
1759 const FuncData
* FuncDataList::Get( const OUString
& aProgrammaticName
) const
1761 if( aLastName
== aProgrammaticName
)
1762 return Get( nLast
);
1764 ( ( FuncDataList
* ) this )->aLastName
= aProgrammaticName
;
1766 sal_uInt32 nE
= Count();
1767 for( sal_uInt32 n
= 0 ; n
< nE
; n
++ )
1769 const FuncData
* p
= Get( n
);
1770 if( p
->Is( aProgrammaticName
) )
1772 ( ( FuncDataList
* ) this )->nLast
= n
;
1777 ( ( FuncDataList
* ) this )->nLast
= 0xFFFFFFFF;
1782 AnalysisResId::AnalysisResId( sal_uInt16 nId
, ResMgr
& rResMgr
) : ResId( nId
, rResMgr
)
1789 SortedIndividualInt32List::SortedIndividualInt32List()
1794 SortedIndividualInt32List::~SortedIndividualInt32List()
1799 void SortedIndividualInt32List::Insert( sal_Int32 nDay
)
1801 sal_uInt32 nIndex
= Count();
1805 sal_Int32 nRef
= Get( nIndex
);
1808 else if( nDay
> nRef
)
1810 MyList::Insert( (void*) nDay
, nIndex
+ 1 );
1814 MyList::Insert( (void*) nDay
, 0UL );
1818 void SortedIndividualInt32List::Insert( sal_Int32 nDay
, sal_Int32 nNullDate
, sal_Bool bInsertOnWeekend
)
1824 if( bInsertOnWeekend
|| (GetDayOfWeek( nDay
) < 5) )
1829 void SortedIndividualInt32List::Insert(
1830 double fDay
, sal_Int32 nNullDate
, sal_Bool bInsertOnWeekend
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1832 if( (fDay
< -2147483648.0) || (fDay
> 2147483649.0) )
1833 throw lang::IllegalArgumentException();
1834 Insert( static_cast< sal_Int32
>( fDay
), nNullDate
, bInsertOnWeekend
);
1838 sal_Bool
SortedIndividualInt32List::Find( sal_Int32 nVal
) const
1840 sal_uInt32 nE
= Count();
1842 if( !nE
|| nVal
< Get( 0 ) || nVal
> Get( nE
- 1 ) )
1847 for( sal_uInt32 n
= 0 ; n
< nE
; n
++ )
1849 sal_Int32 nRef
= Get( n
);
1853 else if( nRef
> nVal
)
1860 void SortedIndividualInt32List::InsertHolidayList(
1861 const ScaAnyConverter
& rAnyConv
,
1862 const uno::Any
& rHolAny
,
1863 sal_Int32 nNullDate
,
1864 sal_Bool bInsertOnWeekend
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1867 if( rAnyConv
.getDouble( fDay
, rHolAny
) )
1868 Insert( fDay
, nNullDate
, bInsertOnWeekend
);
1872 void SortedIndividualInt32List::InsertHolidayList(
1873 ScaAnyConverter
& rAnyConv
,
1874 const uno::Reference
< beans::XPropertySet
>& xOptions
,
1875 const uno::Any
& rHolAny
,
1876 sal_Int32 nNullDate
,
1877 sal_Bool bInsertOnWeekend
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1879 rAnyConv
.init( xOptions
);
1880 if( rHolAny
.getValueTypeClass() == uno::TypeClass_SEQUENCE
)
1882 uno::Sequence
< uno::Sequence
< uno::Any
> > aAnySeq
;
1883 if( rHolAny
>>= aAnySeq
)
1885 const uno::Sequence
< uno::Any
>* pSeqArray
= aAnySeq
.getConstArray();
1886 for( sal_Int32 nIndex1
= 0; nIndex1
< aAnySeq
.getLength(); nIndex1
++ )
1888 const uno::Sequence
< uno::Any
>& rSubSeq
= pSeqArray
[ nIndex1
];
1889 const uno::Any
* pAnyArray
= rSubSeq
.getConstArray();
1891 for( sal_Int32 nIndex2
= 0; nIndex2
< rSubSeq
.getLength(); nIndex2
++ )
1892 InsertHolidayList( rAnyConv
, pAnyArray
[ nIndex2
], nNullDate
, bInsertOnWeekend
);
1896 throw lang::IllegalArgumentException();
1899 InsertHolidayList( rAnyConv
, rHolAny
, nNullDate
, bInsertOnWeekend
);
1904 //-----------------------------------------------------------------------------
1906 ScaDoubleList::~ScaDoubleList()
1908 for( double* pDbl
= const_cast< double* >( First() ); pDbl
; pDbl
= const_cast< double* >( Next() ) )
1913 void ScaDoubleList::Append(
1914 const uno::Sequence
< uno::Sequence
< double > >& rValueSeq
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1916 const uno::Sequence
< double >* pSeqArray
= rValueSeq
.getConstArray();
1917 for( sal_Int32 nIndex1
= 0; nIndex1
< rValueSeq
.getLength(); nIndex1
++ )
1919 const uno::Sequence
< double >& rSubSeq
= pSeqArray
[ nIndex1
];
1920 const double* pArray
= rSubSeq
.getConstArray();
1921 for( sal_Int32 nIndex2
= 0; nIndex2
< rSubSeq
.getLength(); nIndex2
++ )
1922 Append( pArray
[ nIndex2
] );
1927 void ScaDoubleList::Append(
1928 const uno::Sequence
< uno::Sequence
< sal_Int32
> >& rValueSeq
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1930 const uno::Sequence
< sal_Int32
>* pSeqArray
= rValueSeq
.getConstArray();
1931 for( sal_Int32 nIndex1
= 0; nIndex1
< rValueSeq
.getLength(); nIndex1
++ )
1933 const uno::Sequence
< sal_Int32
>& rSubSeq
= pSeqArray
[ nIndex1
];
1934 const sal_Int32
* pArray
= rSubSeq
.getConstArray();
1935 for( sal_Int32 nIndex2
= 0; nIndex2
< rSubSeq
.getLength(); nIndex2
++ )
1936 Append( pArray
[ nIndex2
] );
1942 void ScaDoubleList::Append(
1943 const ScaAnyConverter
& rAnyConv
,
1944 const uno::Any
& rAny
,
1945 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1947 if( rAny
.getValueTypeClass() == uno::TypeClass_SEQUENCE
)
1948 Append( rAnyConv
, *static_cast< const uno::Sequence
< uno::Sequence
< uno::Any
> >* >( rAny
.getValue() ), bIgnoreEmpty
);
1952 if( rAnyConv
.getDouble( fValue
, rAny
) )
1954 else if( !bIgnoreEmpty
)
1960 void ScaDoubleList::Append(
1961 const ScaAnyConverter
& rAnyConv
,
1962 const uno::Sequence
< uno::Any
>& rAnySeq
,
1963 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1965 const uno::Any
* pArray
= rAnySeq
.getConstArray();
1966 for( sal_Int32 nIndex
= 0; nIndex
< rAnySeq
.getLength(); nIndex
++ )
1967 Append( rAnyConv
, pArray
[ nIndex
], bIgnoreEmpty
);
1971 void ScaDoubleList::Append(
1972 const ScaAnyConverter
& rAnyConv
,
1973 const uno::Sequence
< uno::Sequence
< uno::Any
> >& rAnySeq
,
1974 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1976 const uno::Sequence
< uno::Any
>* pArray
= rAnySeq
.getConstArray();
1977 for( sal_Int32 nIndex
= 0; nIndex
< rAnySeq
.getLength(); nIndex
++ )
1978 Append( rAnyConv
, pArray
[ nIndex
], bIgnoreEmpty
);
1983 void ScaDoubleList::Append(
1984 ScaAnyConverter
& rAnyConv
,
1985 const uno::Reference
< beans::XPropertySet
>& xOpt
,
1986 const uno::Sequence
< uno::Any
>& rAnySeq
,
1987 sal_Bool bIgnoreEmpty
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
1989 rAnyConv
.init( xOpt
);
1990 Append( rAnyConv
, rAnySeq
, bIgnoreEmpty
);
1994 sal_Bool
ScaDoubleList::CheckInsert( double ) const throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2001 //-----------------------------------------------------------------------------
2003 sal_Bool
ScaDoubleListGT0::CheckInsert( double fValue
) const throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2006 throw lang::IllegalArgumentException();
2007 return fValue
> 0.0;
2012 //-----------------------------------------------------------------------------
2014 sal_Bool
ScaDoubleListGE0::CheckInsert( double fValue
) const throw( uno::RuntimeException
, lang::IllegalArgumentException
)
2017 throw lang::IllegalArgumentException();
2023 //-----------------------------------------------------------------------------
2025 Complex::Complex( const STRING
& rStr
) THROWDEF_RTE_IAE
2027 if( !ParseString( rStr
, *this ) )
2032 inline sal_Bool
Complex::IsImagUnit( sal_Unicode c
)
2034 return c
== 'i' || c
== 'j';
2037 sal_Bool
Complex::ParseString( const STRING
& rStr
, Complex
& rCompl
)
2039 rCompl
.c
= '\0'; // do not force a symbol, if only real part present
2041 const sal_Unicode
* pStr
= ( const sal_Unicode
* ) rStr
;
2043 if( IsImagUnit( *pStr
) && rStr
.getLength() == 1)
2053 if( !ParseDouble( pStr
, f
) )
2058 case '-': // imag part follows
2062 if( IsImagUnit( pStr
[ 1 ] ) )
2064 rCompl
.c
= pStr
[ 1 ];
2065 if( pStr
[ 2 ] == 0 )
2068 rCompl
.i
= ( *pStr
== '+' )? 1.0 : -1.0;
2072 else if( ParseDouble( pStr
, f
) && IsImagUnit( *pStr
) )
2096 case 0: // only real-part
2106 STRING
Complex::GetString() const THROWDEF_RTE_IAE
2108 static const String
aI( 'i' );
2109 static const String
aJ( 'j' );
2110 static const String
aPlus( '+' );
2111 static const String
aMinus( '-' );
2117 bool bHasImag
= i
!= 0.0;
2118 bool bHasReal
= !bHasImag
|| (r
!= 0.0);
2121 aRet
= ::GetString( r
);
2129 else if( i
== -1.0 )
2132 aRet
+= ::GetString( i
, bHasReal
);
2133 aRet
+= (c
!= 'j') ? aI
: aJ
;
2140 double Complex::Arg( void ) const THROWDEF_RTE_IAE
2142 if( r
== 0.0 && i
== 0.0 )
2145 double phi
= acos( r
/ Abs() );
2154 void Complex::Power( double fPower
) THROWDEF_RTE_IAE
2156 if( r
== 0.0 && i
== 0.0 )
2171 phi
= acos( r
/ p
);
2175 p
= pow( p
, fPower
);
2183 void Complex::Sqrt( void )
2185 static const double fMultConst
= 0.7071067811865475; // ...2440084436210485 = 1/sqrt(2)
2187 double i_
= sqrt( p
- r
) * fMultConst
;
2189 r
= sqrt( p
+ r
) * fMultConst
;
2190 i
= ( i
< 0.0 )? -i_
: i_
;
2194 inline BOOL
SinOverflow( double f
)
2196 return fabs( f
) >= 134217728;
2200 void Complex::Sin( void ) THROWDEF_RTE_IAE
2202 if( SinOverflow( r
) )
2209 r_
= sin( r
) * cosh( i
);
2210 i
= cos( r
) * sinh( i
);
2218 void Complex::Cos( void ) THROWDEF_RTE_IAE
2220 if( SinOverflow( r
) )
2227 r_
= cos( r
) * cosh( i
);
2228 i
= -( sin( r
) * sinh( i
) );
2236 void Complex::Div( const Complex
& z
) THROWDEF_RTE_IAE
2238 if( z
.r
== 0 && z
.i
== 0 )
2246 double f
= 1.0 / ( a2
* a2
+ b2
* b2
);
2248 r
= ( a1
* a2
+ b1
* b2
) * f
;
2249 i
= ( a2
* b1
- a1
* b2
) * f
;
2255 void Complex::Exp( void )
2257 double fE
= exp( r
);
2263 void Complex::Ln( void ) THROWDEF_RTE_IAE
2265 if( r
== 0.0 && i
== 0.0 )
2268 double fAbs
= Abs();
2269 sal_Bool bNegi
= i
< 0.0;
2271 i
= acos( r
/ fAbs
);
2280 void Complex::Log10( void ) THROWDEF_RTE_IAE
2283 Mult( 0.434294481903251828 ); // * log10( e )
2287 void Complex::Log2( void ) THROWDEF_RTE_IAE
2290 Mult( 1.442695040888963407 ); // * log2( e )
2296 ComplexList::~ComplexList()
2298 for( Complex
* p
= ( Complex
* ) First() ; p
; p
= ( Complex
* ) Next() )
2303 void ComplexList::Append( const SEQSEQ( STRING
)& r
, ComplListAppendHandl eAH
) THROWDEF_RTE_IAE
2306 sal_Int32 nE1
= r
.getLength();
2308 sal_Bool bEmpty0
= eAH
== AH_EmpyAs0
;
2309 sal_Bool bErrOnEmpty
= eAH
== AH_EmptyAsErr
;
2311 for( n1
= 0 ; n1
< nE1
; n1
++ )
2313 const SEQ( STRING
)& rList
= r
[ n1
];
2314 nE2
= rList
.getLength();
2316 for( n2
= 0 ; n2
< nE2
; n2
++ )
2318 const STRING
& rStr
= rList
[ n2
];
2320 if( rStr
.getLength() )
2321 Append( new Complex( rStr
) );
2323 Append( new Complex( 0.0 ) );
2324 else if( bErrOnEmpty
)
2331 void ComplexList::Append( const SEQ( ANY
)& aMultPars
, ComplListAppendHandl eAH
) THROWDEF_RTE_IAE
2333 sal_Int32 nEle
= aMultPars
.getLength();
2334 sal_Bool bEmpty0
= eAH
== AH_EmpyAs0
;
2335 sal_Bool bErrOnEmpty
= eAH
== AH_EmptyAsErr
;
2337 for( sal_Int32 i
= 0 ; i
< nEle
; i
++ )
2339 const ANY
& r
= aMultPars
[ i
];
2340 switch( r
.getValueTypeClass() )
2342 case uno::TypeClass_VOID
: break;
2343 case uno::TypeClass_STRING
:
2345 const STRING
* pStr
= ( const STRING
* ) r
.getValue();
2347 if( pStr
->getLength() )
2348 Append( new Complex( *( STRING
* ) r
.getValue() ) );
2350 Append( new Complex( 0.0 ) );
2351 else if( bErrOnEmpty
)
2355 case uno::TypeClass_DOUBLE
:
2356 Append( new Complex( *( double* ) r
.getValue(), 0.0 ) );
2358 case uno::TypeClass_SEQUENCE
:
2360 SEQSEQ( ANY
) aValArr
;
2363 sal_Int32 nE
= aValArr
.getLength();
2364 const SEQ( ANY
)* pArr
= aValArr
.getConstArray();
2365 for( sal_Int32 n
= 0 ; n
< nE
; n
++ )
2366 Append( pArr
[ n
], eAH
);
2381 ConvertData::ConvertData( const sal_Char p
[], double fC
, ConvertDataClass e
) : aName( p
, strlen( p
), RTL_TEXTENCODING_MS_1252
)
2387 ConvertData::~ConvertData()
2392 sal_Int16
ConvertData::GetMatchingLevel( const STRING
& rRef
) const
2394 if( aName
.equals( rRef
) )
2398 const sal_Unicode
* p
= rRef
.getStr();
2400 if ( aName
== p
+ 1 )
2405 case 'y': n
= -24; break; // yocto
2406 case 'z': n
= -21; break; // zepto
2407 case 'a': n
= -18; break;
2408 case 'f': n
= -15; break;
2409 case 'p': n
= -12; break;
2410 case 'n': n
= -9; break;
2411 case 'u': n
= -6; break;
2412 case 'm': n
= -3; break;
2413 case 'c': n
= -2; break;
2414 case 'd': n
= -1; break;
2415 case 'e': n
= 1; break;
2416 case 'h': n
= 2; break;
2417 case 'k': n
= 3; break;
2418 case 'M': n
= 6; break;
2419 case 'G': n
= 9; break;
2420 case 'T': n
= 12; break;
2421 case 'P': n
= 15; break;
2422 case 'E': n
= 18; break;
2423 case 'Z': n
= 21; break; // zetta
2424 case 'Y': n
= 24; break; // yotta
2429 //! <HACK> #100616# "cm3" is not 10^-2 m^3 but 10^-6 m^3 !!! ------------------
2430 if( n
!= INV_MATCHLEV
)
2432 sal_Unicode cLast
= p
[ rRef
.getLength() - 1 ];
2435 else if( cLast
== '3' )
2438 //! </HACK> -------------------------------------------------------------------
2443 return INV_MATCHLEV
;
2448 double ConvertData::Convert(
2449 double f
, const ConvertData
& r
, sal_Int16 nLevFrom
, sal_Int16 nLevTo
) const THROWDEF_RTE_IAE
2451 if( Class() != r
.Class() )
2454 nLevFrom
= sal::static_int_cast
<sal_Int16
>( nLevFrom
- nLevTo
); // effective level
2456 f
*= r
.fConst
/ fConst
;
2459 f
= ::rtl::math::pow10Exp( f
, nLevFrom
);
2465 double ConvertData::ConvertToBase( double f
, sal_Int16 n
) const
2467 return ::rtl::math::pow10Exp( f
/ fConst
, n
);
2471 double ConvertData::ConvertFromBase( double f
, sal_Int16 n
) const
2473 return ::rtl::math::pow10Exp( f
* fConst
, -n
);
2478 ConvertDataLinear::~ConvertDataLinear()
2482 double ConvertDataLinear::Convert(
2483 double f
, const ConvertData
& r
, sal_Int16 nLevFrom
, sal_Int16 nLevTo
) const THROWDEF_RTE_IAE
2485 if( Class() != r
.Class() )
2488 // return ::rtl::math::round( r.ConvertFromBase( ConvertToBase( f, nLevFrom ), nLevTo ), 13 );
2489 return r
.ConvertFromBase( ConvertToBase( f
, nLevFrom
), nLevTo
);
2493 double ConvertDataLinear::ConvertToBase( double f
, sal_Int16 n
) const
2496 f
= ::rtl::math::pow10Exp( f
, n
);
2505 double ConvertDataLinear::ConvertFromBase( double f
, sal_Int16 n
) const
2511 f
= ::rtl::math::pow10Exp( f
, -n
);
2519 ConvertDataList::ConvertDataList( void )
2521 #define NEWD(str,unit,cl) Append(new ConvertData(str,unit,cl))
2522 #define NEWL(str,unit,offs,cl) Append(new ConvertDataLinear(str,unit,offs,cl))
2524 // *** are extra and not standard Excel Analysis Addin!
2526 // MASS: 1 Gram is...
2527 NEWD( "g", 1.0000000000000000E00
, CDC_Mass
); // Gram
2528 NEWD( "sg", 6.8522050005347800E-05, CDC_Mass
); // Pieces
2529 NEWD( "lbm", 2.2046229146913400E-03, CDC_Mass
); // Pound (commercial weight)
2530 NEWD( "u", 6.0221370000000000E23
, CDC_Mass
); // U (atomic mass)
2531 NEWD( "ozm", 3.5273971800362700E-02, CDC_Mass
); // Ounce (commercial weight)
2532 NEWD( "stone", 1.574730e-04, CDC_Mass
); // *** Stone
2533 NEWD( "ton", 1.102311e-06, CDC_Mass
); // *** Ton
2534 NEWD( "grain", 1.543236E01
, CDC_Mass
); // *** Grain
2535 NEWD( "pweight", 7.054792E-01, CDC_Mass
); // *** Pennyweight
2536 NEWD( "hweight", 1.968413E-05, CDC_Mass
); // *** Hundredweight
2537 NEWD( "shweight", 2.204623E-05, CDC_Mass
); // *** Shorthundredweight
2538 NEWD( "brton", 9.842065E-07, CDC_Mass
); // *** Gross Registered Ton
2540 // LENGTH: 1 Meter is...
2541 NEWD( "m", 1.0000000000000000E00
, CDC_Length
); // Meter
2542 NEWD( "mi", 6.2137119223733397E-04, CDC_Length
); // Britsh Mile 6,21371192237333969617434184363e-4
2543 NEWD( "Nmi", 5.3995680345572354E-04, CDC_Length
); // Nautical Mile 5,39956803455723542116630669546e-4
2544 NEWD( "in", 3.9370078740157480E01
, CDC_Length
); // Inch 39,37007874015748031496062992126
2545 NEWD( "ft", 3.2808398950131234E00
, CDC_Length
); // Foot 3,2808398950131233595800524934383
2546 NEWD( "yd", 1.0936132983377078E00
, CDC_Length
); // Yard 1,0936132983377077865266841644794
2547 NEWD( "ang", 1.0000000000000000E10
, CDC_Length
); // Angstroem
2548 NEWD( "Pica", 2.8346456692913386E03
, CDC_Length
); // Pica (1/72 Inch) 2834,6456692913385826771653543307
2549 NEWD( "ell", 8.748906E-01, CDC_Length
); // *** Ell
2550 NEWD( "parsec", 3.240779E-17, CDC_Length
); // *** Parsec
2551 NEWD( "lightyear", 1.0570234557732930E-16, CDC_Length
); // *** Light Year
2553 // TIME: 1 Second is...
2554 NEWD( "yr", 3.1688087814028950E-08, CDC_Time
); // Year
2555 NEWD( "day", 1.1574074074074074E-05, CDC_Time
); // Day
2556 NEWD( "hr", 2.7777777777777778E-04, CDC_Time
); // Hour
2557 NEWD( "mn", 1.6666666666666667E-02, CDC_Time
); // Minute
2558 NEWD( "sec", 1.0000000000000000E00
, CDC_Time
); // Second
2560 // PRESSURE: 1 Pascal is...
2561 NEWD( "Pa", 1.0000000000000000E00
, CDC_Pressure
); // Pascal
2562 NEWD( "atm", 9.8692329999819300E-06, CDC_Pressure
); // Atmoshpere
2563 NEWD( "mmHg", 7.5006170799862700E-03, CDC_Pressure
); // mm Hg (Mercury)
2564 NEWD( "Torr", 7.5006380000000000E-03, CDC_Pressure
); // *** Torr
2565 NEWD( "psi", 1.4503770000000000E-04, CDC_Pressure
); // *** Psi
2567 // FORCE: 1 Newton is...
2568 NEWD( "N", 1.0000000000000000E00
, CDC_Force
); // Newton
2569 NEWD( "dyn", 1.0000000000000000E05
, CDC_Force
); // Dyn
2570 NEWD( "lbf", 2.24808923655339E-01, CDC_Force
); // Pound-Force
2571 NEWD( "pond", 1.019716E02
, CDC_Force
); // *** Pond
2573 // ENERGY: 1 Joule is...
2574 NEWD( "J", 1.0000000000000000E00
, CDC_Energy
); // Joule
2575 NEWD( "e", 1.0000000000000000E07
, CDC_Energy
); // Erg -> http://www.chemie.fu-berlin.de/chemistry/general/si.html
2576 // NEWD( "e", 9.99999519343231E06, CDC_Energy ); // Erg
2577 NEWD( "c", 2.3900624947346700E-01, CDC_Energy
); // Thermodynamical Calorie
2578 NEWD( "cal", 2.3884619064201700E-01, CDC_Energy
); // Calorie
2579 NEWD( "eV", 6.2414570000000000E18
, CDC_Energy
); // Electronvolt
2580 NEWD( "HPh", 3.7250611111111111E-07, CDC_Energy
); // Horsepower Hours
2581 // NEWD( "HPh", 3.72506430801000E-07, CDC_Energy ); // Horsepower Hours
2582 NEWD( "Wh", 2.7777777777777778E-04, CDC_Energy
); // Watt Hours
2583 NEWD( "flb", 2.37304222192651E01
, CDC_Energy
); // Foot Pound
2584 NEWD( "BTU", 9.4781506734901500E-04, CDC_Energy
); // British Thermal Unit
2586 // POWER: 1 Watt is...
2587 NEWD( "W", 1.0000000000000000E00
, CDC_Power
); // Watt
2588 NEWD( "HP", 1.341022E-03, CDC_Power
); // Horsepower
2589 NEWD( "PS", 1.359622E-03, CDC_Power
); // *** German Pferdestaerke
2590 // NEWD( "HP", 1.4102006031908E-03, CDC_Power ); // Excel seams to be a little bit wrong... either this doesn't fit to J -> HPh
2592 // MAGNETISM: 1 Tesla is...
2593 NEWD( "T", 1.0000000000000000E00
, CDC_Magnetism
); // Tesla
2594 NEWD( "ga", 1.0000000000000000E04
, CDC_Magnetism
); // Gauss
2596 // TEMERATURE: 1 Kelvin is...
2597 NEWL( "C", 1.0000000000000000E00
, -2.7315000000000000E02
, CDC_Temperature
); // Celsius
2598 NEWL( "F", 1.8000000000000000E00
, -2.5537222222222222E02
, CDC_Temperature
); // Fahrenheit
2599 NEWL( "K", 1.0000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // Kelvin
2600 NEWL( "Reau", 8.0000000000000000E-01, -2.7315000000000000E02
, CDC_Temperature
); // *** Reaumur
2601 NEWL( "Rank", 1.8000000000000000E00
, +0.0000000000000000E00
, CDC_Temperature
); // *** Rankine
2603 // VOLUMNE: 1 Liter is...
2604 NEWD( "tsp", 2.0284000000000000E02
, CDC_Volume
); // Teaspoon
2605 NEWD( "tbs", 6.7613333333333333E01
, CDC_Volume
); // Tablespoon
2606 NEWD( "oz", 3.3806666666666667E01
, CDC_Volume
); // Ounce Liquid
2607 NEWD( "cup", 4.2258333333333333E00
, CDC_Volume
); // Cup
2608 NEWD( "pt", 2.1129166666666667E00
, CDC_Volume
); // US Pint
2609 NEWD( "uk_pt", 1.75975569552166E00
, CDC_Volume
); // UK Pint
2610 NEWD( "qt", 1.0564583333333333E00
, CDC_Volume
); // Quart
2611 NEWD( "gal", 2.6411458333333333E-01, CDC_Volume
); // Gallone
2612 NEWD( "l", 1.0000000000000000E00
, CDC_Volume
); // Liter
2613 NEWD( "m3", 1.0000000000000000E-03, CDC_Volume
); // *** Cubic Meter
2614 NEWD( "mi3", 2.3991275857892772E-13, CDC_Volume
); // *** Cubic Britsh Mile
2615 NEWD( "Nmi3", 1.5742621468581148E-13, CDC_Volume
); // *** Cubic Nautical Mile
2616 NEWD( "in3", 6.1023744094732284E01
, CDC_Volume
); // *** Cubic Inch
2617 NEWD( "ft3", 3.5314666721488590E-02, CDC_Volume
); // *** Cubic Foot
2618 NEWD( "yd3", 1.3079506193143922E-03, CDC_Volume
); // *** Cubic Yard
2619 NEWD( "ang3", 1.0000000000000000E27
, CDC_Volume
); // *** Cubic Angstroem
2620 NEWD( "Pica3", 2.2776990435870636E07
, CDC_Volume
); // *** Cubic Pica
2621 NEWD( "barrel", 6.289811E-03, CDC_Volume
); // *** Barrel (=42gal?)
2622 NEWD( "bushel", 2.837759E-02, CDC_Volume
); // *** Bushel
2623 NEWD( "regton", 3.531467E-04, CDC_Volume
); // *** Register ton
2624 NEWD( "Schooner", 2.3529411764705882E00
, CDC_Volume
); // *** austr. Schooner
2625 NEWD( "Middy", 3.5087719298245614E00
, CDC_Volume
); // *** austr. Middy
2626 NEWD( "Glass", 5.0000000000000000E00
, CDC_Volume
); // *** austr. Glass
2627 NEWD( "Sixpack", 0.5, CDC_Volume
); // ***
2628 NEWD( "Humpen", 2.0, CDC_Volume
); // ***
2630 // 1 Square Meter is...
2631 NEWD( "m2", 1.0000000000000000E00
, CDC_Area
); // *** Square Meter
2632 NEWD( "mi2", 3.8610215854244585E-07, CDC_Area
); // *** Square Britsh Mile
2633 NEWD( "Nmi2", 2.9155334959812286E-07, CDC_Area
); // *** Square Nautical Mile
2634 NEWD( "in2", 1.5500031000062000E03
, CDC_Area
); // *** Square Inch
2635 NEWD( "ft2", 1.0763910416709722E01
, CDC_Area
); // *** Square Foot
2636 NEWD( "yd2", 1.1959900463010803E00
, CDC_Area
); // *** Square Yard
2637 NEWD( "ang2", 1.0000000000000000E20
, CDC_Area
); // *** Square Angstroem
2638 NEWD( "Pica2", 8.0352160704321409E06
, CDC_Area
); // *** Square Pica
2639 NEWD( "Morgen", 4.0000000000000000E-04, CDC_Area
); // *** Morgen
2640 NEWD( "ar", 1.000000E-02, CDC_Area
); // *** Ar
2641 NEWD( "acre", 2.471053815E-04, CDC_Area
); // *** Acre
2642 NEWD( "ha", 1.000000E-04, CDC_Area
); // *** Hectare
2643 NEWD( "Quadratlatschen",5.6689342403628117914,CDC_Area
); // ***
2645 // SPEED: 1 Meter per Second is...
2646 NEWD( "m/s", 1.0000000000000000E00
, CDC_Speed
); // *** Meters per Second
2647 NEWD( "m/h", 3.6000000000000000E03
, CDC_Speed
); // *** Meters per Hour
2648 NEWD( "mph", 2.2369362920544023E00
, CDC_Speed
); // *** Britsh Miles per Hour
2649 NEWD( "kn", 1.9438444924406048E00
, CDC_Speed
); // *** Knot = Nautical Miles per Hour
2650 NEWD( "admkn", 1.9438446603753486E00
, CDC_Speed
); // *** Admiralty Knot
2651 NEWD( "wahnsinnige Geschwindigkeit", 2.0494886343432328E-14, CDC_Speed
); // ***
2652 NEWD( "ludicrous speed", 2.0494886343432328E-14, CDC_Speed
); // ***
2653 NEWD( "laecherliche Geschwindigkeit", 4.0156958471424288E-06, CDC_Speed
); // ***
2654 NEWD( "ridiculous speed", 4.0156958471424288E-06, CDC_Speed
); // ***
2658 ConvertDataList::~ConvertDataList()
2660 for( ConvertData
* p
= First() ; p
; p
= Next() )
2665 double ConvertDataList::Convert( double fVal
, const STRING
& rFrom
, const STRING
& rTo
) THROWDEF_RTE_IAE
2667 // This will not catch illegal units
2668 // if( rFrom == rTo )
2671 ConvertData
* pFrom
= NULL
;
2672 ConvertData
* pTo
= NULL
;
2673 sal_Bool bSearchFrom
= sal_True
;
2674 sal_Bool bSearchTo
= sal_True
;
2675 sal_Int16 nLevelFrom
= 0;
2676 sal_Int16 nLevelTo
= 0;
2678 ConvertData
* p
= First();
2679 while( p
&& ( bSearchFrom
|| bSearchTo
) )
2683 sal_Int16 n
= p
->GetMatchingLevel( rFrom
);
2684 if( n
!= INV_MATCHLEV
)
2687 { // only first match for partial equality rulz a little bit more
2692 { // ... but exact match rulz most
2694 bSearchFrom
= sal_False
;
2702 sal_Int16 n
= p
->GetMatchingLevel( rTo
);
2703 if( n
!= INV_MATCHLEV
)
2706 { // only first match for partial equality rulz a little bit more
2711 { // ... but exact match rulz most
2713 bSearchTo
= sal_False
;
2723 return pFrom
->Convert( fVal
, *pTo
, nLevelFrom
, nLevelTo
);
2730 //-----------------------------------------------------------------------------
2732 ScaDate::ScaDate() :
2737 bLastDayMode( sal_True
),
2738 bLastDay( sal_False
),
2739 b30Days( sal_False
),
2740 bUSMode( sal_False
)
2744 ScaDate::ScaDate( sal_Int32 nNullDate
, sal_Int32 nDate
, sal_Int32 nBase
)
2746 DaysToDate( nNullDate
+ nDate
, nOrigDay
, nMonth
, nYear
);
2747 bLastDayMode
= (nBase
!= 5);
2748 bLastDay
= (nOrigDay
>= ::DaysInMonth( nMonth
, nYear
));
2749 b30Days
= (nBase
== 0) || (nBase
== 4);
2750 bUSMode
= (nBase
== 0);
2754 ScaDate::ScaDate( const ScaDate
& rCopy
) :
2755 nOrigDay( rCopy
.nOrigDay
),
2757 nMonth( rCopy
.nMonth
),
2758 nYear( rCopy
.nYear
),
2759 bLastDayMode( rCopy
.bLastDayMode
),
2760 bLastDay( rCopy
.bLastDay
),
2761 b30Days( rCopy
.b30Days
),
2762 bUSMode( rCopy
.bUSMode
)
2766 ScaDate
& ScaDate::operator=( const ScaDate
& rCopy
)
2768 if( this != &rCopy
)
2770 nOrigDay
= rCopy
.nOrigDay
;
2772 nMonth
= rCopy
.nMonth
;
2773 nYear
= rCopy
.nYear
;
2774 bLastDayMode
= rCopy
.bLastDayMode
;
2775 bLastDay
= rCopy
.bLastDay
;
2776 b30Days
= rCopy
.b30Days
;
2777 bUSMode
= rCopy
.bUSMode
;
2782 void ScaDate::setDay()
2786 // 30-days-mode: set nDay to 30 if original was last day in month
2787 nDay
= Min( nOrigDay
, static_cast< sal_uInt16
>( 30 ) );
2788 if( bLastDay
|| (nDay
>= ::DaysInMonth( nMonth
, nYear
)) )
2793 // set nDay to last day in this month if original was last day
2794 sal_uInt16 nLastDay
= ::DaysInMonth( nMonth
, nYear
);
2795 nDay
= bLastDay
? nLastDay
: Min( nOrigDay
, nLastDay
);
2799 sal_Int32
ScaDate::getDaysInMonthRange( sal_uInt16 nFrom
, sal_uInt16 nTo
) const
2806 nRet
= (nTo
- nFrom
+ 1) * 30;
2809 for( sal_uInt16 nMonthIx
= nFrom
; nMonthIx
<= nTo
; ++nMonthIx
)
2810 nRet
+= getDaysInMonth( nMonthIx
);
2815 sal_Int32
ScaDate::getDaysInYearRange( sal_uInt16 nFrom
, sal_uInt16 nTo
) const
2820 return b30Days
? ((nTo
- nFrom
+ 1) * 360) : ::GetDaysInYears( nFrom
, nTo
);
2823 void ScaDate::doAddYears( sal_Int32 nYearCount
) throw( lang::IllegalArgumentException
)
2825 sal_Int32 nNewYear
= nYearCount
+ nYear
;
2826 if( (nNewYear
< 0) || (nNewYear
> 0x7FFF) )
2827 throw lang::IllegalArgumentException();
2828 nYear
= static_cast< sal_uInt16
>( nNewYear
);
2831 void ScaDate::addMonths( sal_Int32 nMonthCount
) throw( lang::IllegalArgumentException
)
2833 sal_Int32 nNewMonth
= nMonthCount
+ nMonth
;
2834 if( nNewMonth
> 12 )
2837 doAddYears( nNewMonth
/ 12 );
2838 nMonth
= static_cast< sal_uInt16
>( nNewMonth
% 12 ) + 1;
2840 else if( nNewMonth
< 1 )
2842 doAddYears( nNewMonth
/ 12 - 1 );
2843 nMonth
= static_cast< sal_uInt16
>( nNewMonth
% 12 + 12 );
2846 nMonth
= static_cast< sal_uInt16
>( nNewMonth
);
2850 sal_Int32
ScaDate::getDate( sal_Int32 nNullDate
) const
2852 sal_uInt16 nLastDay
= ::DaysInMonth( nMonth
, nYear
);
2853 sal_uInt16 nRealDay
= (bLastDayMode
&& bLastDay
) ? nLastDay
: Min( nLastDay
, nOrigDay
);
2854 return ::DateToDays( nRealDay
, nMonth
, nYear
) - nNullDate
;
2857 sal_Int32
ScaDate::getDiff( const ScaDate
& rFrom
, const ScaDate
& rTo
) throw( lang::IllegalArgumentException
)
2860 return getDiff( rTo
, rFrom
);
2862 sal_Int32 nDiff
= 0;
2863 ScaDate
aFrom( rFrom
);
2868 // corrections for base 0 (US NASD)
2871 if( ((rFrom
.nMonth
== 2) || (rFrom
.nDay
< 30)) && (aTo
.nOrigDay
== 31) )
2873 else if( (aTo
.nMonth
== 2) && aTo
.bLastDay
)
2874 aTo
.nDay
= ::DaysInMonth( 2, aTo
.nYear
);
2876 // corrections for base 4 (Europe)
2879 if( (aFrom
.nMonth
== 2) && (aFrom
.nDay
== 30) )
2880 aFrom
.nDay
= ::DaysInMonth( 2, aFrom
.nYear
);
2881 if( (aTo
.nMonth
== 2) && (aTo
.nDay
== 30) )
2882 aTo
.nDay
= ::DaysInMonth( 2, aTo
.nYear
);
2886 if( (aFrom
.nYear
< aTo
.nYear
) || ((aFrom
.nYear
== aTo
.nYear
) && (aFrom
.nMonth
< aTo
.nMonth
)) )
2888 // move aFrom to 1st day of next month
2889 nDiff
= aFrom
.getDaysInMonth() - aFrom
.nDay
+ 1;
2890 aFrom
.nOrigDay
= aFrom
.nDay
= 1;
2891 aFrom
.bLastDay
= sal_False
;
2892 aFrom
.addMonths( 1 );
2894 if( aFrom
.nYear
< aTo
.nYear
)
2896 // move aFrom to 1st day of next year
2897 nDiff
+= aFrom
.getDaysInMonthRange( aFrom
.nMonth
, 12 );
2898 aFrom
.addMonths( 13 - aFrom
.nMonth
);
2900 // move aFrom to 1st day of this year
2901 nDiff
+= aFrom
.getDaysInYearRange( aFrom
.nYear
, aTo
.nYear
- 1 );
2902 aFrom
.addYears( aTo
.nYear
- aFrom
.nYear
);
2905 // move aFrom to 1st day of this month
2906 nDiff
+= aFrom
.getDaysInMonthRange( aFrom
.nMonth
, aTo
.nMonth
- 1 );
2907 aFrom
.addMonths( aTo
.nMonth
- aFrom
.nMonth
);
2909 // finally add remaining days in this month
2910 nDiff
+= aTo
.nDay
- aFrom
.nDay
;
2911 return nDiff
> 0 ? nDiff
: 0;
2914 sal_Bool
ScaDate::operator<( const ScaDate
& rCmp
) const
2916 if( nYear
!= rCmp
.nYear
)
2917 return nYear
< rCmp
.nYear
;
2918 if( nMonth
!= rCmp
.nMonth
)
2919 return nMonth
< rCmp
.nMonth
;
2920 if( nDay
!= rCmp
.nDay
)
2921 return nDay
< rCmp
.nDay
;
2922 if( bLastDay
|| rCmp
.bLastDay
)
2923 return !bLastDay
&& rCmp
.bLastDay
;
2924 return nOrigDay
< rCmp
.nOrigDay
;
2929 //-----------------------------------------------------------------------------
2931 ScaAnyConverter::ScaAnyConverter( const uno::Reference
< lang::XMultiServiceFactory
>& xServiceFact
) :
2932 bHasValidFormat( sal_False
)
2934 if( xServiceFact
.is() )
2936 uno::Reference
< uno::XInterface
> xInstance
= xServiceFact
->createInstance(
2937 OUString::createFromAscii( "com.sun.star.util.NumberFormatter" ) );
2938 xFormatter
= uno::Reference
< util::XNumberFormatter
>( xInstance
, uno::UNO_QUERY
);
2942 ScaAnyConverter::~ScaAnyConverter()
2946 void ScaAnyConverter::init( const uno::Reference
< beans::XPropertySet
>& xPropSet
) throw( uno::RuntimeException
)
2948 // try to get default number format
2949 bHasValidFormat
= sal_False
;
2950 if( xFormatter
.is() )
2952 // get XFormatsSupplier from outer XPropertySet
2953 uno::Reference
< util::XNumberFormatsSupplier
> xFormatsSupp( xPropSet
, uno::UNO_QUERY
);
2954 if( xFormatsSupp
.is() )
2956 // get XNumberFormatTypes from XNumberFormatsSupplier to get standard index
2957 uno::Reference
< util::XNumberFormats
> xFormats( xFormatsSupp
->getNumberFormats() );
2958 uno::Reference
< util::XNumberFormatTypes
> xFormatTypes( xFormats
, uno::UNO_QUERY
);
2959 if( xFormatTypes
.is() )
2961 lang::Locale eLocale
;
2962 nDefaultFormat
= xFormatTypes
->getStandardIndex( eLocale
);
2963 xFormatter
->attachNumberFormatsSupplier( xFormatsSupp
);
2964 bHasValidFormat
= sal_True
;
2970 double ScaAnyConverter::convertToDouble( const OUString
& rString
) const throw( lang::IllegalArgumentException
)
2972 double fValue
= 0.0;
2973 if( bHasValidFormat
)
2977 fValue
= xFormatter
->convertStringToNumber( nDefaultFormat
, rString
);
2979 catch( uno::Exception
& )
2981 throw lang::IllegalArgumentException();
2986 rtl_math_ConversionStatus eStatus
;
2988 fValue
= ::rtl::math::stringToDouble( rString
, '.', ',', &eStatus
, &nEnd
);
2989 if( (eStatus
!= rtl_math_ConversionStatus_Ok
) || (nEnd
< rString
.getLength()) )
2990 throw lang::IllegalArgumentException();
2995 sal_Bool
ScaAnyConverter::getDouble(
2997 const uno::Any
& rAny
) const throw( lang::IllegalArgumentException
)
3000 sal_Bool bContainsVal
= sal_True
;
3001 switch( rAny
.getValueTypeClass() )
3003 case uno::TypeClass_VOID
:
3004 bContainsVal
= sal_False
;
3006 case uno::TypeClass_DOUBLE
:
3009 case uno::TypeClass_STRING
:
3011 const OUString
* pString
= static_cast< const OUString
* >( rAny
.getValue() );
3012 if( pString
->getLength() )
3013 rfResult
= convertToDouble( *pString
);
3015 bContainsVal
= sal_False
;
3019 throw lang::IllegalArgumentException();
3021 return bContainsVal
;
3024 sal_Bool
ScaAnyConverter::getDouble(
3026 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
3027 const uno::Any
& rAny
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
3030 return getDouble( rfResult
, rAny
);
3033 double ScaAnyConverter::getDouble(
3034 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
3035 const uno::Any
& rAny
,
3036 double fDefault
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
3039 if( !getDouble( fResult
, xPropSet
, rAny
) )
3044 sal_Bool
ScaAnyConverter::getInt32(
3045 sal_Int32
& rnResult
,
3046 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
3047 const uno::Any
& rAny
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
3050 sal_Bool bContainsVal
= getDouble( fResult
, xPropSet
, rAny
);
3051 if( (fResult
<= -2147483649.0) || (fResult
>= 2147483648.0) )
3052 throw lang::IllegalArgumentException();
3054 rnResult
= static_cast< sal_Int32
>( fResult
);
3055 return bContainsVal
;
3058 sal_Int32
ScaAnyConverter::getInt32(
3059 const uno::Reference
< beans::XPropertySet
>& xPropSet
,
3060 const uno::Any
& rAny
,
3061 sal_Int32 nDefault
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
3064 if( !getInt32( nResult
, xPropSet
, rAny
) )
3071 //-----------------------------------------------------------------------------