1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "analysisdefs.hxx"
21 #include "analysis.hxx"
22 #include "analysishelper.hxx"
23 #include <o3tl/temporary.hxx>
25 using namespace sca::analysis
;
27 double SAL_CALL
AnalysisAddIn::getAmordegrc( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
28 double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
, double fRestVal
,
29 double fPer
, double fRate
, const css::uno::Any
& rOB
)
31 if( nDate
> nFirstPer
|| fRate
<= 0.0 || fRestVal
> fCost
||
32 fCost
<= 0.0 || fRestVal
< 0 || fPer
< 0 )
33 throw css::lang::IllegalArgumentException();
35 double fRet
= GetAmordegrc( GetNullDate( xOpt
), fCost
, nDate
, nFirstPer
, fRestVal
, fPer
, fRate
, getDateMode( xOpt
, rOB
) );
36 return finiteOrThrow( fRet
);
40 double SAL_CALL
AnalysisAddIn::getAmorlinc( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
41 double fCost
, sal_Int32 nDate
, sal_Int32 nFirstPer
, double fRestVal
,
42 double fPer
, double fRate
, const css::uno::Any
& rOB
)
44 if ( nDate
> nFirstPer
|| fRate
<= 0.0 || fRestVal
> fCost
||
45 fCost
<= 0.0 || fRestVal
< 0 || fPer
< 0 )
46 throw css::lang::IllegalArgumentException();
48 double fRet
= GetAmorlinc( GetNullDate( xOpt
), fCost
, nDate
, nFirstPer
, fRestVal
, fPer
, fRate
, getDateMode( xOpt
, rOB
) );
49 return finiteOrThrow( fRet
);
53 double SAL_CALL
AnalysisAddIn::getAccrint( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
54 sal_Int32 nIssue
, sal_Int32
/*nFirstInter*/, sal_Int32 nSettle
, double fRate
,
55 const css::uno::Any
&rVal
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
57 double fVal
= aAnyConv
.getDouble( xOpt
, rVal
, 1000.0 );
59 if( fRate
<= 0.0 || fVal
<= 0.0 || isFreqInvalid(nFreq
) || nIssue
>= nSettle
)
60 throw css::lang::IllegalArgumentException();
62 double fRet
= fVal
* fRate
* GetYearDiff( GetNullDate( xOpt
), nIssue
, nSettle
, getDateMode( xOpt
, rOB
) );
63 return finiteOrThrow( fRet
);
67 double SAL_CALL
AnalysisAddIn::getAccrintm( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
68 sal_Int32 nIssue
, sal_Int32 nSettle
, double fRate
, const css::uno::Any
& rVal
, const css::uno::Any
& rOB
)
70 double fVal
= aAnyConv
.getDouble( xOpt
, rVal
, 1000.0 );
72 if( fRate
<= 0.0 || fVal
<= 0.0 || nIssue
>= nSettle
)
73 throw css::lang::IllegalArgumentException();
75 double fRet
= fVal
* fRate
* GetYearDiff( GetNullDate( xOpt
), nIssue
, nSettle
, getDateMode( xOpt
, rOB
) );
76 return finiteOrThrow( fRet
);
80 double SAL_CALL
AnalysisAddIn::getReceived( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
81 sal_Int32 nSettle
, sal_Int32 nMat
, double fInvest
, double fDisc
, const css::uno::Any
& rOB
)
83 if( fInvest
<= 0.0 || fDisc
<= 0.0 || nSettle
>= nMat
)
84 throw css::lang::IllegalArgumentException();
86 double fRet
= fInvest
/ ( 1.0 - ( fDisc
* GetYearDiff( GetNullDate( xOpt
), nSettle
, nMat
, getDateMode( xOpt
, rOB
) ) ) );
87 return finiteOrThrow( fRet
);
91 double SAL_CALL
AnalysisAddIn::getDisc( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
92 sal_Int32 nSettle
, sal_Int32 nMat
, double fPrice
, double fRedemp
, const css::uno::Any
& rOB
)
94 if( fPrice
<= 0.0 || fRedemp
<= 0.0 || nSettle
>= nMat
)
95 throw css::lang::IllegalArgumentException();
96 double fRet
= ( 1.0 - fPrice
/ fRedemp
) / GetYearFrac( xOpt
, nSettle
, nMat
, getDateMode( xOpt
, rOB
) );
97 return finiteOrThrow( fRet
);
101 double SAL_CALL
AnalysisAddIn::getDuration( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
102 sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
, double fYield
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
104 if( fCoup
< 0.0 || fYield
< 0.0 || isFreqInvalid(nFreq
) || nSettle
>= nMat
)
105 throw css::lang::IllegalArgumentException();
107 double fRet
= GetDuration( GetNullDate( xOpt
), nSettle
, nMat
, fCoup
, fYield
, nFreq
, getDateMode( xOpt
, rOB
) );
108 return finiteOrThrow( fRet
);
112 double SAL_CALL
AnalysisAddIn::getEffect( double fNominal
, sal_Int32 nPeriods
)
114 if( nPeriods
< 1 || fNominal
<= 0.0 )
115 throw css::lang::IllegalArgumentException();
117 double fPeriods
= nPeriods
;
119 double fRet
= pow( 1.0 + fNominal
/ fPeriods
, fPeriods
) - 1.0;
120 return finiteOrThrow( fRet
);
124 double SAL_CALL
AnalysisAddIn::getCumprinc( double fRate
, sal_Int32 nNumPeriods
, double fVal
,
125 sal_Int32 nStartPer
, sal_Int32 nEndPer
, sal_Int32 nPayType
)
129 if( nStartPer
< 1 || nEndPer
< nStartPer
|| fRate
<= 0.0 || nEndPer
> nNumPeriods
||
130 fVal
<= 0.0 || ( nPayType
!= 0 && nPayType
!= 1 ) )
131 throw css::lang::IllegalArgumentException();
133 fPmt
= GetPmt( fRate
, nNumPeriods
, fVal
, 0.0, nPayType
);
137 sal_uInt32 nStart
= sal_uInt32( nStartPer
);
138 sal_uInt32 nEnd
= sal_uInt32( nEndPer
);
143 fPpmt
= fPmt
+ fVal
* fRate
;
150 for( sal_uInt32 i
= nStart
; i
<= nEnd
; i
++ )
153 fPpmt
+= fPmt
- ( GetFv( fRate
, double( i
- 2 ), fPmt
, fVal
, 1 ) - fPmt
) * fRate
;
155 fPpmt
+= fPmt
- GetFv( fRate
, double( i
- 1 ), fPmt
, fVal
, 0 ) * fRate
;
158 return finiteOrThrow( fPpmt
);
162 double SAL_CALL
AnalysisAddIn::getCumipmt( double fRate
, sal_Int32 nNumPeriods
, double fVal
,
163 sal_Int32 nStartPer
, sal_Int32 nEndPer
, sal_Int32 nPayType
)
167 if( nStartPer
< 1 || nEndPer
< nStartPer
|| fRate
<= 0.0 || nEndPer
> nNumPeriods
||
168 fVal
<= 0.0 || ( nPayType
!= 0 && nPayType
!= 1 ) )
169 throw css::lang::IllegalArgumentException();
171 fPmt
= GetPmt( fRate
, nNumPeriods
, fVal
, 0.0, nPayType
);
175 sal_uInt32 nStart
= sal_uInt32( nStartPer
);
176 sal_uInt32 nEnd
= sal_uInt32( nEndPer
);
186 for( sal_uInt32 i
= nStart
; i
<= nEnd
; i
++ )
189 fIpmt
+= GetFv( fRate
, double( i
- 2 ), fPmt
, fVal
, 1 ) - fPmt
;
191 fIpmt
+= GetFv( fRate
, double( i
- 1 ), fPmt
, fVal
, 0 );
196 return finiteOrThrow( fIpmt
);
200 double SAL_CALL
AnalysisAddIn::getPrice( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
201 sal_Int32 nSettle
, sal_Int32 nMat
, double fRate
, double fYield
, double fRedemp
, sal_Int32 nFreq
,
202 const css::uno::Any
& rOB
)
204 if( fYield
< 0.0 || fRate
< 0.0 || fRedemp
<= 0.0 || isFreqInvalid(nFreq
) || nSettle
>= nMat
)
205 throw css::lang::IllegalArgumentException();
207 double fRet
= getPrice_( GetNullDate( xOpt
), nSettle
, nMat
, fRate
, fYield
, fRedemp
, nFreq
, getDateMode( xOpt
, rOB
) );
208 return finiteOrThrow( fRet
);
212 double SAL_CALL
AnalysisAddIn::getPricedisc( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
213 sal_Int32 nSettle
, sal_Int32 nMat
, double fDisc
, double fRedemp
, const css::uno::Any
& rOB
)
215 if( fDisc
<= 0.0 || fRedemp
<= 0.0 || nSettle
>= nMat
)
216 throw css::lang::IllegalArgumentException();
218 double fRet
= fRedemp
* ( 1.0 - fDisc
* GetYearDiff( GetNullDate( xOpt
), nSettle
, nMat
, getDateMode( xOpt
, rOB
) ) );
219 return finiteOrThrow( fRet
);
223 double SAL_CALL
AnalysisAddIn::getPricemat( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
224 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nIssue
, double fRate
, double fYield
, const css::uno::Any
& rOB
)
226 if( fRate
< 0.0 || fYield
< 0.0 || nSettle
>= nMat
)
227 throw css::lang::IllegalArgumentException();
229 sal_Int32 nNullDate
= GetNullDate( xOpt
);
230 sal_Int32 nBase
= getDateMode( xOpt
, rOB
);
232 double fIssMat
= GetYearFrac( nNullDate
, nIssue
, nMat
, nBase
);
233 double fIssSet
= GetYearFrac( nNullDate
, nIssue
, nSettle
, nBase
);
234 double fSetMat
= GetYearFrac( nNullDate
, nSettle
, nMat
, nBase
);
236 double fRet
= 1.0 + fIssMat
* fRate
;
237 fRet
/= 1.0 + fSetMat
* fYield
;
238 fRet
-= fIssSet
* fRate
;
241 return finiteOrThrow( fRet
);
245 double SAL_CALL
AnalysisAddIn::getMduration( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
246 sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
, double fYield
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
248 if( fCoup
< 0.0 || fYield
< 0.0 || isFreqInvalid(nFreq
) )
249 throw css::lang::IllegalArgumentException();
251 double fRet
= GetDuration( GetNullDate( xOpt
), nSettle
, nMat
, fCoup
, fYield
, nFreq
, getDateMode( xOpt
, rOB
) );
252 fRet
/= 1.0 + ( fYield
/ double( nFreq
) );
253 return finiteOrThrow( fRet
);
257 double SAL_CALL
AnalysisAddIn::getNominal( double fRate
, sal_Int32 nPeriods
)
259 if( fRate
<= 0.0 || nPeriods
< 0 )
260 throw css::lang::IllegalArgumentException();
262 double fPeriods
= nPeriods
;
263 double fRet
= ( pow( fRate
+ 1.0, 1.0 / fPeriods
) - 1.0 ) * fPeriods
;
264 return finiteOrThrow( fRet
);
268 double SAL_CALL
AnalysisAddIn::getDollarfr( double fDollarDec
, sal_Int32 nFrac
)
271 throw css::lang::IllegalArgumentException();
274 double fFrac
= nFrac
;
276 double fRet
= modf( fDollarDec
, &fInt
);
280 fRet
*= pow( 10.0, -ceil( log10( fFrac
) ) );
284 return finiteOrThrow( fRet
);
288 double SAL_CALL
AnalysisAddIn::getDollarde( double fDollarFrac
, sal_Int32 nFrac
)
291 throw css::lang::IllegalArgumentException();
294 double fFrac
= nFrac
;
296 double fRet
= modf( fDollarFrac
, &fInt
);
300 fRet
*= pow( 10.0, ceil( log10( fFrac
) ) );
304 return finiteOrThrow( fRet
);
308 double SAL_CALL
AnalysisAddIn::getYield( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
309 sal_Int32 nSettle
, sal_Int32 nMat
, double fCoup
, double fPrice
, double fRedemp
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
311 if( fCoup
< 0.0 || fPrice
<= 0.0 || fRedemp
<= 0.0 || isFreqInvalid(nFreq
) || nSettle
>= nMat
)
312 throw css::lang::IllegalArgumentException();
314 double fRet
= getYield_( GetNullDate( xOpt
), nSettle
, nMat
, fCoup
, fPrice
, fRedemp
, nFreq
, getDateMode( xOpt
, rOB
) );
315 return finiteOrThrow( fRet
);
319 double SAL_CALL
AnalysisAddIn::getYielddisc( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
320 sal_Int32 nSettle
, sal_Int32 nMat
, double fPrice
, double fRedemp
, const css::uno::Any
& rOB
)
322 if( fPrice
<= 0.0 || fRedemp
<= 0.0 || nSettle
>= nMat
)
323 throw css::lang::IllegalArgumentException();
325 sal_Int32 nNullDate
= GetNullDate( xOpt
);
327 double fRet
= ( fRedemp
/ fPrice
) - 1.0;
328 fRet
/= GetYearFrac( nNullDate
, nSettle
, nMat
, getDateMode( xOpt
, rOB
) );
330 return finiteOrThrow( fRet
);
334 double SAL_CALL
AnalysisAddIn::getYieldmat( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
335 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nIssue
, double fRate
, double fPrice
, const css::uno::Any
& rOB
)
337 if( fPrice
<= 0.0 || fRate
< 0.0 || nSettle
>= nMat
|| nSettle
< nIssue
)
338 throw css::lang::IllegalArgumentException();
340 double fRet
= GetYieldmat( GetNullDate( xOpt
), nSettle
, nMat
, nIssue
, fRate
, fPrice
, getDateMode( xOpt
, rOB
) );
341 return finiteOrThrow( fRet
);
345 double SAL_CALL
AnalysisAddIn::getTbilleq( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
346 sal_Int32 nSettle
, sal_Int32 nMat
, double fDisc
)
350 sal_Int32 nDiff
= GetDiffDate360( xOpt
, nSettle
, nMat
, true );
352 if( fDisc
<= 0.0 || nSettle
>= nMat
|| nDiff
> 360 )
353 throw css::lang::IllegalArgumentException();
355 double fRet
= ( 365 * fDisc
) / ( 360 - ( fDisc
* double( nDiff
) ) );
356 return finiteOrThrow( fRet
);
360 double SAL_CALL
AnalysisAddIn::getTbillprice( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
361 sal_Int32 nSettle
, sal_Int32 nMat
, double fDisc
)
363 if( fDisc
<= 0.0 || nSettle
> nMat
)
364 throw css::lang::IllegalArgumentException();
368 double fFraction
= GetYearFrac( xOpt
, nSettle
, nMat
, 0 ); // method: USA 30/360
370 if( modf( fFraction
, &o3tl::temporary(double()) ) == 0.0 )
371 throw css::lang::IllegalArgumentException();
373 double fRet
= 100.0 * ( 1.0 - fDisc
* fFraction
);
374 return finiteOrThrow( fRet
);
378 double SAL_CALL
AnalysisAddIn::getTbillyield( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
, sal_Int32 nSettle
, sal_Int32 nMat
, double fPrice
)
380 sal_Int32 nDiff
= GetDiffDate360( xOpt
, nSettle
, nMat
, true );
383 if( fPrice
<= 0.0 || nSettle
>= nMat
|| nDiff
> 360 )
384 throw css::lang::IllegalArgumentException();
389 fRet
/= double( nDiff
);
392 return finiteOrThrow( fRet
);
395 // Encapsulation violation: We *know* that GetOddfprice() always
398 SAL_WNOUNREACHABLE_CODE_PUSH
400 double SAL_CALL
AnalysisAddIn::getOddfprice( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
401 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nIssue
, sal_Int32 nFirstCoup
,
402 double fRate
, double fYield
, double fRedemp
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
404 if( fRate
< 0.0 || fYield
< 0.0 || isFreqInvalid(nFreq
) || nMat
<= nFirstCoup
|| nFirstCoup
<= nSettle
|| nSettle
<= nIssue
)
405 throw css::lang::IllegalArgumentException();
407 double fRet
= GetOddfprice( GetNullDate( xOpt
), nSettle
, nMat
, nIssue
, nFirstCoup
, fRate
, fYield
, fRedemp
, nFreq
, getDateMode( xOpt
, rOB
) );
408 return finiteOrThrow( fRet
);
411 SAL_WNOUNREACHABLE_CODE_POP
413 // Encapsulation violation: We *know* that Getoddfyield() always
416 SAL_WNOUNREACHABLE_CODE_PUSH
418 double SAL_CALL
AnalysisAddIn::getOddfyield( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
419 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nIssue
, sal_Int32 nFirstCoup
,
420 double fRate
, double fPrice
, double fRedemp
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
422 if( fRate
< 0.0 || fPrice
<= 0.0 || isFreqInvalid(nFreq
) || nMat
<= nFirstCoup
|| nFirstCoup
<= nSettle
|| nSettle
<= nIssue
)
423 throw css::lang::IllegalArgumentException();
425 double fRet
= GetOddfyield( GetNullDate( xOpt
), nSettle
, nMat
, nIssue
, nFirstCoup
, fRate
, fPrice
, fRedemp
, nFreq
,
426 getDateMode( xOpt
, rOB
) );
427 return finiteOrThrow( fRet
);
430 SAL_WNOUNREACHABLE_CODE_POP
432 double SAL_CALL
AnalysisAddIn::getOddlprice( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
433 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastInterest
,
434 double fRate
, double fYield
, double fRedemp
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
436 if( fRate
<= 0.0 || fYield
< 0.0 || fRedemp
<= 0.0 || isFreqInvalid(nFreq
) || nMat
<= nSettle
|| nSettle
<= nLastInterest
)
437 throw css::lang::IllegalArgumentException();
439 double fRet
= GetOddlprice( GetNullDate( xOpt
), nSettle
, nMat
, nLastInterest
, fRate
, fYield
, fRedemp
, nFreq
,
440 getDateMode( xOpt
, rOB
) );
441 return finiteOrThrow( fRet
);
445 double SAL_CALL
AnalysisAddIn::getOddlyield( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
446 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nLastInterest
,
447 double fRate
, double fPrice
, double fRedemp
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
449 if( fRate
<= 0.0 || fPrice
<= 0.0 || fRedemp
<= 0.0 || isFreqInvalid(nFreq
) || nMat
<= nSettle
|| nSettle
<= nLastInterest
)
450 throw css::lang::IllegalArgumentException();
452 double fRet
= GetOddlyield( GetNullDate( xOpt
), nSettle
, nMat
, nLastInterest
, fRate
, fPrice
, fRedemp
, nFreq
,
453 getDateMode( xOpt
, rOB
) );
454 return finiteOrThrow( fRet
);
457 // XIRR helper functions
459 #define V_(i) (rValues.Get(i))
460 #define D_(i) (rDates.Get(i))
462 /** Calculates the resulting amount for the passed interest rate and the given XIRR parameters. */
463 static double lcl_sca_XirrResult( const ScaDoubleList
& rValues
, const ScaDoubleList
& rDates
, double fRate
)
465 /* V_0 ... V_n = input values.
466 D_0 ... D_n = input dates.
467 R = input interest rate.
470 E_i := (D_i-D_0) / 365
473 f(R) = SUM ------- = V_0 + SUM ------- .
477 double r
= fRate
+ 1.0;
478 double fResult
= V_(0);
479 for( sal_uInt32 i
= 1, nCount
= rValues
.Count(); i
< nCount
; ++i
)
480 fResult
+= V_(i
) / pow( r
, (D_(i
) - D_0
) / 365.0 );
484 /** Calculates the first derivation of lcl_sca_XirrResult(). */
485 static double lcl_sca_XirrResult_Deriv1( const ScaDoubleList
& rValues
, const ScaDoubleList
& rDates
, double fRate
)
487 /* V_0 ... V_n = input values.
488 D_0 ... D_n = input dates.
489 R = input interest rate.
492 E_i := (D_i-D_0) / 365
495 f'(R) = [ V_0 + SUM ------- ]'
499 = 0 + SUM -E_i ----------- r' = - SUM ----------- .
500 i=1 r^(E_i+1) i=1 r^(E_i+1)
503 double r
= fRate
+ 1.0;
504 double fResult
= 0.0;
505 for( sal_uInt32 i
= 1, nCount
= rValues
.Count(); i
< nCount
; ++i
)
507 double E_i
= (D_(i
) - D_0
) / 365.0;
508 fResult
-= E_i
* V_(i
) / pow( r
, E_i
+ 1.0 );
518 double SAL_CALL
AnalysisAddIn::getXirr(
519 const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
, const css::uno::Sequence
< css::uno::Sequence
< double > >& rValues
, const css::uno::Sequence
< css::uno::Sequence
< sal_Int32
> >& rDates
, const css::uno::Any
& rGuessRate
)
521 ScaDoubleList aValues
, aDates
;
522 aValues
.Append( rValues
);
523 aDates
.Append( rDates
);
525 if( (aValues
.Count() < 2) || (aValues
.Count() != aDates
.Count()) )
526 throw css::lang::IllegalArgumentException();
528 // result interest rate, initialized with passed guessed rate, or 10%
529 double fResultRate
= aAnyConv
.getDouble( xOpt
, rGuessRate
, 0.1 );
530 if( fResultRate
<= -1 )
531 throw css::lang::IllegalArgumentException();
533 // maximum epsilon for end of iteration
534 static const double fMaxEps
= 1e-10;
535 // maximum number of iterations
536 static const sal_Int32 nMaxIter
= 50;
538 // Newton's method - try to find a fResultRate, so that lcl_sca_XirrResult() returns 0.
541 sal_Int32 nIterScan
= 0;
542 bool bContLoop
= false;
543 bool bResultRateScanEnd
= false;
545 // First the inner while-loop will be executed using the default Value fResultRate
546 // or the user guessed fResultRate if those do not deliver a solution for the
547 // Newton's method then the range from -0.99 to +0.99 will be scanned with a
548 // step size of 0.01 to find fResultRate's value which can deliver a solution
552 fResultRate
= -0.99 + (nIterScan
-1)* 0.01;
555 fResultValue
= lcl_sca_XirrResult( aValues
, aDates
, fResultRate
);
556 double fNewRate
= fResultRate
- fResultValue
/ lcl_sca_XirrResult_Deriv1( aValues
, aDates
, fResultRate
);
557 double fRateEps
= fabs( fNewRate
- fResultRate
);
558 fResultRate
= fNewRate
;
559 bContLoop
= (fRateEps
> fMaxEps
) && (fabs( fResultValue
) > fMaxEps
);
561 while( bContLoop
&& (++nIter
< nMaxIter
) );
563 if ( std::isnan(fResultRate
) || std::isinf(fResultRate
)
564 ||std::isnan(fResultValue
) || std::isinf(fResultValue
))
568 bResultRateScanEnd
= (nIterScan
>= 200);
570 while(bContLoop
&& !bResultRateScanEnd
);
573 throw css::lang::IllegalArgumentException();
574 return finiteOrThrow( fResultRate
);
578 double SAL_CALL
AnalysisAddIn::getXnpv(
579 double fRate
, const css::uno::Sequence
< css::uno::Sequence
< double > >& rValues
, const css::uno::Sequence
< css::uno::Sequence
< sal_Int32
> >& rDates
)
581 ScaDoubleList aValList
;
582 ScaDoubleList aDateList
;
584 aValList
.Append( rValues
);
585 aDateList
.Append( rDates
);
587 sal_uInt32 nNum
= aValList
.Count();
589 if( nNum
!= aDateList
.Count() || nNum
< 2 )
590 throw css::lang::IllegalArgumentException();
593 double fNull
= aDateList
.Get( 0 );
596 for( sal_uInt32 i
= 0 ; i
< nNum
; i
++ )
597 fRet
+= aValList
.Get( i
) / ( pow( fRate
, ( aDateList
.Get( i
) - fNull
) / 365.0 ) );
599 return finiteOrThrow( fRet
);
603 double SAL_CALL
AnalysisAddIn::getIntrate( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
604 sal_Int32 nSettle
, sal_Int32 nMat
, double fInvest
, double fRedemp
, const css::uno::Any
& rOB
)
606 if( fInvest
<= 0.0 || fRedemp
<= 0.0 || nSettle
>= nMat
)
607 throw css::lang::IllegalArgumentException();
609 double fRet
= ( ( fRedemp
/ fInvest
) - 1.0 ) / GetYearDiff( GetNullDate( xOpt
), nSettle
, nMat
, getDateMode( xOpt
, rOB
) );
610 return finiteOrThrow( fRet
);
614 double SAL_CALL
AnalysisAddIn::getCoupncd( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
615 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
617 double fRet
= GetCoupncd( GetNullDate( xOpt
), nSettle
, nMat
, nFreq
, getDateMode( xOpt
, rOB
) );
618 return finiteOrThrow( fRet
);
622 double SAL_CALL
AnalysisAddIn::getCoupdays( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
623 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
625 double fRet
= GetCoupdays( GetNullDate( xOpt
), nSettle
, nMat
, nFreq
, getDateMode( xOpt
, rOB
) );
626 return finiteOrThrow( fRet
);
630 double SAL_CALL
AnalysisAddIn::getCoupdaysnc( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
631 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
633 double fRet
= GetCoupdaysnc( GetNullDate( xOpt
), nSettle
, nMat
, nFreq
, getDateMode( xOpt
, rOB
) );
634 return finiteOrThrow( fRet
);
638 double SAL_CALL
AnalysisAddIn::getCoupdaybs( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
639 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
641 double fRet
= GetCoupdaybs( GetNullDate( xOpt
), nSettle
, nMat
, nFreq
, getDateMode( xOpt
, rOB
) );
642 return finiteOrThrow( fRet
);
646 double SAL_CALL
AnalysisAddIn::getCouppcd( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
647 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
649 double fRet
= GetCouppcd( GetNullDate( xOpt
), nSettle
, nMat
, nFreq
, getDateMode( xOpt
, rOB
) );
650 return finiteOrThrow( fRet
);
654 double SAL_CALL
AnalysisAddIn::getCoupnum( const css::uno::Reference
< css::beans::XPropertySet
>& xOpt
,
655 sal_Int32 nSettle
, sal_Int32 nMat
, sal_Int32 nFreq
, const css::uno::Any
& rOB
)
657 double fRet
= GetCoupnum( GetNullDate( xOpt
), nSettle
, nMat
, nFreq
, getDateMode( xOpt
, rOB
) );
658 return finiteOrThrow( fRet
);
662 double SAL_CALL
AnalysisAddIn::getFvschedule( double fPrinc
, const css::uno::Sequence
< css::uno::Sequence
< double > >& rSchedule
)
664 ScaDoubleList aSchedList
;
666 aSchedList
.Append( rSchedule
);
668 for( sal_uInt32 i
= 0; i
< aSchedList
.Count(); ++i
)
669 fPrinc
*= 1.0 + aSchedList
.Get(i
);
671 return finiteOrThrow( fPrinc
);
675 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */