LibreOffice Module scaddins (master) 1
analysishelper.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <com/sun/star/util/Date.hpp>
21#include <com/sun/star/util/XNumberFormatTypes.hpp>
22#include <com/sun/star/util/NumberFormatter.hpp>
23
24#include <string.h>
25#include <stdio.h>
26#include <o3tl/any.hxx>
27#include <rtl/math.hxx>
28#include <algorithm>
29#include <cmath>
30#include <memory>
31
32#include "analysisdefs.hxx"
33#include "analysishelper.hxx"
34#include <analysis.hrc>
35#include <strings.hrc>
36#include "deffuncname.hxx"
37
38using namespace ::com::sun::star;
39using namespace sca::analysis;
40
41#define UNIQUE false // function name does not exist in Calc
42#define DOUBLE true // function name exists in Calc
43
44#define STDPAR false // all parameters are described
45#define INTPAR true // first parameter is internal
46
47#define FUNCDATA( FUNCNAME, DBL, OPT, NUMOFPAR, CAT ) \
48 { "get" #FUNCNAME, ANALYSIS_FUNCNAME_##FUNCNAME, ANALYSIS_##FUNCNAME, DBL, OPT, ANALYSIS_DEFFUNCNAME_##FUNCNAME, NUMOFPAR, CAT, nullptr }
49
50#define FUNCDATAS( FUNCNAME, DBL, OPT, NUMOFPAR, CAT, SUFFIX ) \
51 { "get" #FUNCNAME, ANALYSIS_FUNCNAME_##FUNCNAME, ANALYSIS_##FUNCNAME, DBL, OPT, ANALYSIS_DEFFUNCNAME_##FUNCNAME, NUMOFPAR, CAT, SUFFIX }
52
54{
55 // UNIQUE or INTPAR or
56 // function name DOUBLE STDPAR # of param category
57 FUNCDATA( Workday, UNIQUE, INTPAR, 3, FDCategory::DateTime ),
58 FUNCDATA( Yearfrac, UNIQUE, INTPAR, 3, FDCategory::DateTime ),
59 FUNCDATA( Edate, UNIQUE, INTPAR, 2, FDCategory::DateTime ),
60 FUNCDATAS( Weeknum, DOUBLE, INTPAR, 2, FDCategory::DateTime, "_EXCEL2003" ),
61 FUNCDATA( Eomonth, UNIQUE, INTPAR, 2, FDCategory::DateTime ),
62 FUNCDATAS( Networkdays, DOUBLE, INTPAR, 3, FDCategory::DateTime, "_EXCEL2003" ),
63 FUNCDATA( Iseven, DOUBLE, STDPAR, 1, FDCategory::Inf ),
64 FUNCDATA( Isodd, DOUBLE, STDPAR, 1, FDCategory::Inf ),
65 FUNCDATA( Multinomial, UNIQUE, STDPAR, 1, FDCategory::Math ),
66 FUNCDATA( Seriessum, UNIQUE, STDPAR, 4, FDCategory::Math ),
67 FUNCDATA( Quotient, UNIQUE, STDPAR, 2, FDCategory::Math ),
68 FUNCDATA( Mround, UNIQUE, STDPAR, 2, FDCategory::Math ),
69 FUNCDATA( Sqrtpi, UNIQUE, STDPAR, 1, FDCategory::Math ),
70 FUNCDATA( Randbetween, UNIQUE, STDPAR, 2, FDCategory::Math ),
71 FUNCDATAS( Gcd, DOUBLE, INTPAR, 1, FDCategory::Math, "_EXCEL2003" ),
72 FUNCDATAS( Lcm, DOUBLE, INTPAR, 1, FDCategory::Math, "_EXCEL2003" ),
73 FUNCDATA( Besseli, UNIQUE, STDPAR, 2, FDCategory::Tech ),
74 FUNCDATA( Besselj, UNIQUE, STDPAR, 2, FDCategory::Tech ),
75 FUNCDATA( Besselk, UNIQUE, STDPAR, 2, FDCategory::Tech ),
76 FUNCDATA( Bessely, UNIQUE, STDPAR, 2, FDCategory::Tech ),
77 FUNCDATA( Bin2Oct, UNIQUE, INTPAR, 2, FDCategory::Tech ),
78 FUNCDATA( Bin2Dec, UNIQUE, STDPAR, 1, FDCategory::Tech ),
79 FUNCDATA( Bin2Hex, UNIQUE, INTPAR, 2, FDCategory::Tech ),
80 FUNCDATA( Oct2Bin, UNIQUE, INTPAR, 2, FDCategory::Tech ),
81 FUNCDATA( Oct2Dec, UNIQUE, STDPAR, 1, FDCategory::Tech ),
82 FUNCDATA( Oct2Hex, UNIQUE, INTPAR, 2, FDCategory::Tech ),
83 FUNCDATA( Dec2Bin, UNIQUE, INTPAR, 2, FDCategory::Tech ),
84 FUNCDATA( Dec2Hex, UNIQUE, INTPAR, 2, FDCategory::Tech ),
85 FUNCDATA( Dec2Oct, UNIQUE, INTPAR, 2, FDCategory::Tech ),
86 FUNCDATA( Hex2Bin, UNIQUE, INTPAR, 2, FDCategory::Tech ),
87 FUNCDATA( Hex2Dec, UNIQUE, STDPAR, 1, FDCategory::Tech ),
88 FUNCDATA( Hex2Oct, UNIQUE, INTPAR, 2, FDCategory::Tech ),
89 FUNCDATA( Delta, UNIQUE, INTPAR, 2, FDCategory::Tech ),
90 FUNCDATA( Erf, UNIQUE, INTPAR, 2, FDCategory::Tech ),
91 FUNCDATA( Erfc, UNIQUE, STDPAR, 1, FDCategory::Tech ),
92 FUNCDATA( Gestep, UNIQUE, INTPAR, 2, FDCategory::Tech ),
93 FUNCDATA( Factdouble, UNIQUE, STDPAR, 1, FDCategory::Tech ),
94 FUNCDATA( Imabs, UNIQUE, STDPAR, 1, FDCategory::Tech ),
95 FUNCDATA( Imaginary, UNIQUE, STDPAR, 1, FDCategory::Tech ),
96 FUNCDATA( Impower, UNIQUE, STDPAR, 2, FDCategory::Tech ),
97 FUNCDATA( Imargument, UNIQUE, STDPAR, 1, FDCategory::Tech ),
98 FUNCDATA( Imcos, UNIQUE, STDPAR, 1, FDCategory::Tech ),
99 FUNCDATA( Imdiv, UNIQUE, STDPAR, 2, FDCategory::Tech ),
100 FUNCDATA( Imexp, UNIQUE, STDPAR, 1, FDCategory::Tech ),
101 FUNCDATA( Imconjugate, UNIQUE, STDPAR, 1, FDCategory::Tech ),
102 FUNCDATA( Imln, UNIQUE, STDPAR, 1, FDCategory::Tech ),
103 FUNCDATA( Imlog10, UNIQUE, STDPAR, 1, FDCategory::Tech ),
104 FUNCDATA( Imlog2, UNIQUE, STDPAR, 1, FDCategory::Tech ),
105 FUNCDATA( Improduct, UNIQUE, INTPAR, 2, FDCategory::Tech ),
106 FUNCDATA( Imreal, UNIQUE, STDPAR, 1, FDCategory::Tech ),
107 FUNCDATA( Imsin, UNIQUE, STDPAR, 1, FDCategory::Tech ),
108 FUNCDATA( Imsub, UNIQUE, STDPAR, 2, FDCategory::Tech ),
109 FUNCDATA( Imsqrt, UNIQUE, STDPAR, 1, FDCategory::Tech ),
110 FUNCDATA( Imsum, UNIQUE, INTPAR, 1, FDCategory::Tech ),
111 FUNCDATA( Imtan, UNIQUE, STDPAR, 1, FDCategory::Tech ),
112 FUNCDATA( Imsec, UNIQUE, STDPAR, 1, FDCategory::Tech ),
113 FUNCDATA( Imcsc, UNIQUE, STDPAR, 1, FDCategory::Tech ),
114 FUNCDATA( Imcot, UNIQUE, STDPAR, 1, FDCategory::Tech ),
115 FUNCDATA( Imsinh, UNIQUE, STDPAR, 1, FDCategory::Tech ),
116 FUNCDATA( Imcosh, UNIQUE, STDPAR, 1, FDCategory::Tech ),
117 FUNCDATA( Imsech, UNIQUE, STDPAR, 1, FDCategory::Tech ),
118 FUNCDATA( Imcsch, UNIQUE, STDPAR, 1, FDCategory::Tech ),
119 FUNCDATA( Complex, UNIQUE, STDPAR, 3, FDCategory::Tech ),
120 FUNCDATA( Convert, UNIQUE, STDPAR, 3, FDCategory::Tech ),
121 FUNCDATA( Amordegrc, UNIQUE, INTPAR, 7, FDCategory::Finance ),
122 FUNCDATA( Amorlinc, UNIQUE, INTPAR, 7, FDCategory::Finance ),
123 FUNCDATA( Accrint, UNIQUE, INTPAR, 7, FDCategory::Finance ),
124 FUNCDATA( Accrintm, UNIQUE, INTPAR, 5, FDCategory::Finance ),
125 FUNCDATA( Received, UNIQUE, INTPAR, 5, FDCategory::Finance ),
126 FUNCDATA( Disc, UNIQUE, INTPAR, 5, FDCategory::Finance ),
127 FUNCDATA( Duration, UNIQUE, INTPAR, 6, FDCategory::Finance ),
128 FUNCDATA( Effect, DOUBLE, STDPAR, 2, FDCategory::Finance ),
129 FUNCDATA( Cumprinc, DOUBLE, STDPAR, 6, FDCategory::Finance ),
130 FUNCDATA( Cumipmt, DOUBLE, STDPAR, 6, FDCategory::Finance ),
131 FUNCDATA( Price, UNIQUE, INTPAR, 7, FDCategory::Finance ),
132 FUNCDATA( Pricedisc, UNIQUE, INTPAR, 5, FDCategory::Finance ),
133 FUNCDATA( Pricemat, UNIQUE, INTPAR, 6, FDCategory::Finance ),
134 FUNCDATA( Mduration, UNIQUE, INTPAR, 6, FDCategory::Finance ),
135 FUNCDATA( Nominal, DOUBLE, STDPAR, 2, FDCategory::Finance ),
136 FUNCDATA( Dollarfr, UNIQUE, STDPAR, 2, FDCategory::Finance ),
137 FUNCDATA( Dollarde, UNIQUE, STDPAR, 2, FDCategory::Finance ),
138 FUNCDATA( Yield, UNIQUE, INTPAR, 7, FDCategory::Finance ),
139 FUNCDATA( Yielddisc, UNIQUE, INTPAR, 5, FDCategory::Finance ),
140 FUNCDATA( Yieldmat, UNIQUE, INTPAR, 6, FDCategory::Finance ),
141 FUNCDATA( Tbilleq, UNIQUE, INTPAR, 3, FDCategory::Finance ),
142 FUNCDATA( Tbillprice, UNIQUE, INTPAR, 3, FDCategory::Finance ),
143 FUNCDATA( Tbillyield, UNIQUE, INTPAR, 3, FDCategory::Finance ),
144 FUNCDATA( Oddfprice, UNIQUE, INTPAR, 9, FDCategory::Finance ),
145 FUNCDATA( Oddfyield, UNIQUE, INTPAR, 9, FDCategory::Finance ),
146 FUNCDATA( Oddlprice, UNIQUE, INTPAR, 8, FDCategory::Finance ),
147 FUNCDATA( Oddlyield, UNIQUE, INTPAR, 8, FDCategory::Finance ),
148 FUNCDATA( Xirr, UNIQUE, INTPAR, 3, FDCategory::Finance ),
149 FUNCDATA( Xnpv, UNIQUE, STDPAR, 3, FDCategory::Finance ),
150 FUNCDATA( Intrate, UNIQUE, INTPAR, 5, FDCategory::Finance ),
151 FUNCDATA( Coupncd, UNIQUE, INTPAR, 4, FDCategory::Finance ),
152 FUNCDATA( Coupdays, UNIQUE, INTPAR, 4, FDCategory::Finance ),
153 FUNCDATA( Coupdaysnc, UNIQUE, INTPAR, 4, FDCategory::Finance ),
154 FUNCDATA( Coupdaybs, UNIQUE, INTPAR, 4, FDCategory::Finance ),
155 FUNCDATA( Couppcd, UNIQUE, INTPAR, 4, FDCategory::Finance ),
156 FUNCDATA( Coupnum, UNIQUE, INTPAR, 4, FDCategory::Finance ),
157 FUNCDATA( Fvschedule, UNIQUE, STDPAR, 2, FDCategory::Finance )
158};
159#undef FUNCDATA
160
161namespace sca::analysis {
162
163sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear )
164{
165 if( (nMonth == 2) && IsLeapYear( nYear ) )
166 return 29;
167 static const sal_uInt16 aDaysInMonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
168 return aDaysInMonth[ nMonth ];
169}
170
171
182sal_Int32 DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear )
183{
184 sal_Int32 nDays = (static_cast<sal_Int32>(nYear)-1) * 365;
185 nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400);
186
187 for( sal_uInt16 i = 1; i < nMonth; i++ )
188 nDays += DaysInMonth(i,nYear);
189 nDays += nDay;
190
191 return nDays;
192}
193
194
205void DaysToDate( sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear )
206{
207 if( nDays < 0 )
208 throw lang::IllegalArgumentException();
209
210 sal_Int32 nTempDays;
211 sal_Int32 i = 0;
212 bool bCalc;
213
214 do
215 {
216 nTempDays = nDays;
217 rYear = static_cast<sal_uInt16>((nTempDays / 365) - i);
218 nTempDays -= (static_cast<sal_Int32>(rYear) -1) * 365;
219 nTempDays -= (( rYear -1) / 4) - (( rYear -1) / 100) + ((rYear -1) / 400);
220 bCalc = false;
221 if ( nTempDays < 1 )
222 {
223 i++;
224 bCalc = true;
225 }
226 else
227 {
228 if ( nTempDays > 365 )
229 {
230 if ( (nTempDays != 366) || !IsLeapYear( rYear ) )
231 {
232 i--;
233 bCalc = true;
234 }
235 }
236 }
237 }
238 while ( bCalc );
239
240 rMonth = 1;
241 while ( nTempDays > DaysInMonth( rMonth, rYear ) )
242 {
243 nTempDays -= DaysInMonth( rMonth, rYear );
244 rMonth++;
245 }
246 rDay = static_cast<sal_uInt16>(nTempDays);
247}
248
249
259sal_Int32 GetNullDate( const uno::Reference< beans::XPropertySet >& xOpt )
260{
261 if( xOpt.is() )
262 {
263 try
264 {
265 uno::Any aAny = xOpt->getPropertyValue( "NullDate" );
266 util::Date aDate;
267 if( aAny >>= aDate )
268 return DateToDays( aDate.Day, aDate.Month, aDate.Year );
269 }
270 catch( uno::Exception& )
271 {
272 }
273 }
274
275 // no null date available -> no calculations possible
276 throw uno::RuntimeException();
277}
278
279
281 sal_uInt16 nDay1, sal_uInt16 nMonth1, sal_uInt16 nYear1, bool bLeapYear1,
282 sal_uInt16 nDay2, sal_uInt16 nMonth2, sal_uInt16 nYear2,
283 bool bUSAMethod )
284{
285 if( nDay1 == 31 )
286 nDay1--;
287 else if( bUSAMethod && ( nMonth1 == 2 && ( nDay1 == 29 || ( nDay1 == 28 && !bLeapYear1 ) ) ) )
288 nDay1 = 30;
289
290 if( nDay2 == 31 )
291 {
292 if( bUSAMethod && nDay1 != 30 )
293 {
294 nDay2 = 1;
295 if( nMonth2 == 12 )
296 {
297 nYear2++;
298 nMonth2 = 1;
299 }
300 else
301 nMonth2++;
302 }
303 else
304 nDay2 = 30;
305 }
306
307 return nDay2 + nMonth2 * 30 + nYear2 * 360 - nDay1 - nMonth1 * 30 - nYear1 * 360;
308}
309
310
311sal_Int32 GetDiffDate360( sal_Int32 nNullDate, sal_Int32 nDate1, sal_Int32 nDate2, bool bUSAMethod )
312{
313 nDate1 += nNullDate;
314 nDate2 += nNullDate;
315
316 sal_uInt16 nDay1, nMonth1, nYear1, nDay2, nMonth2, nYear2;
317
318 DaysToDate( nDate1, nDay1, nMonth1, nYear1 );
319 DaysToDate( nDate2, nDay2, nMonth2, nYear2 );
320
321 return GetDiffDate360( nDay1, nMonth1, nYear1, IsLeapYear( nYear1 ), nDay2, nMonth2, nYear2, bUSAMethod );
322}
323
324
325sal_Int32 GetDaysInYears( sal_uInt16 nYear1, sal_uInt16 nYear2 )
326{
327 sal_uInt16 nLeaps = 0;
328 for( sal_uInt16 n = nYear1 ; n <= nYear2 ; n++ )
329 {
330 if( IsLeapYear( n ) )
331 nLeaps++;
332 }
333
334 sal_uInt32 nSum = 1;
335 nSum += nYear2;
336 nSum -= nYear1;
337 nSum *= 365;
338 nSum += nLeaps;
339
340 return nSum;
341}
342
343
344sal_Int32 GetDiffDate( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode,
345 sal_Int32* pOptDaysIn1stYear )
346{
347 bool bNeg = nStartDate > nEndDate;
348
349 if( bNeg )
350 std::swap( nStartDate, nEndDate );
351
352 sal_Int32 nRet;
353
354 switch( nMode )
355 {
356 case 0: // 0=USA (NASD) 30/360
357 case 4: // 4=Europe 30/360
358 {
359 sal_uInt16 nD1, nM1, nY1, nD2, nM2, nY2;
360
361 nStartDate += nNullDate;
362 nEndDate += nNullDate;
363
364 DaysToDate( nStartDate, nD1, nM1, nY1 );
365 DaysToDate( nEndDate, nD2, nM2, nY2 );
366
367 bool bLeap = IsLeapYear( nY1 );
368 sal_Int32 nDays, nMonths;
369
370 nMonths = nM2 - nM1;
371 nDays = nD2 - nD1;
372
373 nMonths += ( nY2 - nY1 ) * 12;
374
375 nRet = nMonths * 30 + nDays;
376 if( nMode == 0 && nM1 == 2 && nM2 != 2 && nY1 == nY2 )
377 nRet -= bLeap? 1 : 2;
378
379 if( pOptDaysIn1stYear )
380 *pOptDaysIn1stYear = 360;
381 }
382 break;
383 case 1: // 1=exact/exact
384 if( pOptDaysIn1stYear )
385 {
386 sal_uInt16 nD, nM, nY;
387
388 DaysToDate( nStartDate + nNullDate, nD, nM, nY );
389
390 *pOptDaysIn1stYear = IsLeapYear( nY )? 366 : 365;
391 }
392 nRet = nEndDate - nStartDate;
393 break;
394 case 2: // 2=exact/360
395 nRet = nEndDate - nStartDate;
396 if( pOptDaysIn1stYear )
397 *pOptDaysIn1stYear = 360;
398 break;
399 case 3: //3=exact/365
400 nRet = nEndDate - nStartDate;
401 if( pOptDaysIn1stYear )
402 *pOptDaysIn1stYear = 365;
403 break;
404 default:
405 throw lang::IllegalArgumentException();
406 }
407
408 return bNeg? -nRet : nRet;
409}
410
411
412double GetYearDiff( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode )
413{
414 sal_Int32 nDays1stYear;
415 sal_Int32 nTotalDays = GetDiffDate( nNullDate, nStartDate, nEndDate, nMode, &nDays1stYear );
416
417 return double( nTotalDays ) / double( nDays1stYear );
418}
419
420
421sal_Int32 GetDaysInYear( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nMode )
422{
423 switch( nMode )
424 {
425 case 0: // 0=USA (NASD) 30/360
426 case 2: // 2=exact/360
427 case 4: // 4=Europe 30/360
428 return 360;
429 case 1: // 1=exact/exact
430 {
431 sal_uInt16 nD, nM, nY;
432 nDate += nNullDate;
433 DaysToDate( nDate, nD, nM, nY );
434 return IsLeapYear( nY )? 366 : 365;
435 }
436 case 3: //3=exact/365
437 return 365;
438 default:
439 throw lang::IllegalArgumentException();
440 }
441}
442
443
444// tdf69569 making code compliant with change request for ODFF1.2 par 4.11.7.7
451double GetYearFrac( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode )
452{
453 if( nStartDate == nEndDate )
454 return 0.0; // nothing to do...
455
456 if( nStartDate > nEndDate )
457 std::swap( nStartDate, nEndDate );
458
459 sal_Int32 nDate1 = nStartDate + nNullDate;
460 sal_Int32 nDate2 = nEndDate + nNullDate;
461
462 sal_uInt16 nDay1, nDay2;
463 sal_uInt16 nMonth1, nMonth2;
464 sal_uInt16 nYear1, nYear2;
465
466 DaysToDate( nDate1, nDay1, nMonth1, nYear1 );
467 DaysToDate( nDate2, nDay2, nMonth2, nYear2 );
468
469 // calculate days between nDate1 and nDate2
470 sal_Int32 nDayDiff;
471 switch( nMode )
472 {
473 case 0: // 0=USA (NASD) 30/360
474 if ( nDay1 == 31 )
475 {
476 nDay1--;
477 }
478 if ( nDay1 == 30 && nDay2 == 31 )
479 {
480 nDay2--;
481 }
482 else
483 {
484 if ( nMonth1 == 2 && nDay1 == ( IsLeapYear( nYear1 ) ? 29 : 28 ) )
485 {
486 nDay1 = 30;
487 if ( nMonth2 == 2 && nDay2 == ( IsLeapYear( nYear2 ) ? 29 : 28 ) )
488 {
489 nDay2 = 30;
490 }
491 }
492 }
493 nDayDiff = ( nYear2 - nYear1 ) * 360 + ( nMonth2 - nMonth1 ) * 30 + ( nDay2 - nDay1 );
494 break;
495 case 1: // 1=exact/exact
496 case 2: // 2=exact/360
497 case 3: // 3=exact/365
498 nDayDiff = nDate2 - nDate1;
499 break;
500 case 4: // 4=Europe 30/360
501 if ( nDay1 == 31 )
502 {
503 nDay1--;
504 }
505 if ( nDay2 == 31 )
506 {
507 nDay2--;
508 }
509 nDayDiff = ( nYear2 - nYear1 ) * 360 + ( nMonth2 - nMonth1 ) * 30 + ( nDay2 - nDay1 );
510 break;
511 default:
512 throw lang::IllegalArgumentException();
513 }
514
515 //calculate days in year
516 double nDaysInYear;
517 switch( nMode )
518 {
519 case 0: // 0=USA (NASD) 30/360
520 case 2: // 2=exact/360
521 case 4: // 4=Europe 30/360
522 nDaysInYear = 360;
523 break;
524 case 1: // 1=exact/exact
525 {
526 const bool isYearDifferent = ( nYear1 != nYear2 );
527 // ODFv1.2 part 2 section 4.11.7.7.7
528 if ( isYearDifferent &&
529 ( ( nYear2 != nYear1 + 1 ) ||
530 ( nMonth1 < nMonth2 ) ||
531 ( nMonth1 == nMonth2 && nDay1 < nDay2 ) ) )
532 {
533 // return average of days in year between nDate1 and nDate2, inclusive
534 sal_Int32 nDayCount = 0;
535 for ( sal_uInt16 i = nYear1; i <= nYear2; i++ )
536 nDayCount += ( IsLeapYear( i ) ? 366 : 365 );
537
538 nDaysInYear = static_cast<double>(nDayCount) / static_cast<double>( nYear2 - nYear1 + 1 );
539 }
540 else
541 {
542 // as a consequence, !isYearDifferent or
543 // nYear2 == nYear + 1 and (nMonth1 > nMonth2 or
544 // (nMonth1 == nMonth2 and nDay1 >= nDay2))
545 assert( ( !isYearDifferent ||
546 ( nYear1 + 1 == nYear2 &&
547 ( nMonth1 > nMonth2 ||
548 ( nMonth1 == nMonth2 || nDay1 >= nDay2 ) ) ) ) );
549
550 // ODFv1.2 part 2 section 4.11.7.7.8 (CHANGE REQUEST PENDING, see tdf6959)
551 if ( !isYearDifferent && IsLeapYear( nYear1 ) )
552 {
553 nDaysInYear = 366;
554 }
555 else
556 {
557 // ODFv1.2 part 2 section 4.11.7.7.9/10 (CHANGE REQUEST PENDING, see tdf69569)
558 // we need to determine whether there is a 29 February
559 // between nDate1 (inclusive) and nDate2 (inclusive)
560 // the case of nYear1 == nYear2 is adequately tested in previous test
561 if( isYearDifferent &&
562 ( ( IsLeapYear( nYear1 ) &&
563 ( ( nMonth1 < 2 ) || ( ( nMonth1 == 2 ) && ( nDay1 <= 29 ) ) ) ) ||
564 ( IsLeapYear( nYear2 ) &&
565 ( nMonth2 > 2 || ( ( nMonth2 == 2 ) && ( nDay2 == 29 ) ) ) ) ) )
566 {
567 nDaysInYear = 366;
568 }
569 else
570 {
571 nDaysInYear = 365;
572 }
573 }
574 }
575 }
576 break;
577 case 3: // 3=exact/365
578 nDaysInYear = 365;
579 break;
580 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
581 default:
582 throw lang::IllegalArgumentException();
583 }
584
585 return double( nDayDiff ) / nDaysInYear;
586}
587
588double BinomialCoefficient( double n, double k )
589{
590 // This method is a copy of BinomKoeff()
591 // found in sc/source/core/tool/interpr3.cxx
592
593 double nVal = 0.0;
594 k = ::rtl::math::approxFloor(k);
595 if (n < k)
596 nVal = 0.0;
597 else if (k == 0.0)
598 nVal = 1.0;
599 else
600 {
601 nVal = n/k;
602 n--;
603 k--;
604 while (k > 0.0)
605 {
606 nVal *= n/k;
607 k--;
608 n--;
609 }
610 }
611 return nVal;
612}
613
614double GetGcd( double f1, double f2 )
615{
616 double f = fmod( f1, f2 );
617 while( f > 0.0 )
618 {
619 f1 = f2;
620 f2 = f;
621 f = fmod( f1, f2 );
622 }
623
624 return f2;
625}
626
627
628double ConvertToDec( const OUString& aStr, sal_uInt16 nBase, sal_uInt16 nCharLim )
629{
630 if ( nBase < 2 || nBase > 36 )
631 throw lang::IllegalArgumentException();
632
633 sal_uInt32 nStrLen = aStr.getLength();
634 if( nStrLen > nCharLim )
635 throw lang::IllegalArgumentException();
636 else if( !nStrLen )
637 return 0.0;
638
639 double fVal = 0.0;
640
641 const sal_Unicode* p = aStr.getStr();
642
643 sal_uInt16 nFirstDig = 0;
644 bool bFirstDig = true;
645 double fBase = nBase;
646
647 while ( *p )
648 {
649 sal_uInt16 n;
650
651 if( '0' <= *p && *p <= '9' )
652 n = *p - '0';
653 else if( 'A' <= *p && *p <= 'Z' )
654 n = 10 + ( *p - 'A' );
655 else if ( 'a' <= *p && *p <= 'z' )
656 n = 10 + ( *p - 'a' );
657 else
658 n = nBase;
659
660 if( n >= nBase )
661 throw lang::IllegalArgumentException(); // illegal char!
662
663 if( bFirstDig )
664 {
665 bFirstDig = false;
666 nFirstDig = n;
667 }
668 fVal = fVal * fBase + double( n );
669
670 p++;
671
672 }
673
674 if( nStrLen == nCharLim && !bFirstDig && (nFirstDig >= nBase / 2) )
675 { // handling negative values
676 fVal = ( pow( double( nBase ), double( nCharLim ) ) - fVal ); // complement
677 fVal *= -1.0;
678 }
679
680 return fVal;
681}
682
683
684static char GetMaxChar( sal_uInt16 nBase )
685{
686 const char* const c = "--123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
687 return c[ nBase ];
688}
689
690
691OUString ConvertFromDec( double fNum, double fMin, double fMax, sal_uInt16 nBase,
692 sal_Int32 nPlaces, sal_Int32 nMaxPlaces, bool bUsePlaces )
693{
694 fNum = ::rtl::math::approxFloor( fNum );
695 fMin = ::rtl::math::approxFloor( fMin );
696 fMax = ::rtl::math::approxFloor( fMax );
697
698 if( fNum < fMin || fNum > fMax || ( bUsePlaces && ( nPlaces <= 0 || nPlaces > nMaxPlaces ) ) )
699 throw lang::IllegalArgumentException();
700
701 sal_Int64 nNum = static_cast< sal_Int64 >( fNum );
702 bool bNeg = nNum < 0;
703 if( bNeg )
704 nNum = sal_Int64( pow( double( nBase ), double( nMaxPlaces ) ) ) + nNum;
705
706 OUString aRet(OUString::number(nNum, nBase).toAsciiUpperCase());
707
708
709 if( bUsePlaces )
710 {
711 sal_Int32 nLen = aRet.getLength();
712 if( !bNeg && nLen > nPlaces )
713 {
714 throw lang::IllegalArgumentException();
715 }
716 else if( ( bNeg && nLen < nMaxPlaces ) || ( !bNeg && nLen < nPlaces ) )
717 {
718 sal_Int32 nLeft = nPlaces - nLen;
719 std::unique_ptr<char[]> p( new char[ nLeft + 1 ] );
720 memset( p.get(), bNeg ? GetMaxChar( nBase ) : '0', nLeft );
721 p[ nLeft ] = 0x00;
722 aRet = OUString( p.get(), nLeft, RTL_TEXTENCODING_MS_1252 ) + aRet;
723 }
724 }
725
726 return aRet;
727}
728
729double Erf( double x )
730{
731 return std::erf(x);
732}
733
734double Erfc( double x )
735{
736 return std::erfc(x);
737}
738
739static bool IsNum( sal_Unicode c )
740{
741 return c >= '0' && c <= '9';
742}
743
744
745static bool IsComma( sal_Unicode c )
746{
747 return c == '.' || c == ',';
748}
749
750
751static bool IsExpStart( sal_Unicode c )
752{
753 return c == 'e' || c == 'E';
754}
755
756
757static bool IsImagUnit( sal_Unicode c )
758{
759 return c == 'i' || c == 'j';
760}
761
762
763static sal_uInt16 GetVal( sal_Unicode c )
764{
765 return sal_uInt16( c - '0' );
766}
767
768
769bool ParseDouble( const sal_Unicode*& rp, double& rRet )
770{
771 double fInt = 0.0;
772 double fFrac = 0.0;
773 double fMult = 0.1; // multiplier to multiply digits with, when adding fractional ones
774 sal_Int32 nExp = 0;
775 sal_Int32 nMaxExp = 307;
776 sal_uInt16 nDigCnt = 18; // max. number of digits to read in, rest doesn't matter
777
778 enum State { S_End = 0, S_Sign, S_IntStart, S_Int, S_IgnoreIntDigs, S_Frac, S_IgnoreFracDigs, S_ExpSign, S_Exp };
779
780 State eS = S_Sign;
781
782 bool bNegNum = false;
783 bool bNegExp = false;
784
785 const sal_Unicode* p = rp;
786 sal_Unicode c;
787
788 while( eS )
789 {
790 c = *p;
791 switch( eS )
792 {
793 case S_Sign:
794 if( IsNum( c ) )
795 {
796 fInt = GetVal( c );
797 nDigCnt--;
798 eS = S_Int;
799 }
800 else if( c == '-' )
801 {
802 bNegNum = true;
803 eS = S_IntStart;
804 }
805 else if( c == '+' )
806 eS = S_IntStart;
807 else if( IsComma( c ) )
808 eS = S_Frac;
809 else
810 return false;
811 break;
812 case S_IntStart:
813 if( IsNum( c ) )
814 {
815 fInt = GetVal( c );
816 nDigCnt--;
817 eS = S_Int;
818 }
819 else if( IsComma( c ) )
820 eS = S_Frac;
821 else if( IsImagUnit( c ) )
822 {
823 rRet = 0.0;
824 return true;
825 }
826 else
827 return false;
828 break;
829 case S_Int:
830 if( IsNum( c ) )
831 {
832 fInt *= 10.0;
833 fInt += double( GetVal( c ) );
834 nDigCnt--;
835 if( !nDigCnt )
836 eS = S_IgnoreIntDigs;
837 }
838 else if( IsComma( c ) )
839 eS = S_Frac;
840 else if( IsExpStart( c ) )
841 eS = S_ExpSign;
842 else
843 eS = S_End;
844 break;
845 case S_IgnoreIntDigs:
846 if( IsNum( c ) )
847 nExp++; // just multiply num with 10... ;-)
848 else if( IsComma( c ) )
849 eS = S_Frac;
850 else if( IsExpStart( c ) )
851 eS = S_ExpSign;
852 else
853 eS = S_End;
854 break;
855 case S_Frac:
856 if( IsNum( c ) )
857 {
858 fFrac += double( GetVal( c ) ) * fMult;
859 nDigCnt--;
860 if( nDigCnt )
861 fMult *= 0.1;
862 else
863 eS = S_IgnoreFracDigs;
864 }
865 else if( IsExpStart( c ) )
866 eS = S_ExpSign;
867 else
868 eS = S_End;
869 break;
870 case S_IgnoreFracDigs:
871 if( IsExpStart( c ) )
872 eS = S_ExpSign;
873 else if( !IsNum( c ) )
874 eS = S_End;
875 break;
876 case S_ExpSign:
877 if( IsNum( c ) )
878 {
879 nExp = GetVal( c );
880 eS = S_Exp;
881 }
882 else if( c == '-' )
883 {
884 bNegExp = true;
885 eS = S_Exp;
886 }
887 else if( c != '+' )
888 eS = S_End;
889 break;
890 case S_Exp:
891 if( IsNum( c ) )
892 {
893 nExp *= 10;
894 nExp += GetVal( c );
895 if( nExp > nMaxExp )
896 return false;
897 }
898 else
899 eS = S_End;
900 break;
901 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
902 case S_End:
903 break;
904 }
905
906 p++;
907 }
908
909 p--; // set pointer back to last
910 rp = p;
911
912 fInt += fFrac;
913
914 if (fInt != 0.0) // exact check; log10(0.0) may entail a pole error
915 {
916 sal_Int32 nLog10 = sal_Int32( log10( fInt ) );
917
918 if( bNegExp )
919 nExp = -nExp;
920
921 if( nLog10 + nExp > nMaxExp )
922 return false;
923
924 fInt = ::rtl::math::pow10Exp( fInt, nExp );
925 }
926
927 if( bNegNum )
928 fInt = -fInt;
929
930 rRet = fInt;
931
932 return true;
933}
934
935
936OUString GetString( double f, bool bLeadingSign, sal_uInt16 nMaxDig )
937{
938 const int nBuff = 256;
939 char aBuff[ nBuff + 1 ];
940 const char* pFormStr = bLeadingSign? "%+.*g" : "%.*g";
941 int nLen = snprintf( aBuff, nBuff, pFormStr, int( nMaxDig ), f );
942 // you never know which underlying implementation you get ...
943 aBuff[nBuff] = 0;
944 if ( nLen < 0 || nLen > nBuff )
945 nLen = strlen( aBuff );
946
947 OUString aRet( aBuff, nLen, RTL_TEXTENCODING_MS_1252 );
948
949 return aRet;
950}
951
952
953double GetAmordegrc( sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer,
954 double fRestVal, double fPer, double fRate, sal_Int32 nBase )
955{
956 sal_uInt32 nPer = sal_uInt32( fPer );
957 double fUsePer = 1.0 / fRate;
958 double fAmorCoeff;
959
960 if( fUsePer < 3.0 )
961 fAmorCoeff = 1.0;
962 else if( fUsePer < 5.0 )
963 fAmorCoeff = 1.5;
964 else if( fUsePer <= 6.0 )
965 fAmorCoeff = 2.0;
966 else
967 fAmorCoeff = 2.5;
968
969 fRate *= fAmorCoeff;
970 double fNRate = ::rtl::math::round( GetYearFrac( nNullDate, nDate, nFirstPer, nBase ) * fRate * fCost );
971 fCost -= fNRate;
972 double fRest = fCost - fRestVal; // aboriginal cost - residual value - sum of all write-downs
973
974 for( sal_uInt32 n = 0 ; n < nPer ; n++ )
975 {
976 fNRate = ::rtl::math::round( fRate * fCost );
977 fRest -= fNRate;
978
979 if( fRest < 0.0 )
980 {
981 switch( nPer - n )
982 {
983 case 0:
984 case 1:
985 return ::rtl::math::round( fCost * 0.5 );
986 default:
987 return 0.0;
988 }
989 }
990
991 fCost -= fNRate;
992 }
993
994 return fNRate;
995}
996
997
998double GetAmorlinc( sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer,
999 double fRestVal, double fPer, double fRate, sal_Int32 nBase )
1000{
1001 sal_uInt32 nPer = sal_uInt32( fPer );
1002 double fOneRate = fCost * fRate;
1003 double fCostDelta = fCost - fRestVal;
1004 double f0Rate = GetYearFrac( nNullDate, nDate, nFirstPer, nBase ) * fRate * fCost;
1005 sal_uInt32 nNumOfFullPeriods = sal_uInt32( ( fCost - fRestVal - f0Rate) / fOneRate );
1006
1007 double fResult = 0.0;
1008 if( nPer == 0 )
1009 fResult = f0Rate;
1010 else if( nPer <= nNumOfFullPeriods )
1011 fResult = fOneRate;
1012 else if( nPer == nNumOfFullPeriods + 1 )
1013 fResult = fCostDelta - fOneRate * nNumOfFullPeriods - f0Rate;
1014
1015 if ( fResult > 0.0 )
1016 return fResult;
1017 else
1018 return 0.0;
1019}
1020
1021
1022double GetDuration( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup,
1023 double fYield, sal_Int32 nFreq, sal_Int32 nBase )
1024{
1025 double fYearfrac = GetYearFrac( nNullDate, nSettle, nMat, nBase );
1026 double fNumOfCoups = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase );
1027 double fDur = 0.0;
1028 const double f100 = 100.0;
1029 fCoup *= f100 / double( nFreq ); // fCoup is used as cash flow
1030 fYield /= nFreq;
1031 fYield += 1.0;
1032
1033 double nDiff = fYearfrac * nFreq - fNumOfCoups;
1034
1035 double t;
1036
1037 for( t = 1.0 ; t < fNumOfCoups ; t++ )
1038 fDur += ( t + nDiff ) * fCoup / pow( fYield, t + nDiff );
1039
1040 fDur += ( fNumOfCoups + nDiff ) * ( fCoup + f100 ) / pow( fYield, fNumOfCoups + nDiff );
1041
1042 double p = 0.0;
1043 for( t = 1.0 ; t < fNumOfCoups ; t++ )
1044 p += fCoup / pow( fYield, t + nDiff );
1045
1046 p += ( fCoup + f100 ) / pow( fYield, fNumOfCoups + nDiff );
1047
1048 fDur /= p;
1049 fDur /= double( nFreq );
1050
1051 return fDur;
1052}
1053
1054
1055double GetYieldmat( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue,
1056 double fRate, double fPrice, sal_Int32 nBase )
1057{
1058 double fIssMat = GetYearFrac( nNullDate, nIssue, nMat, nBase );
1059 double fIssSet = GetYearFrac( nNullDate, nIssue, nSettle, nBase );
1060 double fSetMat = GetYearFrac( nNullDate, nSettle, nMat, nBase );
1061
1062 double y = 1.0 + fIssMat * fRate;
1063 y /= fPrice / 100.0 + fIssSet * fRate;
1064 y--;
1065 y /= fSetMat;
1066
1067 return y;
1068}
1069
1070
1071double GetOddfprice( sal_Int32 /*nNullDate*/, sal_Int32 /*nSettle*/, sal_Int32 /*nMat*/, sal_Int32 /*nIssue*/,
1072 sal_Int32 /*nFirstCoup*/, double /*fRate*/, double /*fYield*/, double /*fRedemp*/, sal_Int32 /*nFreq*/,
1073 sal_Int32 /*nBase*/ )
1074{
1075 // If you change this to not unconditionally throw, the
1076 // SAL_WNOUNREACHABLE_CODE_PUSH/POP around the caller in
1077 // financial.cxx can be removed.
1078 throw uno::RuntimeException();
1079}
1080
1081
1082double getYield_( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup, double fPrice,
1083 double fRedemp, sal_Int32 nFreq, sal_Int32 nBase )
1084{
1085 double fRate = fCoup;
1086 double fPriceN = 0.0;
1087 double fYield1 = 0.0;
1088 double fYield2 = 1.0;
1089 double fPrice1 = getPrice_( nNullDate, nSettle, nMat, fRate, fYield1, fRedemp, nFreq, nBase );
1090 double fPrice2 = getPrice_( nNullDate, nSettle, nMat, fRate, fYield2, fRedemp, nFreq, nBase );
1091 double fYieldN = ( fYield2 - fYield1 ) * 0.5;
1092
1093 for( sal_uInt32 nIter = 0 ; nIter < 100 && !rtl::math::approxEqual(fPriceN, fPrice) ; nIter++ )
1094 {
1095 fPriceN = getPrice_( nNullDate, nSettle, nMat, fRate, fYieldN, fRedemp, nFreq, nBase );
1096
1097 if( rtl::math::approxEqual(fPrice, fPrice1) )
1098 return fYield1;
1099 else if( rtl::math::approxEqual(fPrice, fPrice2) )
1100 return fYield2;
1101 else if( rtl::math::approxEqual(fPrice, fPriceN) )
1102 return fYieldN;
1103 else if( fPrice < fPrice2 )
1104 {
1105 fYield2 *= 2.0;
1106 fPrice2 = getPrice_( nNullDate, nSettle, nMat, fRate, fYield2, fRedemp, nFreq, nBase );
1107
1108 fYieldN = ( fYield2 - fYield1 ) * 0.5;
1109 }
1110 else
1111 {
1112 if( fPrice < fPriceN )
1113 {
1114 fYield1 = fYieldN;
1115 fPrice1 = fPriceN;
1116 }
1117 else
1118 {
1119 fYield2 = fYieldN;
1120 fPrice2 = fPriceN;
1121 }
1122
1123 fYieldN = fYield2 - ( fYield2 - fYield1 ) * ( ( fPrice - fPrice2 ) / ( fPrice1 - fPrice2 ) );
1124 }
1125 }
1126
1127 if( fabs( fPrice - fPriceN ) > fPrice / 100.0 )
1128 throw lang::IllegalArgumentException(); // result not precise enough
1129
1130 return fYieldN;
1131}
1132
1133
1134double getPrice_( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fRate, double fYield,
1135 double fRedemp, sal_Int32 nFreq, sal_Int32 nBase )
1136{
1137 double fFreq = nFreq;
1138
1139 double fE = GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase );
1140 double fDSC_E = GetCoupdaysnc( nNullDate, nSettle, nMat, nFreq, nBase ) / fE;
1141 double fN = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase );
1142 double fA = GetCoupdaybs( nNullDate, nSettle, nMat, nFreq, nBase );
1143
1144 double fRet = fRedemp / ( pow( 1.0 + fYield / fFreq, fN - 1.0 + fDSC_E ) );
1145 fRet -= 100.0 * fRate / fFreq * fA / fE;
1146
1147 double fT1 = 100.0 * fRate / fFreq;
1148 double fT2 = 1.0 + fYield / fFreq;
1149
1150 for( double fK = 0.0 ; fK < fN ; fK++ )
1151 fRet += fT1 / pow( fT2, fK + fDSC_E );
1152
1153 return fRet;
1154}
1155
1156
1157double GetOddfyield( sal_Int32 /*nNullDate*/, sal_Int32 /*nSettle*/, sal_Int32 /*nMat*/, sal_Int32 /*nIssue*/,
1158 sal_Int32 /*nFirstCoup*/, double /*fRate*/, double /*fPrice*/, double /*fRedemp*/, sal_Int32 /*nFreq*/,
1159 sal_Int32 /*nBase*/ )
1160{
1161 // If you change this to not unconditionally throw, the
1162 // SAL_WNOUNREACHABLE_CODE_PUSH/POP around the caller in
1163 // financial.cxx can be removed.
1164 throw uno::RuntimeException();
1165}
1166
1167
1168double GetOddlprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastCoup,
1169 double fRate, double fYield, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase )
1170{
1171 double fFreq = double( nFreq );
1172 double fDCi = GetYearFrac( nNullDate, nLastCoup, nMat, nBase ) * fFreq;
1173 double fDSCi = GetYearFrac( nNullDate, nSettle, nMat, nBase ) * fFreq;
1174 double fAi = GetYearFrac( nNullDate, nLastCoup, nSettle, nBase ) * fFreq;
1175
1176 double p = fRedemp + fDCi * 100.0 * fRate / fFreq;
1177 p /= fDSCi * fYield / fFreq + 1.0;
1178 p -= fAi * 100.0 * fRate / fFreq;
1179
1180 return p;
1181}
1182
1183
1184double GetOddlyield( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastCoup,
1185 double fRate, double fPrice, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase )
1186{
1187 double fFreq = double( nFreq );
1188 double fDCi = GetYearFrac( nNullDate, nLastCoup, nMat, nBase ) * fFreq;
1189 double fDSCi = GetYearFrac( nNullDate, nSettle, nMat, nBase ) * fFreq;
1190 double fAi = GetYearFrac( nNullDate, nLastCoup, nSettle, nBase ) * fFreq;
1191
1192 double y = fRedemp + fDCi * 100.0 * fRate / fFreq;
1193 y /= fPrice + fAi * 100.0 * fRate / fFreq;
1194 y--;
1195 y *= fFreq / fDSCi;
1196
1197 return y;
1198}
1199
1200
1201double GetPmt( double fRate, double fNper, double fPv, double fFv, sal_Int32 nPayType )
1202{
1203 double fPmt;
1204 if( fRate == 0.0 )
1205 fPmt = ( fPv + fFv ) / fNper;
1206 else
1207 {
1208 double fTerm = pow( 1.0 + fRate, fNper );
1209 if( nPayType > 0 )
1210 fPmt = ( fFv * fRate / ( fTerm - 1.0 ) + fPv * fRate / ( 1.0 - 1.0 / fTerm ) ) / ( 1.0 + fRate );
1211 else
1212 fPmt = fFv * fRate / ( fTerm - 1.0 ) + fPv * fRate / ( 1.0 - 1.0 / fTerm );
1213 }
1214
1215 return -fPmt;
1216}
1217
1218
1219double GetFv( double fRate, double fNper, double fPmt, double fPv, sal_Int32 nPayType )
1220{
1221 double fFv;
1222 if( fRate == 0.0 )
1223 fFv = fPv + fPmt * fNper;
1224 else
1225 {
1226 double fTerm = pow( 1.0 + fRate, fNper );
1227 if( nPayType > 0 )
1228 fFv = fPv * fTerm + fPmt * ( 1.0 + fRate ) * ( fTerm - 1.0 ) / fRate;
1229 else
1230 fFv = fPv * fTerm + fPmt * ( fTerm - 1.0 ) / fRate;
1231 }
1232
1233 return -fFv;
1234}
1235
1236// financial functions COUP***
1237
1238// COUPPCD: find last coupon date before settlement (can be equal to settlement)
1240static void lcl_GetCouppcd( ScaDate& rDate, const ScaDate& rSettle, const ScaDate& rMat, sal_Int32 nFreq )
1241{
1242 rDate = rMat;
1243 rDate.setYear( rSettle.getYear() );
1244 if( rDate < rSettle )
1245 rDate.addYears( 1 );
1246 while( rDate > rSettle )
1247 rDate.addMonths( -12 / nFreq );
1248}
1249
1250double GetCouppcd( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase )
1251{
1252 if( nSettle >= nMat || isFreqInvalid(nFreq) )
1253 throw lang::IllegalArgumentException();
1254
1255 ScaDate aDate;
1256 lcl_GetCouppcd( aDate, ScaDate( nNullDate, nSettle, nBase ), ScaDate( nNullDate, nMat, nBase ), nFreq );
1257 return aDate.getDate( nNullDate );
1258}
1259
1260// COUPNCD: find first coupon date after settlement (is never equal to settlement)
1262static void lcl_GetCoupncd( ScaDate& rDate, const ScaDate& rSettle, const ScaDate& rMat, sal_Int32 nFreq )
1263{
1264 rDate = rMat;
1265 rDate.setYear( rSettle.getYear() );
1266 if( rDate > rSettle )
1267 rDate.addYears( -1 );
1268 while( rDate <= rSettle )
1269 rDate.addMonths( 12 / nFreq );
1270}
1271
1272double GetCoupncd( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase )
1273{
1274 if( nSettle >= nMat || isFreqInvalid(nFreq) )
1275 throw lang::IllegalArgumentException();
1276
1277 ScaDate aDate;
1278 lcl_GetCoupncd( aDate, ScaDate( nNullDate, nSettle, nBase ), ScaDate( nNullDate, nMat, nBase ), nFreq );
1279 return aDate.getDate( nNullDate );
1280}
1281
1282// COUPDAYBS: get day count: coupon date before settlement <-> settlement
1283double GetCoupdaybs( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase )
1284{
1285 if( nSettle >= nMat || isFreqInvalid(nFreq) )
1286 throw lang::IllegalArgumentException();
1287
1288 ScaDate aSettle( nNullDate, nSettle, nBase );
1289 ScaDate aDate;
1290 lcl_GetCouppcd( aDate, aSettle, ScaDate( nNullDate, nMat, nBase ), nFreq );
1291 return ScaDate::getDiff( aDate, aSettle );
1292}
1293
1294// COUPDAYSNC: get day count: settlement <-> coupon date after settlement
1295double GetCoupdaysnc( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase )
1296{
1297 if( nSettle >= nMat || isFreqInvalid(nFreq) )
1298 throw lang::IllegalArgumentException();
1299
1300 if( (nBase != 0) && (nBase != 4) )
1301 {
1302 ScaDate aSettle( nNullDate, nSettle, nBase );
1303 ScaDate aDate;
1304 lcl_GetCoupncd( aDate, aSettle, ScaDate( nNullDate, nMat, nBase ), nFreq );
1305 return ScaDate::getDiff( aSettle, aDate );
1306 }
1307 return GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase ) - GetCoupdaybs( nNullDate, nSettle, nMat, nFreq, nBase );
1308}
1309
1310// COUPDAYS: get day count: coupon date before settlement <-> coupon date after settlement
1311double GetCoupdays( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase )
1312{
1313 if( nSettle >= nMat || isFreqInvalid(nFreq) )
1314 throw lang::IllegalArgumentException();
1315
1316 if( nBase == 1 )
1317 {
1318 ScaDate aDate;
1319 lcl_GetCouppcd( aDate, ScaDate( nNullDate, nSettle, nBase ), ScaDate( nNullDate, nMat, nBase ), nFreq );
1320 ScaDate aNextDate( aDate );
1321 aNextDate.addMonths( 12 / nFreq );
1322 return ScaDate::getDiff( aDate, aNextDate );
1323 }
1324 return static_cast< double >( GetDaysInYear( 0, 0, nBase ) ) / nFreq;
1325}
1326
1327// COUPNUM: get count of coupon dates
1328double GetCoupnum( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase )
1329{
1330 if( nSettle >= nMat || isFreqInvalid(nFreq) )
1331 throw lang::IllegalArgumentException();
1332
1333 ScaDate aMat( nNullDate, nMat, nBase );
1334 ScaDate aDate;
1335 lcl_GetCouppcd( aDate, ScaDate( nNullDate, nSettle, nBase ), aMat, nFreq );
1336 sal_uInt16 nMonths = (aMat.getYear() - aDate.getYear()) * 12 + aMat.getMonth() - aDate.getMonth();
1337 return static_cast< double >( nMonths * nFreq / 12 );
1338}
1339
1341 aIntName( OUString::createFromAscii( r.pIntName ) ),
1342 pUINameID( r.pUINameID ),
1343 pDescrID( r.pDescrID ),
1344 bDouble( r.bDouble ),
1345 bWithOpt( r.bWithOpt ),
1346 nParam( r.nNumOfParams ),
1347 eCat( r.eCat )
1348{
1349 if (r.pSuffix)
1350 aSuffix = OUString::createFromAscii(r.pSuffix);
1351
1352 aCompList.resize(2);
1353 aCompList[0] = OUString(r.pCompListID[0], strlen(r.pCompListID[0]), RTL_TEXTENCODING_UTF8);
1354 aCompList[1] = OUString(r.pCompListID[1], strlen(r.pCompListID[1]), RTL_TEXTENCODING_UTF8);
1355}
1356
1357sal_uInt16 FuncData::GetStrIndex( sal_uInt16 nParamNum ) const
1358{
1359 if( !bWithOpt )
1360 nParamNum++;
1361
1362 if( nParamNum > nParam )
1363 return nParam * 2;
1364 else
1365 return nParamNum * 2;
1366}
1367
1369{
1370 for(const auto & rFuncData : pFuncDatas)
1371 rList.push_back(FuncData(rFuncData));
1372}
1373
1375{
1376}
1377
1378
1380{
1381}
1382
1383
1385{
1386 sal_uInt32 nIndex = Count();
1387 while( nIndex )
1388 {
1389 nIndex--;
1390 sal_Int32 nRef = Get( nIndex );
1391 if( nDay == nRef )
1392 return;
1393 else if( nDay > nRef )
1394 {
1395 maVector.insert( maVector.begin() + nIndex + 1, nDay );
1396 return;
1397 }
1398 }
1399 maVector.insert( maVector.begin(), nDay );
1400}
1401
1402
1403void SortedIndividualInt32List::Insert( sal_Int32 nDay, sal_Int32 nNullDate, bool bInsertOnWeekend )
1404{
1405 if( !nDay )
1406 return;
1407
1408 nDay += nNullDate;
1409 if( bInsertOnWeekend || (GetDayOfWeek( nDay ) < 5) )
1410 Insert( nDay );
1411}
1412
1413
1415 double fDay, sal_Int32 nNullDate, bool bInsertOnWeekend )
1416{
1417 if( (fDay < -2147483648.0) || (fDay > 2147483649.0) )
1418 throw lang::IllegalArgumentException();
1419 Insert( static_cast< sal_Int32 >( fDay ), nNullDate, bInsertOnWeekend );
1420}
1421
1422
1423bool SortedIndividualInt32List::Find( sal_Int32 nVal ) const
1424{
1425 sal_uInt32 nE = Count();
1426
1427 if( !nE || nVal < Get( 0 ) || nVal > Get( nE - 1 ) )
1428 return false;
1429
1430 // linear search
1431
1432 for( sal_uInt32 n = 0 ; n < nE ; n++ )
1433 {
1434 sal_Int32 nRef = Get( n );
1435
1436 if( nRef == nVal )
1437 return true;
1438 else if( nRef > nVal )
1439 return false;
1440 }
1441 return false;
1442}
1443
1444
1446 const ScaAnyConverter& rAnyConv,
1447 const uno::Any& rHolAny,
1448 sal_Int32 nNullDate,
1449 bool bInsertOnWeekend )
1450{
1451 double fDay;
1452 if( rAnyConv.getDouble( fDay, rHolAny ) )
1453 Insert( fDay, nNullDate, bInsertOnWeekend );
1454}
1455
1456
1458 ScaAnyConverter& rAnyConv,
1459 const uno::Reference< beans::XPropertySet >& xOptions,
1460 const uno::Any& rHolAny,
1461 sal_Int32 nNullDate )
1462{
1463 rAnyConv.init( xOptions );
1464 if( rHolAny.getValueTypeClass() == uno::TypeClass_SEQUENCE )
1465 {
1466 uno::Sequence< uno::Sequence< uno::Any > > aAnySeq;
1467 if( !(rHolAny >>= aAnySeq) )
1468 throw lang::IllegalArgumentException();
1469
1470 for( const uno::Sequence< uno::Any >& rSubSeq : std::as_const(aAnySeq) )
1471 {
1472 for( const uno::Any& rAny : rSubSeq )
1473 InsertHolidayList( rAnyConv, rAny, nNullDate, false/*bInsertOnWeekend*/ );
1474 }
1475 }
1476 else
1477 InsertHolidayList( rAnyConv, rHolAny, nNullDate, false/*bInsertOnWeekend*/ );
1478}
1479
1480
1482 const uno::Sequence< uno::Sequence< double > >& rValueSeq )
1483{
1484 for( const uno::Sequence< double >& rSubSeq : rValueSeq )
1485 {
1486 for( const double fValue : rSubSeq )
1487 Append( fValue );
1488 }
1489}
1490
1491
1493 const uno::Sequence< uno::Sequence< sal_Int32 > >& rValueSeq )
1494{
1495 for( const uno::Sequence< sal_Int32 >& rSubSeq : rValueSeq )
1496 {
1497 for( const sal_Int32 nValue : rSubSeq )
1498 Append( nValue );
1499 }
1500}
1501
1503 const ScaAnyConverter& rAnyConv,
1504 const uno::Any& rAny,
1505 bool bIgnoreEmpty )
1506{
1507 if( auto s = o3tl::tryAccess<
1508 css::uno::Sequence<css::uno::Sequence<css::uno::Any>>>(rAny) )
1509 Append( rAnyConv, *s, bIgnoreEmpty );
1510 else
1511 {
1512 double fValue;
1513 if( rAnyConv.getDouble( fValue, rAny ) )
1514 Append( fValue );
1515 else if( !bIgnoreEmpty )
1516 Append( 0.0 );
1517 }
1518}
1519
1520
1522 const ScaAnyConverter& rAnyConv,
1523 const uno::Sequence< uno::Any >& rAnySeq,
1524 bool bIgnoreEmpty )
1525{
1526 for( const uno::Any& rAny : rAnySeq )
1527 Append( rAnyConv, rAny, bIgnoreEmpty );
1528}
1529
1530
1532 const ScaAnyConverter& rAnyConv,
1533 const uno::Sequence< uno::Sequence< uno::Any > >& rAnySeq,
1534 bool bIgnoreEmpty )
1535{
1536 for( const uno::Sequence< uno::Any >& rArray : rAnySeq )
1537 Append( rAnyConv, rArray, bIgnoreEmpty );
1538}
1539
1541 ScaAnyConverter& rAnyConv,
1542 const uno::Reference< beans::XPropertySet >& xOpt,
1543 const uno::Sequence< uno::Any >& rAnySeq )
1544{
1545 rAnyConv.init( xOpt );
1546 Append( rAnyConv, rAnySeq, true/*bIgnoreEmpty*/ );
1547}
1548
1549
1550bool ScaDoubleList::CheckInsert( double ) const
1551{
1552 return true;
1553}
1554
1555
1556bool ScaDoubleListGT0::CheckInsert( double fValue ) const
1557{
1558 if( fValue < 0.0 )
1559 throw lang::IllegalArgumentException();
1560 return fValue > 0.0;
1561}
1562
1563
1564bool ScaDoubleListGE0::CheckInsert( double fValue ) const
1565{
1566 if( fValue < 0.0 )
1567 throw lang::IllegalArgumentException();
1568 return true;
1569}
1570
1571
1572Complex::Complex( const OUString& rStr )
1573{
1574 if( !ParseString( rStr, *this ) )
1575 throw lang::IllegalArgumentException();
1576}
1577
1578
1580{
1581 return c == 'i' || c == 'j';
1582}
1583
1584bool Complex::ParseString( const OUString& rStr, Complex& rCompl )
1585{
1586 rCompl.c = '\0'; // do not force a symbol, if only real part present
1587
1588 const sal_Unicode* pStr = rStr.getStr();
1589
1590 if( IsImagUnit( *pStr ) && rStr.getLength() == 1)
1591 {
1592 rCompl.r = 0.0;
1593 rCompl.i = 1.0;
1594 rCompl.c = *pStr;
1595 return true;
1596 }
1597
1598 double f;
1599
1600 if( !ParseDouble( pStr, f ) )
1601 return false;
1602
1603 switch( *pStr )
1604 {
1605 case '-': // imag part follows
1606 case '+':
1607 {
1608 double r = f;
1609 if( IsImagUnit( pStr[ 1 ] ) )
1610 {
1611 rCompl.c = pStr[ 1 ];
1612 if( pStr[ 2 ] == 0 )
1613 {
1614 rCompl.r = f;
1615 rCompl.i = ( *pStr == '+' )? 1.0 : -1.0;
1616 return true;
1617 }
1618 }
1619 else if( ParseDouble( pStr, f ) && IsImagUnit( *pStr ) )
1620 {
1621 rCompl.c = *pStr;
1622 pStr++;
1623 if( *pStr == 0 )
1624 {
1625 rCompl.r = r;
1626 rCompl.i = f;
1627 return true;
1628 }
1629 }
1630 }
1631 break;
1632 case 'j':
1633 case 'i':
1634 rCompl.c = *pStr;
1635 pStr++;
1636 if( *pStr == 0 )
1637 {
1638 rCompl.i = f;
1639 rCompl.r = 0.0;
1640 return true;
1641 }
1642 break;
1643 case 0: // only real-part
1644 rCompl.r = f;
1645 rCompl.i = 0.0;
1646 return true;
1647 }
1648
1649 return false;
1650}
1651
1652
1653OUString Complex::GetString() const
1654{
1657 OUStringBuffer aRet;
1658
1659 bool bHasImag = i != 0.0;
1660 bool bHasReal = !bHasImag || (r != 0.0);
1661
1662 if( bHasReal )
1663 aRet.append(::GetString( r, false ));
1664 if( bHasImag )
1665 {
1666 if( i == 1.0 )
1667 {
1668 if( bHasReal )
1669 aRet.append('+');
1670 }
1671 else if( i == -1.0 )
1672 aRet.append('-');
1673 else
1674 aRet.append(::GetString( i, bHasReal ));
1675 aRet.append((c != 'j') ? 'i' : 'j');
1676 }
1677
1678 return aRet.makeStringAndClear();
1679}
1680
1681
1682double Complex::Arg() const
1683{
1684 if( r == 0.0 && i == 0.0 )
1685 throw lang::IllegalArgumentException();
1686
1687 double phi = acos( r / Abs() );
1688
1689 if( i < 0.0 )
1690 phi = -phi;
1691
1692 return phi;
1693}
1694
1695
1696void Complex::Power( double fPower )
1697{
1698 if( r == 0.0 && i == 0.0 )
1699 {
1700 if( fPower <= 0 )
1701 throw lang::IllegalArgumentException();
1702 r = i = 0.0;
1703 return;
1704 }
1705
1706 double p, phi;
1707
1708 p = Abs();
1709
1710 phi = acos( r / p );
1711 if( i < 0.0 )
1712 phi = -phi;
1713
1714 p = pow( p, fPower );
1715 phi *= fPower;
1716
1717 r = cos( phi ) * p;
1718 i = sin( phi ) * p;
1719}
1720
1721
1723{
1724 static const double fMultConst = M_SQRT1_2;
1725 double p = Abs();
1726 double i_ = sqrt( p - r ) * fMultConst;
1727
1728 r = sqrt( p + r ) * fMultConst;
1729 i = ( i < 0.0 )? -i_ : i_;
1730}
1731
1732
1734{
1735 if( !::rtl::math::isValidArcArg( r ) )
1736 throw lang::IllegalArgumentException();
1737
1738 if( i )
1739 {
1740 double r_;
1741
1742 r_ = sin( r ) * cosh( i );
1743 i = cos( r ) * sinh( i );
1744 r = r_;
1745 }
1746 else
1747 r = sin( r );
1748}
1749
1750
1752{
1753 if( !::rtl::math::isValidArcArg( r ) )
1754 throw lang::IllegalArgumentException();
1755
1756 if( i )
1757 {
1758 double r_;
1759
1760 r_ = cos( r ) * cosh( i );
1761 i = -( sin( r ) * sinh( i ) );
1762 r = r_;
1763 }
1764 else
1765 r = cos( r );
1766}
1767
1768
1769void Complex::Div( const Complex& z )
1770{
1771 if( z.r == 0 && z.i == 0 )
1772 throw lang::IllegalArgumentException();
1773
1774 double a1 = r;
1775 double a2 = z.r;
1776 double b1 = i;
1777 double b2 = z.i;
1778
1779 double f = 1.0 / ( a2 * a2 + b2 * b2 );
1780
1781 r = ( a1 * a2 + b1 * b2 ) * f;
1782 i = ( a2 * b1 - a1 * b2 ) * f;
1783
1784 if( !c ) c = z.c;
1785}
1786
1787
1789{
1790 double fE = exp( r );
1791 r = fE * cos( i );
1792 i = fE * sin( i );
1793}
1794
1795
1797{
1798 if( r == 0.0 && i == 0.0 )
1799 throw lang::IllegalArgumentException();
1800
1801 double fAbs = Abs();
1802 bool bNegi = i < 0.0;
1803
1804 i = acos( r / fAbs );
1805
1806 if( bNegi )
1807 i = -i;
1808
1809 r = log( fAbs );
1810}
1811
1812
1814{
1815 Ln();
1816 Mult( M_LOG10E );
1817}
1818
1819
1821{
1822 Ln();
1823 Mult( M_LOG2E );
1824}
1825
1826
1828{
1829 if ( i )
1830 {
1831 if( !::rtl::math::isValidArcArg( 2.0 * r ) )
1832 throw lang::IllegalArgumentException();
1833 double fScale =1.0 / ( cos( 2.0 * r ) + cosh( 2.0 * i ));
1834 r = sin( 2.0 * r ) * fScale;
1835 i = sinh( 2.0 * i ) * fScale;
1836 }
1837 else
1838 {
1839 if( !::rtl::math::isValidArcArg( r ) )
1840 throw lang::IllegalArgumentException();
1841 r = tan( r );
1842 }
1843}
1844
1845
1847{
1848 if( i )
1849 {
1850 if( !::rtl::math::isValidArcArg( 2 * r ) )
1851 throw lang::IllegalArgumentException();
1852 double fScale = 1.0 / (cosh( 2.0 * i) + cos ( 2.0 * r));
1853 double r_;
1854 r_ = 2.0 * cos( r ) * cosh( i ) * fScale;
1855 i = 2.0 * sin( r ) * sinh( i ) * fScale;
1856 r = r_;
1857 }
1858 else
1859 {
1860 if( !::rtl::math::isValidArcArg( r ) )
1861 throw lang::IllegalArgumentException();
1862 r = 1.0 / cos( r );
1863 }
1864}
1865
1866
1868{
1869 if( i )
1870 {
1871 if( !::rtl::math::isValidArcArg( 2 * r ) )
1872 throw lang::IllegalArgumentException();
1873 double fScale = 1.0 / (cosh( 2.0 * i) - cos ( 2.0 * r));
1874 double r_;
1875 r_ = 2.0 * sin( r ) * cosh( i ) * fScale;
1876 i = -2.0 * cos( r ) * sinh( i ) * fScale;
1877 r = r_;
1878 }
1879 else
1880 {
1881 if( !::rtl::math::isValidArcArg( r ) )
1882 throw lang::IllegalArgumentException();
1883 r = 1.0 / sin( r );
1884 }
1885}
1886
1887
1889{
1890 if ( i )
1891 {
1892 if( !::rtl::math::isValidArcArg( 2.0 * r ) )
1893 throw lang::IllegalArgumentException();
1894 double fScale =1.0 / ( cosh( 2.0 * i ) - cos( 2.0 * r ) );
1895 r = sin( 2.0 * r ) * fScale;
1896 i = - ( sinh( 2.0 * i ) * fScale );
1897 }
1898 else
1899 {
1900 if( !::rtl::math::isValidArcArg( r ) )
1901 throw lang::IllegalArgumentException();
1902 r = 1.0 / tan( r );
1903 }
1904}
1905
1906
1908{
1909 if( !::rtl::math::isValidArcArg( r ) )
1910 throw lang::IllegalArgumentException();
1911
1912 if( i )
1913 {
1914 double r_;
1915 r_ = sinh( r ) * cos( i );
1916 i = cosh( r ) * sin( i );
1917 r = r_;
1918 }
1919 else
1920 r = sinh( r );
1921}
1922
1923
1925{
1926 if( !::rtl::math::isValidArcArg( r ) )
1927 throw lang::IllegalArgumentException();
1928
1929 if( i )
1930 {
1931 double r_;
1932 r_ = cosh( r ) * cos( i );
1933 i = sinh( r ) * sin( i );
1934 r = r_;
1935 }
1936 else
1937 r = cosh( r );
1938}
1939
1940
1942{
1943 if ( i )
1944 {
1945 if( !::rtl::math::isValidArcArg( 2.0 * r ) )
1946 throw lang::IllegalArgumentException();
1947 double fScale =1.0 / ( cosh( 2.0 * r ) + cos( 2.0 * i ));
1948 double r_;
1949 r_ = 2.0 * cosh( r ) * cos( i ) * fScale;
1950 i = - (2.0 * sinh( r ) * sin( i ) * fScale );
1951 r = r_ ;
1952 }
1953 else
1954 {
1955 if( !::rtl::math::isValidArcArg( r ) )
1956 throw lang::IllegalArgumentException();
1957 r = 1.0 / cosh( r );
1958 }
1959}
1960
1961
1963{
1964 if ( i )
1965 {
1966 if( !::rtl::math::isValidArcArg( 2.0 * r ) )
1967 throw lang::IllegalArgumentException();
1968 double fScale =1.0 / ( cosh( 2.0 * r ) - cos( 2.0 * i ));
1969 double r_;
1970 r_ = 2.0 * sinh( r ) * cos( i ) * fScale;
1971 i = - ( 2.0 * cosh( r ) * sin( i ) * fScale );
1972 r = r_ ;
1973 }
1974 else
1975 {
1976 if( !::rtl::math::isValidArcArg( r ) )
1977 throw lang::IllegalArgumentException();
1978 r = 1.0 / sinh( r );
1979 }
1980}
1981
1982
1984{
1985}
1986
1987
1988void ComplexList::Append( const uno::Sequence< uno::Sequence< OUString > >& r )
1989{
1990 for( const uno::Sequence< OUString >& rList : r )
1991 {
1992 for( const OUString& rStr : rList )
1993 {
1994 if( !rStr.isEmpty() )
1995 Append( Complex( rStr ) );
1996 }
1997 }
1998}
1999
2000
2001void ComplexList::Append( const uno::Sequence< uno::Any >& aMultPars )
2002{
2003 for( const uno::Any& r : aMultPars )
2004 {
2005 switch( r.getValueTypeClass() )
2006 {
2007 case uno::TypeClass_VOID: break;
2008 case uno::TypeClass_STRING:
2009 {
2010 auto pStr = o3tl::forceAccess<OUString>(r);
2011
2012 if( !pStr->isEmpty() )
2013 Append( Complex( *pStr ) );
2014 }
2015 break;
2016 case uno::TypeClass_DOUBLE:
2017 Append( Complex( *o3tl::forceAccess<double>(r), 0.0 ) );
2018 break;
2019 case uno::TypeClass_SEQUENCE:
2020 {
2021 uno::Sequence< uno::Sequence< uno::Any > > aValArr;
2022 if( !(r >>= aValArr) )
2023 throw lang::IllegalArgumentException();
2024
2025 for( const uno::Sequence< uno::Any >& rArr : std::as_const(aValArr) )
2026 Append( rArr );
2027 }
2028 break;
2029 default:
2030 throw lang::IllegalArgumentException();
2031 }
2032 }
2033}
2034
2035ConvertData::ConvertData(const char p[], double fC, ConvertDataClass e, bool bPrefSupport)
2036 : fConst(fC)
2037 , aName(p, strlen(p), RTL_TEXTENCODING_MS_1252)
2038 , eClass(e)
2039 , bPrefixSupport(bPrefSupport)
2040{
2041}
2042
2044{
2045}
2046
2047sal_Int16 ConvertData::GetMatchingLevel( const OUString& rRef ) const
2048{
2049 OUString aStr = rRef;
2050 sal_Int32 nLen = rRef.getLength();
2051 sal_Int32 nIndex = rRef.lastIndexOf( '^' );
2052 if( nIndex > 0 && nIndex == ( nLen - 2 ) )
2053 aStr = aStr.subView( 0, nLen - 2 ) + OUStringChar( aStr[ nLen - 1 ] );
2054 if( aName == aStr )
2055 return 0;
2056 else
2057 {
2058 const sal_Unicode* p = aStr.getStr();
2059
2060 nLen = aStr.getLength();
2061 bool bPref = bPrefixSupport;
2062 bool bOneChar = (bPref && nLen > 1 && (aName == p + 1));
2063 if (bOneChar || (bPref && nLen > 2 && (aName == p + 2) &&
2064 *p == 'd' && *(p+1) == 'a'))
2065 {
2066 sal_Int16 n;
2067 switch( *p )
2068 {
2069 case 'y': n = -24; break; // yocto
2070 case 'z': n = -21; break; // zepto
2071 case 'a': n = -18; break;
2072 case 'f': n = -15; break;
2073 case 'p': n = -12; break;
2074 case 'n': n = -9; break;
2075 case 'u': n = -6; break;
2076 case 'm': n = -3; break;
2077 case 'c': n = -2; break;
2078 case 'd':
2079 {
2080 if ( bOneChar )
2081 n = -1; // deci
2082 else
2083 n = 1; // deca
2084 }
2085 break;
2086 case 'e': n = 1; break;
2087 case 'h': n = 2; break;
2088 case 'k': n = 3; break;
2089 case 'M': n = 6; break;
2090 case 'G': n = 9; break;
2091 case 'T': n = 12; break;
2092 case 'P': n = 15; break;
2093 case 'E': n = 18; break;
2094 case 'Z': n = 21; break; // zetta
2095 case 'Y': n = 24; break; // yotta
2096 default:
2097 n = INV_MATCHLEV;
2098 }
2099
2100// We could weed some nonsense out, ODFF doesn't say so though.
2101#if 0
2102 if (n < 0 && Class() == CDC_Information)
2103 n = INV_MATCHLEV; // milli-bits doesn't make sense
2104#endif
2105
2107 if( n != INV_MATCHLEV )
2108 {
2109 sal_Unicode cLast = p[ aStr.getLength() - 1 ];
2110 if( cLast == '2' )
2111 n *= 2;
2112 else if( cLast == '3' )
2113 n *= 3;
2114 }
2116
2117 return n;
2118 }
2119 else if ( nLen > 2 && ( aName == p + 2 ) && ( Class() == CDC_Information ) )
2120 {
2121 const sal_Unicode* pStr = aStr.getStr();
2122 if ( *(pStr + 1) != 'i')
2123 return INV_MATCHLEV;
2124 sal_Int16 n;
2125 switch( *pStr )
2126 {
2127 case 'k': n = 10; break;
2128 case 'M': n = 20; break;
2129 case 'G': n = 30; break;
2130 case 'T': n = 40; break;
2131 case 'P': n = 50; break;
2132 case 'E': n = 60; break;
2133 case 'Z': n = 70; break;
2134 case 'Y': n = 80; break;
2135 default:
2136 n = INV_MATCHLEV;
2137 }
2138 return n;
2139 }
2140 else
2141 return INV_MATCHLEV;
2142 }
2143}
2144
2145
2147 double f, const ConvertData& r, sal_Int16 nLevFrom, sal_Int16 nLevTo ) const
2148{
2149 if( Class() != r.Class() )
2150 throw lang::IllegalArgumentException();
2151
2152 bool bBinFromLev = ( nLevFrom > 0 && ( nLevFrom % 10 ) == 0 );
2153 bool bBinToLev = ( nLevTo > 0 && ( nLevTo % 10 ) == 0 );
2154
2155 if ( Class() == CDC_Information && ( bBinFromLev || bBinToLev ) )
2156 {
2157 if ( bBinFromLev && bBinToLev )
2158 {
2159 nLevFrom = sal::static_int_cast<sal_Int16>( nLevFrom - nLevTo );
2160 f *= r.fConst / fConst;
2161 if( nLevFrom )
2162 f *= pow( 2.0, nLevFrom );
2163 }
2164 else if ( bBinFromLev )
2165 f *= ( r.fConst / fConst ) * ( pow( 2.0, nLevFrom ) / pow( 10.0, nLevTo ) );
2166 else
2167 f *= ( r.fConst / fConst ) * ( pow( 10.0, nLevFrom ) / pow( 2.0, nLevTo ) );
2168 return f;
2169 }
2170
2171 nLevFrom = sal::static_int_cast<sal_Int16>( nLevFrom - nLevTo ); // effective level
2172
2173 f *= r.fConst / fConst;
2174
2175 if( nLevFrom )
2176 f = ::rtl::math::pow10Exp( f, nLevFrom );
2177
2178 return f;
2179}
2180
2181
2182double ConvertData::ConvertFromBase( double f, sal_Int16 n ) const
2183{
2184 return ::rtl::math::pow10Exp( f * fConst, -n );
2185}
2186
2188{
2189}
2190
2192 double f, const ConvertData& r, sal_Int16 nLevFrom, sal_Int16 nLevTo ) const
2193{
2194 if( Class() != r.Class() )
2195 throw lang::IllegalArgumentException();
2196 return r.ConvertFromBase( ConvertToBase( f, nLevFrom ), nLevTo );
2197}
2198
2199
2200double ConvertDataLinear::ConvertToBase( double f, sal_Int16 n ) const
2201{
2202 if( n )
2203 f = ::rtl::math::pow10Exp( f, n );
2204
2205 f /= fConst;
2206 f -= fOffs;
2207
2208 return f;
2209}
2210
2211
2212double ConvertDataLinear::ConvertFromBase( double f, sal_Int16 n ) const
2213{
2214 f += fOffs;
2215 f *= fConst;
2216
2217 if( n )
2218 f = ::rtl::math::pow10Exp( f, -n );
2219
2220 return f;
2221}
2222
2223
2225{
2226#define NEWD(str,unit,cl) maVector.emplace_back(new ConvertData(str,unit,cl))
2227#define NEWDP(str,unit,cl) maVector.emplace_back(new ConvertData(str,unit,cl,true))
2228#define NEWL(str,unit,offs,cl) maVector.emplace_back(new ConvertDataLinear(str,unit,offs,cl))
2229#define NEWLP(str,unit,offs,cl) maVector.emplace_back(new ConvertDataLinear(str,unit,offs,cl,true))
2230
2231 // *** are extra and not standard Excel Analysis Addin!
2232
2233 // MASS: 1 Gram is...
2234 NEWDP( "g", 1.0000000000000000E00, CDC_Mass ); // Gram
2235 NEWD( "sg", 6.8522050005347800E-05, CDC_Mass ); // Pieces
2236 NEWD( "lbm", 2.2046229146913400E-03, CDC_Mass ); // Pound (commercial weight)
2237 NEWDP( "u", 6.0221370000000000E23, CDC_Mass ); // U (atomic mass)
2238 NEWD( "ozm", 3.5273971800362700E-02, CDC_Mass ); // Ounce (commercial weight)
2239 NEWD( "stone", 1.574730e-04, CDC_Mass ); // *** Stone
2240 NEWD( "ton", 1.102311e-06, CDC_Mass ); // *** Ton
2241 NEWD( "grain", 1.543236E01, CDC_Mass ); // *** Grain
2242 NEWD( "pweight", 7.054792E-01, CDC_Mass ); // *** Pennyweight
2243 NEWD( "hweight", 1.968413E-05, CDC_Mass ); // *** Hundredweight
2244 NEWD( "shweight", 2.204623E-05, CDC_Mass ); // *** Shorthundredweight
2245 NEWD( "brton", 9.842065E-07, CDC_Mass ); // *** Gross Registered Ton
2246 NEWD( "cwt", 2.2046226218487758E-05, CDC_Mass ); // U.S. (short) hundredweight
2247 NEWD( "shweight", 2.2046226218487758E-05, CDC_Mass ); // U.S. (short) hundredweight also
2248 NEWD( "uk_cwt", 1.9684130552221213E-05, CDC_Mass ); // Imperial hundredweight
2249 NEWD( "lcwt", 1.9684130552221213E-05, CDC_Mass ); // Imperial hundredweight also
2250 NEWD( "hweight", 1.9684130552221213E-05, CDC_Mass ); // Imperial hundredweight also
2251 NEWD( "uk_ton", 9.8420652761106063E-07, CDC_Mass ); // Imperial ton
2252 NEWD( "LTON", 9.8420652761106063E-07, CDC_Mass ); // Imperial ton also
2253
2254 // LENGTH: 1 Meter is...
2255 NEWDP( "m", 1.0000000000000000E00, CDC_Length ); // Meter
2256 NEWD( "mi", 6.2137119223733397E-04, CDC_Length ); // Britsh Mile 6,21371192237333969617434184363e-4
2257 NEWD( "Nmi", 5.3995680345572354E-04, CDC_Length ); // Nautical Mile 5,39956803455723542116630669546e-4
2258 NEWD( "in", 3.9370078740157480E01, CDC_Length ); // Inch 39,37007874015748031496062992126
2259 NEWD( "ft", 3.2808398950131234E00, CDC_Length ); // Foot 3,2808398950131233595800524934383
2260 NEWD( "yd", 1.0936132983377078E00, CDC_Length ); // Yard 1,0936132983377077865266841644794
2261 NEWDP( "ang", 1.0000000000000000E10, CDC_Length ); // Angstrom
2262 NEWD( "Pica", 2.8346456692913386E03, CDC_Length ); // Pica Point (1/72 Inch) 2834,6456692913385826771653543307
2263 NEWD( "picapt", 2.8346456692913386E03, CDC_Length ); // Pica Point (1/72 Inch) 2834,6456692913385826771653543307
2264 NEWD( "pica", 2.36220472441E02, CDC_Length ); // pica (1/6 Inch)
2265 NEWD( "ell", 8.748906E-01, CDC_Length ); // *** Ell
2266 NEWDP( "parsec", 3.240779E-17, CDC_Length ); // *** Parsec
2267 NEWDP( "pc", 3.240779E-17, CDC_Length ); // *** Parsec also
2268 NEWDP( "lightyear", 1.0570234557732930E-16, CDC_Length ); // *** Light Year
2269 NEWDP( "ly", 1.0570234557732930E-16, CDC_Length ); // *** Light Year also
2270 NEWD( "survey_mi", 6.2136994949494949E-04, CDC_Length ); // U.S. survey mile
2271
2272 // TIME: 1 Second is...
2273 NEWD( "yr", 3.1688087814028950E-08, CDC_Time ); // Year
2274 NEWD( "day", 1.1574074074074074E-05, CDC_Time ); // Day
2275 NEWD( "d", 1.1574074074074074E-05, CDC_Time ); // Day also
2276 NEWD( "hr", 2.7777777777777778E-04, CDC_Time ); // Hour
2277 NEWD( "mn", 1.6666666666666667E-02, CDC_Time ); // Minute
2278 NEWD( "min", 1.6666666666666667E-02, CDC_Time ); // Minute also
2279 NEWDP( "sec", 1.0000000000000000E00, CDC_Time ); // Second
2280 NEWDP( "s", 1.0000000000000000E00, CDC_Time ); // Second also
2281
2282 // PRESSURE: 1 Pascal is...
2283 NEWDP( "Pa", 1.0000000000000000E00, CDC_Pressure ); // Pascal
2284 NEWDP( "atm", 9.8692329999819300E-06, CDC_Pressure ); // Atmosphere
2285 NEWDP( "at", 9.8692329999819300E-06, CDC_Pressure ); // Atmosphere also
2286 NEWDP( "mmHg", 7.5006170799862700E-03, CDC_Pressure ); // mm Hg (Mercury)
2287 NEWD( "Torr", 7.5006380000000000E-03, CDC_Pressure ); // *** Torr
2288 NEWD( "psi", 1.4503770000000000E-04, CDC_Pressure ); // *** Psi
2289
2290 // FORCE: 1 Newton is...
2291 NEWDP( "N", 1.0000000000000000E00, CDC_Force ); // Newton
2292 NEWDP( "dyn", 1.0000000000000000E05, CDC_Force ); // Dyn
2293 NEWDP( "dy", 1.0000000000000000E05, CDC_Force ); // Dyn also
2294 NEWD( "lbf", 2.24808923655339E-01, CDC_Force ); // Pound-Force
2295 NEWDP( "pond", 1.019716E02, CDC_Force ); // *** Pond
2296
2297 // ENERGY: 1 Joule is...
2298 NEWDP( "J", 1.0000000000000000E00, CDC_Energy ); // Joule
2299 NEWDP( "e", 1.0000000000000000E07, CDC_Energy ); // Erg -> https://en.wikipedia.org/wiki/Erg
2300 NEWDP( "c", 2.3900624947346700E-01, CDC_Energy ); // Thermodynamical Calorie
2301 NEWDP( "cal", 2.3884619064201700E-01, CDC_Energy ); // Calorie
2302 NEWDP( "eV", 6.2414570000000000E18, CDC_Energy ); // Electronvolt
2303 NEWDP( "ev", 6.2414570000000000E18, CDC_Energy ); // Electronvolt also
2304 NEWD( "HPh", 3.7250611111111111E-07, CDC_Energy ); // Horsepower Hours
2305 NEWD( "hh", 3.7250611111111111E-07, CDC_Energy ); // Horsepower Hours also
2306 NEWDP( "Wh", 2.7777777777777778E-04, CDC_Energy ); // Watt Hours
2307 NEWDP( "wh", 2.7777777777777778E-04, CDC_Energy ); // Watt Hours also
2308 NEWD( "flb", 2.37304222192651E01, CDC_Energy ); // Foot Pound
2309 NEWD( "BTU", 9.4781506734901500E-04, CDC_Energy ); // British Thermal Unit
2310 NEWD( "btu", 9.4781506734901500E-04, CDC_Energy ); // British Thermal Unit also
2311
2312 // POWER: 1 Watt is...
2313 NEWDP( "W", 1.0000000000000000E00, CDC_Power ); // Watt
2314 NEWDP( "w", 1.0000000000000000E00, CDC_Power ); // Watt also
2315 NEWD( "HP", 1.341022E-03, CDC_Power ); // Horsepower
2316 NEWD( "h", 1.341022E-03, CDC_Power ); // Horsepower also
2317 NEWD( "PS", 1.359622E-03, CDC_Power ); // *** German Pferdestaerke
2318
2319 // MAGNETISM: 1 Tesla is...
2320 NEWDP( "T", 1.0000000000000000E00, CDC_Magnetism ); // Tesla
2321 NEWDP( "ga", 1.0000000000000000E04, CDC_Magnetism ); // Gauss
2322
2323 // TEMPERATURE: 1 Kelvin is...
2324 NEWL( "C", 1.0000000000000000E00, -2.7315000000000000E02, CDC_Temperature ); // Celsius
2325 NEWL( "cel", 1.0000000000000000E00, -2.7315000000000000E02, CDC_Temperature ); // Celsius also
2326 NEWL( "F", 1.8000000000000000E00, -2.5537222222222222E02, CDC_Temperature ); // Fahrenheit
2327 NEWL( "fah", 1.8000000000000000E00, -2.5537222222222222E02, CDC_Temperature ); // Fahrenheit also
2328 NEWLP( "K", 1.0000000000000000E00, +0.0000000000000000E00, CDC_Temperature ); // Kelvin
2329 NEWLP( "kel", 1.0000000000000000E00, +0.0000000000000000E00, CDC_Temperature ); // Kelvin also
2330 NEWL( "Reau", 8.0000000000000000E-01, -2.7315000000000000E02, CDC_Temperature ); // *** Reaumur
2331 NEWL( "Rank", 1.8000000000000000E00, +0.0000000000000000E00, CDC_Temperature ); // *** Rankine
2332
2333 // VOLUME: 1 Liter is...
2334 NEWD( "tsp", 2.0288413621105798E02, CDC_Volume ); // US teaspoon 1/768 gallon
2335 NEWD( "tbs", 6.7628045403685994E01, CDC_Volume ); // US tablespoon 1/256 gallon
2336 NEWD( "oz", 3.3814022701842997E01, CDC_Volume ); // Ounce Liquid 1/128 gallon
2337 NEWD( "cup", 4.2267528377303746E00, CDC_Volume ); // Cup 1/16 gallon
2338 NEWD( "pt", 2.1133764188651873E00, CDC_Volume ); // US Pint 1/8 gallon
2339 NEWD( "us_pt", 2.1133764188651873E00, CDC_Volume ); // US Pint also
2340 NEWD( "uk_pt", 1.7597539863927023E00, CDC_Volume ); // UK Pint 1/8 imperial gallon
2341 NEWD( "qt", 1.0566882094325937E00, CDC_Volume ); // Quart 1/4 gallon
2342 NEWD( "gal", 2.6417205235814842E-01, CDC_Volume ); // Gallon 1/3.785411784
2343 NEWDP( "l", 1.0000000000000000E00, CDC_Volume ); // Liter
2344 NEWDP( "L", 1.0000000000000000E00, CDC_Volume ); // Liter also
2345 NEWDP( "lt", 1.0000000000000000E00, CDC_Volume ); // Liter also
2346 NEWDP( "m3", 1.0000000000000000E-03, CDC_Volume ); // *** Cubic Meter
2347 NEWD( "mi3", 2.3991275857892772E-13, CDC_Volume ); // *** Cubic Britsh Mile
2348 NEWD( "Nmi3", 1.5742621468581148E-13, CDC_Volume ); // *** Cubic Nautical Mile
2349 NEWD( "in3", 6.1023744094732284E01, CDC_Volume ); // *** Cubic Inch
2350 NEWD( "ft3", 3.5314666721488590E-02, CDC_Volume ); // *** Cubic Foot
2351 NEWD( "yd3", 1.3079506193143922E-03, CDC_Volume ); // *** Cubic Yard
2352 NEWDP( "ang3", 1.0000000000000000E27, CDC_Volume ); // *** Cubic Angstrom
2353 NEWD( "Pica3", 2.2776990435870636E07, CDC_Volume ); // *** Cubic Pica Point (1/72 inch)
2354 NEWD( "picapt3", 2.2776990435870636E07, CDC_Volume ); // *** Cubic Pica Point (1/72 inch)
2355 NEWD( "pica3", 1.31811287245E04, CDC_Volume ); // *** Cubic Pica (1/6 inch)
2356 NEWD( "barrel", 6.2898107704321051E-03, CDC_Volume ); // *** Barrel (=42gal)
2357 NEWD( "bushel", 2.837759E-02, CDC_Volume ); // *** Bushel
2358 NEWD( "regton", 3.531467E-04, CDC_Volume ); // *** Register ton
2359 NEWD( "GRT", 3.531467E-04, CDC_Volume ); // *** Register ton also
2360 NEWD( "Schooner", 2.3529411764705882E00, CDC_Volume ); // *** austr. Schooner
2361 NEWD( "Middy", 3.5087719298245614E00, CDC_Volume ); // *** austr. Middy
2362 NEWD( "Glass", 5.0000000000000000E00, CDC_Volume ); // *** austr. Glass
2363 NEWD( "Sixpack", 0.5, CDC_Volume ); // ***
2364 NEWD( "Humpen", 2.0, CDC_Volume ); // ***
2365 NEWD( "ly3", 1.1810108125623799E-51, CDC_Volume ); // *** Cubic light-year
2366 NEWD( "MTON", 1.4125866688595436E00, CDC_Volume ); // *** Measurement ton
2367 NEWD( "tspm", 2.0000000000000000E02, CDC_Volume ); // *** Modern teaspoon
2368 NEWD( "uk_gal", 2.1996924829908779E-01, CDC_Volume ); // U.K. / Imperial gallon 1/4.54609
2369 NEWD( "uk_qt", 8.7987699319635115E-01, CDC_Volume ); // U.K. / Imperial quart 1/4 imperial gallon
2370
2371 // 1 Square Meter is...
2372 NEWDP( "m2", 1.0000000000000000E00, CDC_Area ); // *** Square Meter
2373 NEWD( "mi2", 3.8610215854244585E-07, CDC_Area ); // *** Square Britsh Mile
2374 NEWD( "Nmi2", 2.9155334959812286E-07, CDC_Area ); // *** Square Nautical Mile
2375 NEWD( "in2", 1.5500031000062000E03, CDC_Area ); // *** Square Inch
2376 NEWD( "ft2", 1.0763910416709722E01, CDC_Area ); // *** Square Foot
2377 NEWD( "yd2", 1.1959900463010803E00, CDC_Area ); // *** Square Yard
2378 NEWDP( "ang2", 1.0000000000000000E20, CDC_Area ); // *** Square Angstrom
2379 NEWD( "Pica2", 8.0352160704321409E06, CDC_Area ); // *** Square Pica Point (1/72 inch)
2380 NEWD( "picapt2", 8.0352160704321409E06, CDC_Area ); // *** Square Pica Point (1/72 inch)
2381 NEWD( "pica2", 5.58001116002232E04, CDC_Area ); // *** Square Pica (1/6 inch)
2382 NEWD( "Morgen", 4.0000000000000000E-04, CDC_Area ); // *** Morgen
2383 NEWDP( "ar", 1.000000E-02, CDC_Area ); // *** Ar
2384 NEWD( "acre", 2.471053815E-04, CDC_Area ); // *** Acre
2385 NEWD( "uk_acre", 2.4710538146716534E-04, CDC_Area ); // *** International acre
2386 NEWD( "us_acre", 2.4710439304662790E-04, CDC_Area ); // *** U.S. survey/statute acre
2387 NEWD( "ly2", 1.1172985860549147E-32, CDC_Area ); // *** Square Light-year
2388 NEWD( "ha", 1.000000E-04, CDC_Area ); // *** Hectare
2389
2390 // SPEED: 1 Meter per Second is...
2391 NEWDP( "m/s", 1.0000000000000000E00, CDC_Speed ); // *** Meters per Second
2392 NEWDP( "m/sec", 1.0000000000000000E00, CDC_Speed ); // *** Meters per Second also
2393 NEWDP( "m/h", 3.6000000000000000E03, CDC_Speed ); // *** Meters per Hour
2394 NEWDP( "m/hr", 3.6000000000000000E03, CDC_Speed ); // *** Meters per Hour also
2395 NEWD( "mph", 2.2369362920544023E00, CDC_Speed ); // *** Britsh Miles per Hour
2396 NEWD( "kn", 1.9438444924406048E00, CDC_Speed ); // *** Knot = Nautical Miles per Hour
2397 NEWD( "admkn", 1.9438446603753486E00, CDC_Speed ); // *** Admiralty Knot
2398 NEWD( "ludicrous speed", 2.0494886343432328E-14, CDC_Speed ); // ***
2399 NEWD( "ridiculous speed", 4.0156958471424288E-06, CDC_Speed); // ***
2400
2401 // INFORMATION: 1 Bit is...
2402 NEWDP( "bit", 1.00E00, CDC_Information); // *** Bit
2403 NEWDP( "byte", 1.25E-01, CDC_Information); // *** Byte
2404}
2405
2406
2408{
2409}
2410
2411
2412double ConvertDataList::Convert( double fVal, const OUString& rFrom, const OUString& rTo )
2413{
2414 ConvertData* pFrom = nullptr;
2415 ConvertData* pTo = nullptr;
2416 bool bSearchFrom = true;
2417 bool bSearchTo = true;
2418 sal_Int16 nLevelFrom = 0;
2419 sal_Int16 nLevelTo = 0;
2420
2421 for( const auto& rItem : maVector )
2422 {
2423 ConvertData* p = rItem.get();
2424 if( bSearchFrom )
2425 {
2426 sal_Int16 n = p->GetMatchingLevel( rFrom );
2427 if( n != INV_MATCHLEV )
2428 {
2429 if( n )
2430 { // only first match for partial equality rulz a little bit more
2431 pFrom = p;
2432 nLevelFrom = n;
2433 }
2434 else
2435 { // ... but exact match rulz most
2436 pFrom = p;
2437 bSearchFrom = false;
2438 nLevelFrom = n;
2439 }
2440 }
2441 }
2442
2443 if( bSearchTo )
2444 {
2445 sal_Int16 n = p->GetMatchingLevel( rTo );
2446 if( n != INV_MATCHLEV )
2447 {
2448 if( n )
2449 { // only first match for partial equality rulz a little bit more
2450 pTo = p;
2451 nLevelTo = n;
2452 }
2453 else
2454 { // ... but exact match rulz most
2455 pTo = p;
2456 bSearchTo = false;
2457 nLevelTo = n;
2458 }
2459 }
2460 }
2461
2462 if( !bSearchFrom && !bSearchTo )
2463 break;
2464 }
2465
2466 if( !pFrom || !pTo )
2467 throw lang::IllegalArgumentException();
2468
2469 return pFrom->Convert( fVal, *pTo, nLevelFrom, nLevelTo );
2470}
2471
2472
2474 nOrigDay( 1 ),
2475 nDay( 1 ),
2476 nMonth( 1 ),
2477 nYear( 1900 ),
2478 bLastDayMode( true ),
2479 bLastDay( false ),
2480 b30Days( false ),
2481 bUSMode( false )
2482{
2483}
2484
2485ScaDate::ScaDate( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nBase )
2486{
2487 DaysToDate( nNullDate + nDate, nOrigDay, nMonth, nYear );
2488 bLastDayMode = (nBase != 5);
2490 b30Days = (nBase == 0) || (nBase == 4);
2491 bUSMode = (nBase == 0);
2492 setDay();
2493}
2494
2495ScaDate::ScaDate( const ScaDate& rCopy ) :
2496 nOrigDay( rCopy.nOrigDay ),
2497 nDay( rCopy.nDay ),
2498 nMonth( rCopy.nMonth ),
2499 nYear( rCopy.nYear ),
2500 bLastDayMode( rCopy.bLastDayMode ),
2501 bLastDay( rCopy.bLastDay ),
2502 b30Days( rCopy.b30Days ),
2503 bUSMode( rCopy.bUSMode )
2504{
2505}
2506
2508{
2509 if( this != &rCopy )
2510 {
2511 nOrigDay = rCopy.nOrigDay;
2512 nDay = rCopy.nDay;
2513 nMonth = rCopy.nMonth;
2514 nYear = rCopy.nYear;
2515 bLastDayMode = rCopy.bLastDayMode;
2516 bLastDay = rCopy.bLastDay;
2517 b30Days = rCopy.b30Days;
2518 bUSMode = rCopy.bUSMode;
2519 }
2520 return *this;
2521}
2522
2524{
2525 if( b30Days )
2526 {
2527 // 30-days-mode: set nDay to 30 if original was last day in month
2528 nDay = std::min( nOrigDay, static_cast< sal_uInt16 >( 30 ) );
2529 if( bLastDay || (nDay >= ::DaysInMonth( nMonth, nYear )) )
2530 nDay = 30;
2531 }
2532 else
2533 {
2534 // set nDay to last day in this month if original was last day
2535 sal_uInt16 nLastDay = ::DaysInMonth( nMonth, nYear );
2536 nDay = bLastDay ? nLastDay : std::min( nOrigDay, nLastDay );
2537 }
2538}
2539
2540sal_Int32 ScaDate::getDaysInMonthRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const
2541{
2542 if( nFrom > nTo )
2543 return 0;
2544
2545 sal_Int32 nRet = 0;
2546 if( b30Days )
2547 nRet = (nTo - nFrom + 1) * 30;
2548 else
2549 {
2550 for( sal_uInt16 nMonthIx = nFrom; nMonthIx <= nTo; ++nMonthIx )
2551 nRet += getDaysInMonth( nMonthIx );
2552 }
2553 return nRet;
2554}
2555
2556sal_Int32 ScaDate::getDaysInYearRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const
2557{
2558 if( nFrom > nTo )
2559 return 0;
2560
2561 return b30Days ? ((nTo - nFrom + 1) * 360) : ::GetDaysInYears( nFrom, nTo );
2562}
2563
2564void ScaDate::doAddYears( sal_Int32 nYearCount )
2565{
2566 sal_Int32 nNewYear = nYearCount + nYear;
2567 if( (nNewYear < 0) || (nNewYear > 0x7FFF) )
2568 throw lang::IllegalArgumentException();
2569 nYear = static_cast< sal_uInt16 >( nNewYear );
2570}
2571
2572void ScaDate::addMonths( sal_Int32 nMonthCount )
2573{
2574 sal_Int32 nNewMonth = nMonthCount + nMonth;
2575 if( nNewMonth > 12 )
2576 {
2577 --nNewMonth;
2578 doAddYears( nNewMonth / 12 );
2579 nMonth = static_cast< sal_uInt16 >( nNewMonth % 12 ) + 1;
2580 }
2581 else if( nNewMonth < 1 )
2582 {
2583 doAddYears( nNewMonth / 12 - 1 );
2584 nMonth = static_cast< sal_uInt16 >( nNewMonth % 12 + 12 );
2585 }
2586 else
2587 nMonth = static_cast< sal_uInt16 >( nNewMonth );
2588 setDay();
2589}
2590
2591sal_Int32 ScaDate::getDate( sal_Int32 nNullDate ) const
2592{
2593 sal_uInt16 nLastDay = ::DaysInMonth( nMonth, nYear );
2594 sal_uInt16 nRealDay = (bLastDayMode && bLastDay) ? nLastDay : std::min( nLastDay, nOrigDay );
2595 return ::DateToDays( nRealDay, nMonth, nYear ) - nNullDate;
2596}
2597
2598sal_Int32 ScaDate::getDiff( const ScaDate& rFrom, const ScaDate& rTo )
2599{
2600 if( rFrom > rTo )
2601 return getDiff( rTo, rFrom );
2602
2603 sal_Int32 nDiff = 0;
2604 ScaDate aFrom( rFrom );
2605 ScaDate aTo( rTo );
2606
2607 if( rTo.b30Days )
2608 {
2609 // corrections for base 0 (US NASD)
2610 if( rTo.bUSMode )
2611 {
2612 if( ((rFrom.nMonth == 2) || (rFrom.nDay < 30)) && (aTo.nOrigDay == 31) )
2613 aTo.nDay = 31;
2614 else if( (aTo.nMonth == 2) && aTo.bLastDay )
2615 aTo.nDay = ::DaysInMonth( 2, aTo.nYear );
2616 }
2617 // corrections for base 4 (Europe)
2618 else
2619 {
2620 if( (aFrom.nMonth == 2) && (aFrom.nDay == 30) )
2621 aFrom.nDay = ::DaysInMonth( 2, aFrom.nYear );
2622 if( (aTo.nMonth == 2) && (aTo.nDay == 30) )
2623 aTo.nDay = ::DaysInMonth( 2, aTo.nYear );
2624 }
2625 }
2626
2627 if( (aFrom.nYear < aTo.nYear) || ((aFrom.nYear == aTo.nYear) && (aFrom.nMonth < aTo.nMonth)) )
2628 {
2629 // move aFrom to 1st day of next month
2630 nDiff = aFrom.getDaysInMonth() - aFrom.nDay + 1;
2631 aFrom.nOrigDay = aFrom.nDay = 1;
2632 aFrom.bLastDay = false;
2633 aFrom.addMonths( 1 );
2634
2635 if( aFrom.nYear < aTo.nYear )
2636 {
2637 // move aFrom to 1st day of next year
2638 nDiff += aFrom.getDaysInMonthRange( aFrom.nMonth, 12 );
2639 aFrom.addMonths( 13 - aFrom.nMonth );
2640
2641 // move aFrom to 1st day of this year
2642 nDiff += aFrom.getDaysInYearRange( aFrom.nYear, aTo.nYear - 1 );
2643 aFrom.addYears( aTo.nYear - aFrom.nYear );
2644 }
2645
2646 // move aFrom to 1st day of this month
2647 nDiff += aFrom.getDaysInMonthRange( aFrom.nMonth, aTo.nMonth - 1 );
2648 aFrom.addMonths( aTo.nMonth - aFrom.nMonth );
2649 }
2650 // finally add remaining days in this month
2651 nDiff += aTo.nDay - aFrom.nDay;
2652 return std::max<sal_Int32>(nDiff, 0);
2653}
2654
2655bool ScaDate::operator<( const ScaDate& rCmp ) const
2656{
2657 if( nYear != rCmp.nYear )
2658 return nYear < rCmp.nYear;
2659 if( nMonth != rCmp.nMonth )
2660 return nMonth < rCmp.nMonth;
2661 if( nDay != rCmp.nDay )
2662 return nDay < rCmp.nDay;
2663 if( bLastDay || rCmp.bLastDay )
2664 return !bLastDay && rCmp.bLastDay;
2665 return nOrigDay < rCmp.nOrigDay;
2666}
2667
2668
2669ScaAnyConverter::ScaAnyConverter( const uno::Reference< uno::XComponentContext >& xContext )
2670 : nDefaultFormat(0)
2671 , bHasValidFormat(false)
2672{
2673 xFormatter = util::NumberFormatter::create(xContext);
2674}
2675
2677{
2678}
2679
2680void ScaAnyConverter::init( const uno::Reference< beans::XPropertySet >& xPropSet )
2681{
2682 // try to get default number format
2683 bHasValidFormat = false;
2684 if( !xFormatter.is() )
2685 return;
2686
2687 // get XFormatsSupplier from outer XPropertySet
2688 uno::Reference< util::XNumberFormatsSupplier > xFormatsSupp( xPropSet, uno::UNO_QUERY );
2689 if( !xFormatsSupp.is() )
2690 return;
2691
2692 // get XNumberFormatTypes from XNumberFormatsSupplier to get standard index
2693 uno::Reference< util::XNumberFormats > xFormats( xFormatsSupp->getNumberFormats() );
2694 uno::Reference< util::XNumberFormatTypes > xFormatTypes( xFormats, uno::UNO_QUERY );
2695 if( xFormatTypes.is() )
2696 {
2697 lang::Locale eLocale;
2698 nDefaultFormat = xFormatTypes->getStandardIndex( eLocale );
2699 xFormatter->attachNumberFormatsSupplier( xFormatsSupp );
2700 bHasValidFormat = true;
2701 }
2702}
2703
2704double ScaAnyConverter::convertToDouble( const OUString& rString ) const
2705{
2706 double fValue = 0.0;
2707 if( bHasValidFormat )
2708 {
2709 try
2710 {
2711 fValue = xFormatter->convertStringToNumber( nDefaultFormat, rString );
2712 }
2713 catch( uno::Exception& )
2714 {
2715 throw lang::IllegalArgumentException();
2716 }
2717 }
2718 else
2719 {
2720 rtl_math_ConversionStatus eStatus;
2721 sal_Int32 nEnd;
2722 fValue = ::rtl::math::stringToDouble( rString, '.', ',', &eStatus, &nEnd );
2723 if( (eStatus != rtl_math_ConversionStatus_Ok) || (nEnd < rString.getLength()) )
2724 throw lang::IllegalArgumentException();
2725 }
2726 return fValue;
2727}
2728
2730 double& rfResult,
2731 const uno::Any& rAny ) const
2732{
2733 rfResult = 0.0;
2734 bool bContainsVal = true;
2735 switch( rAny.getValueTypeClass() )
2736 {
2737 case uno::TypeClass_VOID:
2738 bContainsVal = false;
2739 break;
2740 case uno::TypeClass_DOUBLE:
2741 rAny >>= rfResult;
2742 break;
2743 case uno::TypeClass_STRING:
2744 {
2745 auto pString = o3tl::forceAccess< OUString >( rAny );
2746 if( !pString->isEmpty() )
2747 rfResult = convertToDouble( *pString );
2748 else
2749 bContainsVal = false;
2750 }
2751 break;
2752 default:
2753 throw lang::IllegalArgumentException();
2754 }
2755 return bContainsVal;
2756}
2757
2759 double& rfResult,
2760 const uno::Reference< beans::XPropertySet >& xPropSet,
2761 const uno::Any& rAny )
2762{
2763 init( xPropSet );
2764 return getDouble( rfResult, rAny );
2765}
2766
2768 const uno::Reference< beans::XPropertySet >& xPropSet,
2769 const uno::Any& rAny,
2770 double fDefault )
2771{
2772 double fResult;
2773 if( !getDouble( fResult, xPropSet, rAny ) )
2774 fResult = fDefault;
2775 return fResult;
2776}
2777
2779 sal_Int32& rnResult,
2780 const uno::Reference< beans::XPropertySet >& xPropSet,
2781 const uno::Any& rAny )
2782{
2783 double fResult;
2784 bool bContainsVal = getDouble( fResult, xPropSet, rAny );
2785 if( (fResult <= -2147483649.0) || (fResult >= 2147483648.0) )
2786 throw lang::IllegalArgumentException();
2787
2788 rnResult = static_cast< sal_Int32 >( fResult );
2789 return bContainsVal;
2790}
2791
2793 const uno::Reference< beans::XPropertySet >& xPropSet,
2794 const uno::Any& rAny,
2795 sal_Int32 nDefault )
2796{
2797 sal_Int32 nResult;
2798 if( !getInt32( nResult, xPropSet, rAny ) )
2799 nResult = nDefault;
2800 return nResult;
2801}
2802
2803}
2804
2805/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
bool isFreqInvalid(sal_Int32 nFreq)
double finiteOrThrow(double d)
#define FUNCDATAS(FUNCNAME, DBL, OPT, NUMOFPAR, CAT, SUFFIX)
#define FUNCDATA(FUNCNAME, DBL, OPT, NUMOFPAR, CAT)
#define INTPAR
#define STDPAR
#define DOUBLE
#define NEWD(str, unit, cl)
#define NEWL(str, unit, offs, cl)
#define UNIQUE
#define NEWDP(str, unit, cl)
#define NEWLP(str, unit, offs, cl)
const FuncDataBase pFuncDatas[]
#define INV_MATCHLEV
void Append(Complex &&pNew)
OUString GetString() const
void Div(const Complex &rDivisor)
void Power(double fPower)
static bool ParseString(const OUString &rComplexAsString, Complex &rReturn)
static bool IsImagUnit(sal_Unicode c)
void Mult(double fFact)
Complex(double fReal, double fImag=0.0, sal_Unicode cC='\0')
double ConvertToBase(double fVal, sal_Int16 nMatchLevel) const
virtual double ConvertFromBase(double fVal, sal_Int16 nMatchLevel) const override
virtual double Convert(double fVal, const ConvertData &rTo, sal_Int16 nMatchLevelFrom, sal_Int16 nMatchLevelTo) const override
double Convert(double fVal, const OUString &rFrom, const OUString &rTo)
std::vector< std::unique_ptr< ConvertData > > maVector
virtual double Convert(double fVal, const ConvertData &rTo, sal_Int16 nMatchLevelFrom, sal_Int16 nMatchLevelTo) const
ConvertData(const char pUnitName[], double fConvertConstant, ConvertDataClass eClass, bool bPrefSupport=false)
ConvertDataClass Class() const
virtual double ConvertFromBase(double fVal, sal_Int16 nMatchLevel) const
sal_Int16 GetMatchingLevel(const OUString &rRef) const
std::vector< OUString > aCompList
sal_uInt16 GetStrIndex(sal_uInt16 nParamNum) const
FuncData(const FuncDataBase &rBaseData)
Helper class for Any->double conversion, using current language settings.
double convertToDouble(const OUString &rString) const
Converts a string to double using the number formatter.
ScaAnyConverter(const css::uno::Reference< css::uno::XComponentContext > &xContext)
bool getDouble(double &rfResult, const css::uno::Any &rAny) const
Converts an Any to double (without initialization).
css::uno::Reference< css::util::XNumberFormatter2 > xFormatter
void init(const css::uno::Reference< css::beans::XPropertySet > &xPropSet)
Initializing with current language settings.
bool getInt32(sal_Int32 &rnResult, const css::uno::Reference< css::beans::XPropertySet > &xPropSet, const css::uno::Any &rAny)
Converts an Any to sal_Int32 (with initialization).
Helper class for date calculation for various financial functions.
sal_uInt16 nDay
is the day of the original date.
sal_Int32 getDate(sal_Int32 nNullDate) const
void doAddYears(sal_Int32 nYearCount)
Adds/subtracts the given count of years, does not adjust day.
bool bLastDayMode
is the current year.
sal_uInt16 getDaysInMonth() const
sal_Int32 getDaysInYearRange(sal_uInt16 nFrom, sal_uInt16 nTo) const
@ return count of days in the given year range
void addMonths(sal_Int32 nMonthCount)
adds/subtracts the given count of months, adjusts day
void setYear(sal_uInt16 nNewYear)
sets the given year, adjusts day
void setDay()
is true, if the US method of 30-day-calculations is used.
void addYears(sal_Int32 nYearCount)
adds/subtracts the given count of years, adjusts day
bool bLastDay
if true, recalculate nDay after every calculation.
sal_uInt16 nYear
is the current month (one-based).
sal_uInt16 getYear() const
sal_uInt16 getMonth() const
ScaDate & operator=(const ScaDate &rCopy)
sal_Int32 getDaysInMonthRange(sal_uInt16 nFrom, sal_uInt16 nTo) const
@ return count of days in the given month range
static sal_Int32 getDiff(const ScaDate &rFrom, const ScaDate &rTo)
bool b30Days
is true, if original date was the last day in month.
bool bUSMode
is true, if every month has 30 days in calculations.
sal_uInt16 nMonth
is the calculated day depending on the current month/year.
bool operator<(const ScaDate &rCmp) const
virtual bool CheckInsert(double fValue) const override
virtual bool CheckInsert(double fValue) const override
virtual bool CheckInsert(double fValue) const
sal_Int32 Get(sal_uInt32 n) const
void InsertHolidayList(const ScaAnyConverter &rAnyConv, const css::uno::Any &rHolAny, sal_Int32 nNullDate, bool bInsertOnWeekend)
float y
float x
float z
sal_Int32 nIndex
OUString aName
void * p
sal_Int64 n
Environment aTo
Environment aFrom
sal_Int32 nRef
aStr
int i
std::enable_if<!(detail::IsDerivedReference< T >::value||detail::IsUnoSequenceType< T >::value||std::is_base_of< css::uno::XInterface, T >::value), typenamedetail::Optional< T >::type >::type tryAccess(css::uno::Any const &any)
log
static bool IsNum(sal_Unicode c)
double GetYearDiff(sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode)
static void lcl_GetCoupncd(ScaDate &rDate, const ScaDate &rSettle, const ScaDate &rMat, sal_Int32 nFreq)
double GetOddfprice(sal_Int32, sal_Int32, sal_Int32, sal_Int32, sal_Int32, double, double, double, sal_Int32, sal_Int32)
double getYield_(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup, double fPrice, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase)
double BinomialCoefficient(double n, double k)
static void lcl_GetCouppcd(ScaDate &rDate, const ScaDate &rSettle, const ScaDate &rMat, sal_Int32 nFreq)
double GetOddfyield(sal_Int32, sal_Int32, sal_Int32, sal_Int32, sal_Int32, double, double, double, sal_Int32, sal_Int32)
void InitFuncDataList(FuncDataList &rList)
sal_Int32 GetNullDate(const uno::Reference< beans::XPropertySet > &xOpt)
Get the null date used by the spreadsheet document.
double GetYieldmat(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue, double fRate, double fPrice, sal_Int32 nBase)
static sal_uInt16 GetVal(sal_Unicode c)
double Erfc(double x)
double GetPmt(double fRate, double fNper, double fPv, double fFv, sal_Int32 nPayType)
double GetCoupdaysnc(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase)
double GetCouppcd(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase)
sal_Int32 GetDaysInYear(sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nMode)
double GetAmordegrc(sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer, double fRestVal, double fPer, double fRate, sal_Int32 nBase)
static char GetMaxChar(sal_uInt16 nBase)
static bool IsExpStart(sal_Unicode c)
double GetCoupnum(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase)
double GetGcd(double f1, double f2)
OUString GetString(double f, bool bLeadingSign, sal_uInt16 nMaxDig)
OUString ConvertFromDec(double fNum, double fMin, double fMax, sal_uInt16 nBase, sal_Int32 nPlaces, sal_Int32 nMaxPlaces, bool bUsePlaces)
bool ParseDouble(const sal_Unicode *&rp, double &rRet)
sal_Int32 GetDiffDate(sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode, sal_Int32 *pOptDaysIn1stYear)
double getPrice_(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fRate, double fYield, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase)
double GetCoupdays(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase)
double GetOddlyield(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastCoup, double fRate, double fPrice, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase)
double ConvertToDec(const OUString &aStr, sal_uInt16 nBase, sal_uInt16 nCharLim)
sal_Int32 GetDiffDate360(sal_uInt16 nDay1, sal_uInt16 nMonth1, sal_uInt16 nYear1, bool bLeapYear1, sal_uInt16 nDay2, sal_uInt16 nMonth2, sal_uInt16 nYear2, bool bUSAMethod)
static bool IsComma(sal_Unicode c)
sal_Int32 DateToDays(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear)
Convert a date to a count of days starting from 01/01/0001.
static bool IsImagUnit(sal_Unicode c)
void DaysToDate(sal_Int32 nDays, sal_uInt16 &rDay, sal_uInt16 &rMonth, sal_uInt16 &rYear)
Convert a count of days starting from 01/01/0001 to a date.
double GetYearFrac(sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode)
Function GetYearFrac implements YEARFRAC as defined in: Open Document Format for Office Applications ...
sal_uInt16 DaysInMonth(sal_uInt16 nMonth, sal_uInt16 nYear)
sal_Int32 GetDaysInYears(sal_uInt16 nYear1, sal_uInt16 nYear2)
double GetCoupdaybs(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase)
double GetOddlprice(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastCoup, double fRate, double fYield, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase)
double GetFv(double fRate, double fNper, double fPmt, double fPv, sal_Int32 nPayType)
bool IsLeapYear(sal_uInt16 nYear)
double GetAmorlinc(sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer, double fRestVal, double fPer, double fRate, sal_Int32 nBase)
double GetCoupncd(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase)
double GetDuration(sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup, double fYield, sal_Int32 nFreq, sal_Int32 nBase)
sal_Int16 GetDayOfWeek(sal_Int32 nDate)
double Erf(double x)
std::vector< FuncData > FuncDataList
State
const char phi[]
sal_uInt16 sal_Unicode