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