xref: /trunk/main/scaddins/source/analysis/analysishelper.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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