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