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