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