xref: /trunk/main/scaddins/source/analysis/analysishelper.cxx (revision cea84f56765a2ac06f0f5a2718f45f6430edc781)
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     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( "SI_at", 1.0197162129779282E-05, CDC_Pressure ); // Technical atmosphere (ODF 1.4)
2456     NEWDP( "mmHg",  7.5006170799862700E-03, CDC_Pressure ); // mm Hg (Mercury)
2457     NEWD( "Torr",   7.5006380000000000E-03, CDC_Pressure ); // *** Torr
2458     NEWD( "psi",    1.4503770000000000E-04, CDC_Pressure ); // *** Psi
2459 
2460     // FORCE: 1 Newton is...
2461     NEWDP( "N",     1.0000000000000000E00,  CDC_Force ); // Newton
2462     NEWDP( "dyn",   1.0000000000000000E05,  CDC_Force ); // Dyn
2463     NEWDP( "dy",    1.0000000000000000E05,  CDC_Force ); // Dyn also
2464     NEWD( "lbf",    2.24808923655339E-01,   CDC_Force ); // Pound-Force
2465     NEWDP( "pond",  1.019716E02,            CDC_Force ); // *** Pond
2466 
2467     // ENERGY: 1 Joule is...
2468     NEWDP( "J",     1.0000000000000000E00,  CDC_Energy ); // Joule
2469     NEWDP( "e",     1.0000000000000000E07,  CDC_Energy ); // Erg  -> http://www.chemie.fu-berlin.de/chemistry/general/si.html
2470 //  NEWD( "e",      9.99999519343231E06,    CDC_Energy ); // Erg
2471     NEWDP( "c",     2.3900624947346700E-01, CDC_Energy ); // Thermodynamical Calorie
2472     NEWDP( "cal",   2.3884619064201700E-01, CDC_Energy ); // Calorie
2473     NEWDP( "eV",    6.2414570000000000E18,  CDC_Energy ); // Electronvolt
2474     NEWDP( "ev",    6.2414570000000000E18,  CDC_Energy ); // Electronvolt also
2475     NEWD( "HPh",    3.7250611111111111E-07, CDC_Energy ); // Horsepower Hours
2476     NEWD( "hh",     3.7250611111111111E-07, CDC_Energy ); // Horsepower Hours also
2477 //  NEWD( "HPh",    3.72506430801000E-07,   CDC_Energy ); // Horsepower Hours
2478     NEWDP( "Wh",    2.7777777777777778E-04, CDC_Energy ); // Watt Hours
2479     NEWDP( "wh",    2.7777777777777778E-04, CDC_Energy ); // Watt Hours also
2480     NEWD( "flb",    2.37304222192651E01,    CDC_Energy ); // Foot Pound
2481     NEWD( "BTU",    9.4781506734901500E-04, CDC_Energy ); // British Thermal Unit
2482     NEWD( "btu",    9.4781506734901500E-04, CDC_Energy ); // British Thermal Unit also
2483 
2484     // POWER: 1 Watt is...
2485     NEWDP( "W",     1.0000000000000000E00,  CDC_Power ); // Watt
2486     NEWDP( "w",     1.0000000000000000E00,  CDC_Power ); // Watt also
2487     NEWD( "HP",     1.341022E-03,           CDC_Power ); // Horsepower
2488     NEWD( "h",      1.341022E-03,           CDC_Power ); // Horsepower also
2489     NEWD( "PS",     1.359622E-03,           CDC_Power ); // *** German Pferdestaerke
2490 //  NEWD( "HP",     1.4102006031908E-03,    CDC_Power ); // Excel seems to be a little bit wrong... either this doesn't fit to J -> HPh
2491 
2492     // MAGNETISM: 1 Tesla is...
2493     NEWDP( "T",     1.0000000000000000E00,  CDC_Magnetism ); // Tesla
2494     NEWDP( "ga",    1.0000000000000000E04,  CDC_Magnetism ); // Gauss
2495 
2496     // TEMPERATURE: 1 Kelvin is...
2497     NEWL( "C",      1.0000000000000000E00,  -2.7315000000000000E02, CDC_Temperature ); // Celsius
2498     NEWL( "cel",    1.0000000000000000E00,  -2.7315000000000000E02, CDC_Temperature ); // Celsius also
2499     NEWL( "F",      1.8000000000000000E00,  -2.5537222222222222E02, CDC_Temperature ); // Fahrenheit
2500     NEWL( "fah",    1.8000000000000000E00,  -2.5537222222222222E02, CDC_Temperature ); // Fahrenheit also
2501     NEWLP( "K",     1.0000000000000000E00,  +0.0000000000000000E00, CDC_Temperature ); // Kelvin
2502     NEWLP( "kel",   1.0000000000000000E00,  +0.0000000000000000E00, CDC_Temperature ); // Kelvin also
2503     NEWL( "Reau",   8.0000000000000000E-01, -2.7315000000000000E02, CDC_Temperature ); // *** Reaumur
2504     NEWL( "Rank",   1.8000000000000000E00,  +0.0000000000000000E00, CDC_Temperature ); // *** Rankine
2505 
2506     // VOLUME: 1 Liter is...
2507     NEWD( "tsp",        2.0284000000000000E02,  CDC_Volume ); // Teaspoon
2508     NEWD( "tbs",        6.7613333333333333E01,  CDC_Volume ); // Tablespoon
2509     NEWD( "oz",         3.3806666666666667E01,  CDC_Volume ); // Ounce Liquid
2510     NEWD( "cup",        4.2258333333333333E00,  CDC_Volume ); // Cup
2511     NEWD( "pt",         2.1129166666666667E00,  CDC_Volume ); // US Pint
2512     NEWD( "us_pt",      2.1129166666666667E00,  CDC_Volume ); // US Pint also
2513     NEWD( "uk_pt",      1.75975569552166E00,    CDC_Volume ); // UK Pint
2514     NEWD( "qt",         1.0564583333333333E00,  CDC_Volume ); // Quart
2515     NEWD( "gal",        2.6411458333333333E-01, CDC_Volume ); // Gallone
2516     NEWDP( "l",         1.0000000000000000E00,  CDC_Volume ); // Liter
2517     NEWDP( "L",         1.0000000000000000E00,  CDC_Volume ); // Liter also
2518     NEWDP( "lt",        1.0000000000000000E00,  CDC_Volume ); // Liter also
2519     NEWDP( "m3",        1.0000000000000000E-03, CDC_Volume ); // *** Cubic Meter
2520     NEWD( "mi3",        2.3991275857892772E-13, CDC_Volume ); // *** Cubic Britsh Mile
2521     NEWD( "Nmi3",       1.5742621468581148E-13, CDC_Volume ); // *** Cubic Nautical Mile
2522     NEWD( "in3",        6.1023744094732284E01,  CDC_Volume ); // *** Cubic Inch
2523     NEWD( "ft3",        3.5314666721488590E-02, CDC_Volume ); // *** Cubic Foot
2524     NEWD( "yd3",        1.3079506193143922E-03, CDC_Volume ); // *** Cubic Yard
2525     NEWDP( "ang3",      1.0000000000000000E27,  CDC_Volume ); // *** Cubic Angstroem
2526     NEWD( "Pica3",      2.2776990435870636E07,  CDC_Volume ); // *** Cubic Pica
2527     NEWD( "barrel",     6.289811E-03,           CDC_Volume ); // *** Barrel (=42gal?)
2528     NEWD( "bushel",     2.837759E-02,           CDC_Volume ); // *** Bushel
2529     NEWD( "regton",     3.531467E-04,           CDC_Volume ); // *** Register ton
2530     NEWD( "GRT",        3.531467E-04,           CDC_Volume ); // *** Register ton also
2531     NEWD( "Schooner",   2.3529411764705882E00,  CDC_Volume ); // *** austr. Schooner
2532     NEWD( "Middy",      3.5087719298245614E00,  CDC_Volume ); // *** austr. Middy
2533     NEWD( "Glass",      5.0000000000000000E00,  CDC_Volume ); // *** austr. Glass
2534     NEWD( "Sixpack",    0.5,                    CDC_Volume ); // ***
2535     NEWD( "Humpen",     2.0,                    CDC_Volume ); // ***
2536     NEWD( "ly3",        1.1810108125623799E-51, CDC_Volume ); // *** Cubic light-year
2537     NEWD( "MTON",       1.4125866688595436E00,  CDC_Volume ); // *** Measurement ton
2538     NEWD( "tspm",       5.0000000000000000E02,  CDC_Volume ); // *** Modern teaspoon
2539     NEWD( "uk_gal",     2.199694619402070E-01,  CDC_Volume ); // U.K. / Imperial gallon
2540     NEWD( "uk_qt",      8.798778477608300E-01,  CDC_Volume ); // U.K. / Imperial quart
2541 
2542     // 1 Square Meter is...
2543     NEWDP( "m2",        1.0000000000000000E00,  CDC_Area ); // *** Square Meter
2544     NEWD( "mi2",        3.8610215854244585E-07, CDC_Area ); // *** Square Britsh Mile
2545     NEWD( "Nmi2",       2.9155334959812286E-07, CDC_Area ); // *** Square Nautical Mile
2546     NEWD( "in2",        1.5500031000062000E03,  CDC_Area ); // *** Square Inch
2547     NEWD( "ft2",        1.0763910416709722E01,  CDC_Area ); // *** Square Foot
2548     NEWD( "yd2",        1.1959900463010803E00,  CDC_Area ); // *** Square Yard
2549     NEWDP( "ang2",      1.0000000000000000E20,  CDC_Area ); // *** Square Angstroem
2550     NEWD( "Pica2",      8.0352160704321409E06,  CDC_Area ); // *** Square Pica
2551     NEWD( "Morgen",     4.0000000000000000E-04, CDC_Area ); // *** Morgen
2552     NEWDP( "ar",        1.000000E-02,           CDC_Area ); // *** Ar
2553     NEWD( "acre",       2.471053815E-04,        CDC_Area ); // *** Acre
2554     NEWD( "uk_acre",    2.4710538146716534E-04, CDC_Area ); // *** International acre
2555     NEWD( "us_acre",    2.4710439304662790E-04, CDC_Area ); // *** U.S. survey/statute acre
2556     NEWD( "ly2",        1.1172985860549147E-32, CDC_Area ); // *** Square Light-year
2557     NEWD( "ha",         1.000000E-04,           CDC_Area ); // *** Hectare
2558     NEWD( "Quadratlatschen",5.6689342403628117914,CDC_Area ); // ***
2559 
2560     // SPEED: 1 Meter per Second is...
2561     NEWDP( "m/s",   1.0000000000000000E00,  CDC_Speed ); // *** Meters per Second
2562     NEWDP( "m/sec", 1.0000000000000000E00,  CDC_Speed ); // *** Meters per Second also
2563     NEWDP( "m/h",   3.6000000000000000E03,  CDC_Speed ); // *** Meters per Hour
2564     NEWDP( "m/hr",  3.6000000000000000E03,  CDC_Speed ); // *** Meters per Hour also
2565     NEWD( "mph",    2.2369362920544023E00,  CDC_Speed ); // *** Britsh Miles per Hour
2566     NEWD( "kn",     1.9438444924406048E00,  CDC_Speed ); // *** Knot = Nautical Miles per Hour
2567     NEWD( "admkn",  1.9438446603753486E00,  CDC_Speed ); // *** Admiralty Knot
2568     NEWD( "wahnsinnige Geschwindigkeit", 2.0494886343432328E-14, CDC_Speed ); // ***
2569     NEWD( "ludicrous speed", 2.0494886343432328E-14, CDC_Speed ); // ***
2570     NEWD( "laecherliche Geschwindigkeit", 4.0156958471424288E-06, CDC_Speed); // ***
2571     NEWD( "ridiculous speed", 4.0156958471424288E-06, CDC_Speed); // ***
2572 
2573     // INFORMATION: 1 Bit is...
2574     NEWDP( "bit",   1.00E00,  CDC_Information); // *** Bit
2575     NEWDP( "byte",  1.25E-01, CDC_Information); // *** Byte
2576 }
2577 
2578 
~ConvertDataList()2579 ConvertDataList::~ConvertDataList()
2580 {
2581     for( ConvertData* p = First() ; p ; p = Next() )
2582         delete p;
2583 }
2584 
2585 
Convert(double fVal,const STRING & rFrom,const STRING & rTo)2586 double ConvertDataList::Convert( double fVal, const STRING& rFrom, const STRING& rTo )
2587 {
2588 // This will not catch illegal units
2589 //   if( rFrom == rTo )
2590 //       return fVal;
2591 
2592     ConvertData*    pFrom = NULL;
2593     ConvertData*    pTo = NULL;
2594     sal_Bool        bSearchFrom = sal_True;
2595     sal_Bool        bSearchTo = sal_True;
2596     sal_Int16       nLevelFrom = 0;
2597     sal_Int16       nLevelTo = 0;
2598 
2599     ConvertData*    p = First();
2600     while( p && ( bSearchFrom || bSearchTo ) )
2601     {
2602         if( bSearchFrom )
2603         {
2604             sal_Int16   n = p->GetMatchingLevel( rFrom );
2605             if( n != INV_MATCHLEV )
2606             {
2607                 if( n )
2608                 {   // only first match for partial equality rulz a little bit more
2609                     pFrom = p;
2610                     nLevelFrom = n;
2611                 }
2612                 else
2613                 {   // ... but exact match rulz most
2614                     pFrom = p;
2615                     bSearchFrom = sal_False;
2616                     nLevelFrom = n;
2617                 }
2618             }
2619         }
2620 
2621         if( bSearchTo )
2622         {
2623             sal_Int16   n = p->GetMatchingLevel( rTo );
2624             if( n != INV_MATCHLEV )
2625             {
2626                 if( n )
2627                 {   // only first match for partial equality rulz a little bit more
2628                     pTo = p;
2629                     nLevelTo = n;
2630                 }
2631                 else
2632                 {   // ... but exact match rulz most
2633                     pTo = p;
2634                     bSearchTo = sal_False;
2635                     nLevelTo = n;
2636                 }
2637             }
2638         }
2639 
2640         p = Next();
2641     }
2642 
2643     if( pFrom && pTo )
2644         return pFrom->Convert( fVal, *pTo, nLevelFrom, nLevelTo );
2645     else
2646         THROW_IAE;
2647 }
2648 
2649 
2650 
2651 //-----------------------------------------------------------------------------
2652 
ScaDate()2653 ScaDate::ScaDate() :
2654     nOrigDay( 1 ),
2655     nDay( 1 ),
2656     nMonth( 1 ),
2657     nYear( 1900 ),
2658     bLastDayMode( sal_True ),
2659     bLastDay( sal_False ),
2660     b30Days( sal_False ),
2661     bUSMode( sal_False )
2662 {
2663 }
2664 
ScaDate(sal_Int32 nNullDate,sal_Int32 nDate,sal_Int32 nBase)2665 ScaDate::ScaDate( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nBase )
2666 {
2667     DaysToDate( nNullDate + nDate, nOrigDay, nMonth, nYear );
2668     bLastDayMode = (nBase != 5);
2669     bLastDay = (nOrigDay >= ::DaysInMonth( nMonth, nYear ));
2670     b30Days = (nBase == 0) || (nBase == 4);
2671     bUSMode = (nBase == 0);
2672     setDay();
2673 }
2674 
ScaDate(const ScaDate & rCopy)2675 ScaDate::ScaDate( const ScaDate& rCopy ) :
2676     nOrigDay( rCopy.nOrigDay ),
2677     nDay( rCopy.nDay ),
2678     nMonth( rCopy.nMonth ),
2679     nYear( rCopy.nYear ),
2680     bLastDayMode( rCopy.bLastDayMode ),
2681     bLastDay( rCopy.bLastDay ),
2682     b30Days( rCopy.b30Days ),
2683     bUSMode( rCopy.bUSMode )
2684 {
2685 }
2686 
operator =(const ScaDate & rCopy)2687 ScaDate& ScaDate::operator=( const ScaDate& rCopy )
2688 {
2689     if( this != &rCopy )
2690     {
2691         nOrigDay = rCopy.nOrigDay;
2692         nDay = rCopy.nDay;
2693         nMonth = rCopy.nMonth;
2694         nYear = rCopy.nYear;
2695         bLastDayMode = rCopy.bLastDayMode;
2696         bLastDay = rCopy.bLastDay;
2697         b30Days = rCopy.b30Days;
2698         bUSMode = rCopy.bUSMode;
2699     }
2700     return *this;
2701 }
2702 
setDay()2703 void ScaDate::setDay()
2704 {
2705     if( b30Days )
2706     {
2707         // 30-days-mode: set nDay to 30 if original was last day in month
2708         nDay = Min( nOrigDay, static_cast< sal_uInt16 >( 30 ) );
2709         if( bLastDay || (nDay >= ::DaysInMonth( nMonth, nYear )) )
2710             nDay = 30;
2711     }
2712     else
2713     {
2714         // set nDay to last day in this month if original was last day
2715         sal_uInt16 nLastDay = ::DaysInMonth( nMonth, nYear );
2716         nDay = bLastDay ? nLastDay : Min( nOrigDay, nLastDay );
2717     }
2718 }
2719 
getDaysInMonthRange(sal_uInt16 nFrom,sal_uInt16 nTo) const2720 sal_Int32 ScaDate::getDaysInMonthRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const
2721 {
2722     if( nFrom > nTo )
2723         return 0;
2724 
2725     sal_Int32 nRet = 0;
2726     if( b30Days )
2727         nRet = (nTo - nFrom + 1) * 30;
2728     else
2729     {
2730         for( sal_uInt16 nMonthIx = nFrom; nMonthIx <= nTo; ++nMonthIx )
2731             nRet += getDaysInMonth( nMonthIx );
2732     }
2733     return nRet;
2734 }
2735 
getDaysInYearRange(sal_uInt16 nFrom,sal_uInt16 nTo) const2736 sal_Int32 ScaDate::getDaysInYearRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const
2737 {
2738     if( nFrom > nTo )
2739         return 0;
2740 
2741     return b30Days ? ((nTo - nFrom + 1) * 360) : ::GetDaysInYears( nFrom, nTo );
2742 }
2743 
doAddYears(sal_Int32 nYearCount)2744 void ScaDate::doAddYears( sal_Int32 nYearCount )
2745 {
2746     sal_Int32 nNewYear = nYearCount + nYear;
2747     if( (nNewYear < 0) || (nNewYear > 0x7FFF) )
2748         throw lang::IllegalArgumentException();
2749     nYear = static_cast< sal_uInt16 >( nNewYear );
2750 }
2751 
addMonths(sal_Int32 nMonthCount)2752 void ScaDate::addMonths( sal_Int32 nMonthCount )
2753 {
2754     sal_Int32 nNewMonth = nMonthCount + nMonth;
2755     if( nNewMonth > 12 )
2756     {
2757         --nNewMonth;
2758         doAddYears( nNewMonth / 12 );
2759         nMonth = static_cast< sal_uInt16 >( nNewMonth % 12 ) + 1;
2760     }
2761     else if( nNewMonth < 1 )
2762     {
2763         doAddYears( nNewMonth / 12 - 1 );
2764         nMonth = static_cast< sal_uInt16 >( nNewMonth % 12 + 12 );
2765     }
2766     else
2767         nMonth = static_cast< sal_uInt16 >( nNewMonth );
2768     setDay();
2769 }
2770 
getDate(sal_Int32 nNullDate) const2771 sal_Int32 ScaDate::getDate( sal_Int32 nNullDate ) const
2772 {
2773     sal_uInt16 nLastDay = ::DaysInMonth( nMonth, nYear );
2774     sal_uInt16 nRealDay = (bLastDayMode && bLastDay) ? nLastDay : Min( nLastDay, nOrigDay );
2775     return ::DateToDays( nRealDay, nMonth, nYear ) - nNullDate;
2776 }
2777 
getDiff(const ScaDate & rFrom,const ScaDate & rTo)2778 sal_Int32 ScaDate::getDiff( const ScaDate& rFrom, const ScaDate& rTo )
2779 {
2780     if( rFrom > rTo )
2781         return getDiff( rTo, rFrom );
2782 
2783     sal_Int32 nDiff = 0;
2784     ScaDate aFrom( rFrom );
2785     ScaDate aTo( rTo );
2786 
2787     if( rTo.b30Days )
2788     {
2789         // corrections for base 0 (US NASD)
2790         if( rTo.bUSMode )
2791         {
2792             if( ((rFrom.nMonth == 2) || (rFrom.nDay < 30)) && (aTo.nOrigDay == 31) )
2793                 aTo.nDay = 31;
2794             else if( (aTo.nMonth == 2) && aTo.bLastDay )
2795                 aTo.nDay = ::DaysInMonth( 2, aTo.nYear );
2796         }
2797         // corrections for base 4 (Europe)
2798         else
2799         {
2800             if( (aFrom.nMonth == 2) && (aFrom.nDay == 30) )
2801                 aFrom.nDay = ::DaysInMonth( 2, aFrom.nYear );
2802             if( (aTo.nMonth == 2) && (aTo.nDay == 30) )
2803                 aTo.nDay = ::DaysInMonth( 2, aTo.nYear );
2804         }
2805     }
2806 
2807     if( (aFrom.nYear < aTo.nYear) || ((aFrom.nYear == aTo.nYear) && (aFrom.nMonth < aTo.nMonth)) )
2808     {
2809         // move aFrom to 1st day of next month
2810         nDiff = aFrom.getDaysInMonth() - aFrom.nDay + 1;
2811         aFrom.nOrigDay = aFrom.nDay = 1;
2812         aFrom.bLastDay = sal_False;
2813         aFrom.addMonths( 1 );
2814 
2815         if( aFrom.nYear < aTo.nYear )
2816         {
2817             // move aFrom to 1st day of next year
2818             nDiff += aFrom.getDaysInMonthRange( aFrom.nMonth, 12 );
2819             aFrom.addMonths( 13 - aFrom.nMonth );
2820 
2821             // move aFrom to 1st day of this year
2822             nDiff += aFrom.getDaysInYearRange( aFrom.nYear, aTo.nYear - 1 );
2823             aFrom.addYears( aTo.nYear - aFrom.nYear );
2824         }
2825 
2826         // move aFrom to 1st day of this month
2827         nDiff += aFrom.getDaysInMonthRange( aFrom.nMonth, aTo.nMonth - 1 );
2828         aFrom.addMonths( aTo.nMonth - aFrom.nMonth );
2829     }
2830     // finally add remaining days in this month
2831     nDiff += aTo.nDay - aFrom.nDay;
2832     return nDiff > 0 ? nDiff : 0;
2833 }
2834 
operator <(const ScaDate & rCmp) const2835 sal_Bool ScaDate::operator<( const ScaDate& rCmp ) const
2836 {
2837     if( nYear != rCmp.nYear )
2838         return nYear < rCmp.nYear;
2839     if( nMonth != rCmp.nMonth )
2840         return nMonth < rCmp.nMonth;
2841     if( nDay != rCmp.nDay )
2842         return nDay < rCmp.nDay;
2843     if( bLastDay || rCmp.bLastDay )
2844         return !bLastDay && rCmp.bLastDay;
2845     return nOrigDay < rCmp.nOrigDay;
2846 }
2847 
2848 
2849 
2850 //-----------------------------------------------------------------------------
2851 
ScaAnyConverter(const uno::Reference<lang::XMultiServiceFactory> & xServiceFact)2852 ScaAnyConverter::ScaAnyConverter( const uno::Reference< lang::XMultiServiceFactory >& xServiceFact ) :
2853     bHasValidFormat( sal_False )
2854 {
2855     if( xServiceFact.is() )
2856     {
2857         uno::Reference< uno::XInterface > xInstance = xServiceFact->createInstance(
2858             OUString::createFromAscii( "com.sun.star.util.NumberFormatter" ) );
2859         xFormatter = uno::Reference< util::XNumberFormatter >( xInstance, uno::UNO_QUERY );
2860     }
2861 }
2862 
~ScaAnyConverter()2863 ScaAnyConverter::~ScaAnyConverter()
2864 {
2865 }
2866 
init(const uno::Reference<beans::XPropertySet> & xPropSet)2867 void ScaAnyConverter::init( const uno::Reference< beans::XPropertySet >& xPropSet )
2868 {
2869     // try to get default number format
2870     bHasValidFormat = sal_False;
2871     if( xFormatter.is() )
2872     {
2873         // get XFormatsSupplier from outer XPropertySet
2874         uno::Reference< util::XNumberFormatsSupplier > xFormatsSupp( xPropSet, uno::UNO_QUERY );
2875         if( xFormatsSupp.is() )
2876         {
2877             // get XNumberFormatTypes from XNumberFormatsSupplier to get standard index
2878             uno::Reference< util::XNumberFormats > xFormats( xFormatsSupp->getNumberFormats() );
2879             uno::Reference< util::XNumberFormatTypes > xFormatTypes( xFormats, uno::UNO_QUERY );
2880             if( xFormatTypes.is() )
2881             {
2882                 lang::Locale eLocale;
2883                 nDefaultFormat = xFormatTypes->getStandardIndex( eLocale );
2884                 xFormatter->attachNumberFormatsSupplier( xFormatsSupp );
2885                 bHasValidFormat = sal_True;
2886             }
2887         }
2888     }
2889 }
2890 
convertToDouble(const OUString & rString) const2891 double ScaAnyConverter::convertToDouble( const OUString& rString ) const
2892 {
2893     double fValue = 0.0;
2894     if( bHasValidFormat )
2895     {
2896         try
2897         {
2898             fValue = xFormatter->convertStringToNumber( nDefaultFormat, rString );
2899         }
2900         catch( uno::Exception& )
2901         {
2902             throw lang::IllegalArgumentException();
2903         }
2904     }
2905     else
2906     {
2907         rtl_math_ConversionStatus eStatus;
2908         sal_Int32 nEnd;
2909         fValue = ::rtl::math::stringToDouble( rString, '.', ',', &eStatus, &nEnd );
2910         if( (eStatus != rtl_math_ConversionStatus_Ok) || (nEnd < rString.getLength()) )
2911             throw lang::IllegalArgumentException();
2912     }
2913     return fValue;
2914 }
2915 
getDouble(double & rfResult,const uno::Any & rAny) const2916 sal_Bool ScaAnyConverter::getDouble(
2917         double& rfResult,
2918         const uno::Any& rAny ) const
2919 {
2920     rfResult = 0.0;
2921     sal_Bool bContainsVal = sal_True;
2922     switch( rAny.getValueTypeClass() )
2923     {
2924         case uno::TypeClass_VOID:
2925             bContainsVal = sal_False;
2926         break;
2927         case uno::TypeClass_DOUBLE:
2928             rAny >>= rfResult;
2929         break;
2930         case uno::TypeClass_STRING:
2931         {
2932             const OUString* pString = static_cast< const OUString* >( rAny.getValue() );
2933             if( pString->getLength() )
2934                 rfResult = convertToDouble( *pString );
2935             else
2936                 bContainsVal = sal_False;
2937         }
2938         break;
2939         default:
2940             throw lang::IllegalArgumentException();
2941     }
2942     return bContainsVal;
2943 }
2944 
getDouble(double & rfResult,const uno::Reference<beans::XPropertySet> & xPropSet,const uno::Any & rAny)2945 sal_Bool ScaAnyConverter::getDouble(
2946         double& rfResult,
2947         const uno::Reference< beans::XPropertySet >& xPropSet,
2948         const uno::Any& rAny )
2949 {
2950     init( xPropSet );
2951     return getDouble( rfResult, rAny );
2952 }
2953 
getDouble(const uno::Reference<beans::XPropertySet> & xPropSet,const uno::Any & rAny,double fDefault)2954 double ScaAnyConverter::getDouble(
2955         const uno::Reference< beans::XPropertySet >& xPropSet,
2956         const uno::Any& rAny,
2957         double fDefault )
2958 {
2959     double fResult;
2960     if( !getDouble( fResult, xPropSet, rAny ) )
2961         fResult = fDefault;
2962     return fResult;
2963 }
2964 
getInt32(sal_Int32 & rnResult,const uno::Reference<beans::XPropertySet> & xPropSet,const uno::Any & rAny)2965 sal_Bool ScaAnyConverter::getInt32(
2966         sal_Int32& rnResult,
2967         const uno::Reference< beans::XPropertySet >& xPropSet,
2968         const uno::Any& rAny )
2969 {
2970     double fResult;
2971     sal_Bool bContainsVal = getDouble( fResult, xPropSet, rAny );
2972     if( (fResult <= -2147483649.0) || (fResult >= 2147483648.0) )
2973         throw lang::IllegalArgumentException();
2974 
2975     rnResult = static_cast< sal_Int32 >( fResult );
2976     return bContainsVal;
2977 }
2978 
getInt32(const uno::Reference<beans::XPropertySet> & xPropSet,const uno::Any & rAny,sal_Int32 nDefault)2979 sal_Int32 ScaAnyConverter::getInt32(
2980         const uno::Reference< beans::XPropertySet >& xPropSet,
2981         const uno::Any& rAny,
2982         sal_Int32 nDefault )
2983 {
2984     sal_Int32 nResult;
2985     if( !getInt32( nResult, xPropSet, rAny ) )
2986         nResult = nDefault;
2987     return nResult;
2988 }
2989 
2990 
2991 
2992 //-----------------------------------------------------------------------------
2993