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 #ifndef ANALYSISHELPER_HXX
24 #define ANALYSISHELPER_HXX
25 
26 
27 #include <com/sun/star/lang/XServiceName.hpp>
28 #include <com/sun/star/lang/XServiceInfo.hpp>
29 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30 #include <com/sun/star/util/Date.hpp>
31 #include <com/sun/star/util/XNumberFormatter.hpp>
32 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
33 #include <com/sun/star/sheet/XAddIn.hpp>
34 #include <com/sun/star/sheet/addin/XAnalysis.hpp>
35 
36 #include <math.h>
37 
38 #include <tools/resid.hxx>
39 #include <tools/rc.hxx>
40 
41 #include "analysisdefs.hxx"
42 
43 
44 class ResMgr;
45 class SortedIndividualInt32List;
46 class ScaAnyConverter;
47 
48 
49 #define	PI			3.1415926535897932
50 #define PI_2		(PI/2.0)
51 //#define	EULER		2.7182818284590452
52 #define	EOL			( ( const sal_Char* ) 1 )
53 #define	EOE			( ( const sal_Char* ) 2 )
54 
55 
56 //double				_Test( sal_Int32 nMode, double f1, double f2, double f3 );
57 inline sal_Bool     IsLeapYear( sal_uInt16 nYear );
58 sal_uInt16			DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear );
59 sal_Int32			DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear );
60 void				DaysToDate( sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear ) throw( ::com::sun::star::lang::IllegalArgumentException );
61 sal_Int32           GetNullDate( const REF( CSS::beans::XPropertySet )& xOptions ) THROWDEF_RTE;
62 sal_Int32			GetDiffDate360(
63 						sal_uInt16 nDay1, sal_uInt16 nMonth1, sal_uInt16 nYear1, sal_Bool bLeapYear1,
64 						sal_uInt16 nDay2, sal_uInt16 nMonth2, sal_uInt16 nYear2,
65 						sal_Bool bUSAMethod );
66 inline sal_Int32	GetDiffDate360( constREFXPS& xOpt, sal_Int32 nDate1, sal_Int32 nDate2, sal_Bool bUSAMethod );
67 sal_Int32			GetDiffDate360( sal_Int32 nNullDate, sal_Int32 nDate1, sal_Int32 nDate2, sal_Bool bUSAMethod );
68 
69 sal_Int32			GetDaysInYears( sal_uInt16 nYear1, sal_uInt16 nYear2 );
70 inline sal_Int16	GetDayOfWeek( sal_Int32 nDate );
71 void				GetDiffParam( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode,
72 						sal_uInt16& rYears, sal_Int32& rDayDiffPart, sal_Int32& rDaysInYear ) THROWDEF_RTE_IAE;
73 						// rYears = full num of years
74 						// rDayDiffPart = num of days for last year
75 						// rDaysInYear = num of days in first year
76 sal_Int32			GetDiffDate( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode,
77 								sal_Int32* pOptDaysIn1stYear = NULL ) THROWDEF_RTE_IAE;
78 double				GetYearDiff( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode )
79 								THROWDEF_RTE_IAE;
80 sal_Int32			GetDaysInYear( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nMode ) THROWDEF_RTE_IAE;
81 double				GetYearFrac( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode )
82 						THROWDEF_RTE_IAE;
83 inline double		GetYearFrac( constREFXPS& xOpt, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode )
84 						THROWDEF_RTE_IAE;
85 inline void			AlignDate( sal_uInt16& rDay, sal_uInt16 nMonth, sal_uInt16 nYear );
86 
87 double				Fak( sal_Int32 n );
88 double				GetGcd( double f1, double f2 );
89 double				ConvertToDec( const STRING& rFromNum, sal_uInt16 nBaseFrom, sal_uInt16 nCharLim ) THROWDEF_RTE_IAE;
90 STRING				ConvertFromDec(
91                         double fNum, double fMin, double fMax, sal_uInt16 nBase,
92                         sal_Int32 nPlaces, sal_Int32 nMaxPlaces, sal_Bool bUsePlaces ) THROWDEF_RTE_IAE;
93 double				Erf( double fX );
94 double				Erfc( double fX );
95 sal_Bool			ParseDouble( const sal_Unicode*& rpDoubleAsString, double& rReturn );
96 STRING				GetString( double fNumber, sal_Bool bLeadingSign = sal_False, sal_uInt16 nMaxNumOfDigits = 15 );
97 inline double		Exp10( sal_Int16 nPower );		// 10 ^ nPower
98 
99 double				GetAmordegrc( sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer,
100 								double fRestVal, double fPer, double fRate, sal_Int32 nBase ) THROWDEF_RTE_IAE;
101 double				GetAmorlinc( sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer,
102 								double fRestVal, double fPer, double fRate, sal_Int32 nBase ) THROWDEF_RTE_IAE;
103 double				GetDuration( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup,
104 								double fYield, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE;
105 double				GetYieldmat( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue,
106 								double fRate, double fPrice, sal_Int32 nBase ) THROWDEF_RTE_IAE;
107 double				GetOddfprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue,
108 								sal_Int32 nFirstCoup, double fRate, double fYield, double fRedemp,
109 								sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE;
110 double				getYield_( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup, double fPrice,
111 								double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE;
112 double				getPrice_( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fRate, double fYield,
113 								double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE;
114 double				GetOddfyield( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue,
115 								sal_Int32 nFirstCoup, double fRate, double fPrice, double fRedemp,
116 								sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE;
117 double				GetOddlprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastInterest,
118 								double fRate, double fYield, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE;
119 double				GetOddlyield( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastInterest,
120 								double fRate, double fPrice, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE;
121 double				GetRmz( double fZins, double fZzr, double fBw, double fZw, sal_Int32 nF );
122 double				GetZw( double fZins, double fZzr, double fRmz, double fBw, sal_Int32 nF );
123 //double				TBillYield( constREFXPS& xOpt, sal_Int32 nSettle, sal_Int32 nMat, double fPrice )THROWDEF_RTE_IAE;
124 
125 double				GetCouppcd( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq,
126 								sal_Int32 nBase ) THROWDEF_RTE_IAE;
127 double              GetCoupncd( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq,
128 								sal_Int32 nBase ) THROWDEF_RTE_IAE;
129 double              GetCoupdaybs( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq,
130 								sal_Int32 nBase ) THROWDEF_RTE_IAE;
131 double				GetCoupdaysnc( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq,
132 								sal_Int32 nBase ) THROWDEF_RTE_IAE;
133 
134 double              GetCoupnum( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat,
135 								sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE;
136 double				GetCoupdays( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq,
137 								sal_Int32 nBase ) THROWDEF_RTE_IAE;
138 
139 
140 
141 
142 //-----------------------------------------------------------------------------
143 
144 
145 
146 class MyList
147 {
148 private:
149 	static const sal_uInt32	nStartSize;
150 	static const sal_uInt32	nIncrSize;
151 
152 	void**					pData;			// pointer array
153 	sal_uInt32				nSize;			// array size
154 	sal_uInt32				nNew;			// next index to be inserted at
155 	sal_uInt32				nAct;			// actual for iterations
156 
157 	void					_Grow( void );
158 	inline void				Grow( void );
159 protected:
160 public:
161 							MyList( void );
162 	virtual					~MyList();
163 
164 	inline const void*		GetObject( sal_uInt32 nIndex ) const;
165 	inline const void*		First( void );
166 	inline const void*		Next( void );
167 
168 	inline void				Append( void* pNewElement );
169 	void					Insert( void* pNewLement, sal_uInt32 nPlace );
170 
171 	inline sal_uInt32		Count( void ) const;
172 };
173 
174 
175 
176 
177 class StringList : protected MyList
178 {
179 public:
180 	virtual					~StringList();
181 
182 	inline const STRING*	First( void );
183 	inline const STRING*	Next( void );
184 	inline const STRING*	Get( sal_uInt32 nIndex ) const;
185 
186     using MyList::Append;
187 	inline void				Append( STRING* pNew );
188 	inline void				Append( const STRING& rNew );
189 
190 	using MyList::Count;
191 };
192 
193 
194 
195 
196 enum FDCategory
197 {
198 	FDCat_AddIn,
199 	FDCat_DateTime,
200 	FDCat_Finance,
201 	FDCat_Inf,
202 	FDCat_Math,
203 	FDCat_Tech
204 };
205 
206 
207 struct FuncDataBase
208 {
209 	const sal_Char*			pIntName;
210 	sal_uInt16				nUINameID;			// resource ID to UI name
211 	sal_uInt16				nDescrID;			// resource ID to description, parameter names and ~ description
212 	sal_Bool				bDouble;			// name already exist in Calc
213 	sal_Bool				bWithOpt;			// first parameter is internal
214 	sal_uInt16				nCompListID;		// resource ID to list of valid names
215 	sal_uInt16				nNumOfParams;		// number of named / described parameters
216 	FDCategory				eCat;				// function category
217 };
218 
219 
220 
221 
222 class FuncData
223 {
224 private:
225     ::rtl::OUString         aIntName;
226 	sal_uInt16				nUINameID;
227 	sal_uInt16				nDescrID;			// leads also to parameter descriptions!
228 	sal_Bool				bDouble;			// flag for names, wich already exist in Calc
229 	sal_Bool				bWithOpt;			// has internal parameter on first position
230 
231 	sal_uInt16				nParam;				// num of parameters
232 	sal_uInt16				nCompID;
233 	StringList				aCompList;			// list of all valid names
234 	FDCategory				eCat;				// function category
235 public:
236 							FuncData( const FuncDataBase& rBaseData, ResMgr& );
237 	virtual					~FuncData();
238 
239 	inline sal_uInt16		GetUINameID( void ) const;
240 	inline sal_uInt16		GetDescrID( void ) const;
241 	inline sal_Bool			IsDouble( void ) const;
242 	inline sal_Bool			HasIntParam( void ) const;
243 
244 	sal_uInt16				GetStrIndex( sal_uInt16 nParamNum ) const;
245     inline sal_Bool         Is( const ::rtl::OUString& rCompareTo ) const;
246 
247 	inline const StringList&	GetCompNameList( void ) const;
248 
249 	inline FDCategory		GetCategory( void ) const;
250 };
251 
252 
253 
254 
255 class CStrList : private MyList
256 {
257 public:
258     using MyList::Append;
259 	inline void				Append( const sal_Char* pNew );
260 	inline const sal_Char*	Get( sal_uInt32 nIndex ) const;
261 	using MyList::Count;
262 };
263 
264 
265 
266 
267 class FuncDataList : private MyList
268 {
269     ::rtl::OUString         aLastName;
270 	sal_uInt32				nLast;
271 public:
272 							FuncDataList( ResMgr& );
273 	virtual					~FuncDataList();
274     using MyList::Append;
275 	inline void				Append( FuncData* pNew );
276 	inline const FuncData*	Get( sal_uInt32 nIndex ) const;
277 	using MyList::Count;
278 
279     const FuncData*         Get( const ::rtl::OUString& aProgrammaticName ) const;
280 };
281 
282 
283 
284 class AnalysisResId : public ResId
285 {
286  public:
287 					AnalysisResId( sal_uInt16 nId, ResMgr& rResMgr );
288 };
289 
290 
291 
292 
293 class AnalysisRscStrLoader : public Resource
294 {
295 private:
296 	String			aStr;
297 public:
298 	AnalysisRscStrLoader( sal_uInt16 nRsc, sal_uInt16 nStrId, ResMgr& rResMgr ) :
299 		Resource( AnalysisResId( nRsc, rResMgr ) ),
300 		aStr( AnalysisResId( nStrId, rResMgr ) )
301 	{
302 		FreeResource();
303 	}
304 
305 	const String&	GetString() const { return aStr; }
306 
307 };
308 
309 
310 
311 //-----------------------------------------------------------------------------
312 
313 /// sorted list with unique sal_Int32 values
314 class SortedIndividualInt32List : private MyList
315 {
316 protected:
317     using MyList::Insert;
318     void                        Insert( sal_Int32 nDay );
319     void                        Insert( sal_Int32 nDay, sal_Int32 nNullDate, sal_Bool bInsertOnWeekend );
320     void                        Insert( double fDay, sal_Int32 nNullDate, sal_Bool bInsertOnWeekend )
321                                     throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
322 
323                                 /** @param rAnyConv  must be an initialized ScaAnyConmverter
324                                     @param bInsertOnWeekend  insertion mode: sal_False = holidays on weekend are omitted */
325     void                        InsertHolidayList(
326                                     const ScaAnyConverter& rAnyConv,
327                                     const CSS::uno::Any& rHolAny,
328                                     sal_Int32 nNullDate,
329                                     sal_Bool bInsertOnWeekend ) throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
330 
331 public:
332                                 SortedIndividualInt32List();
333     virtual                     ~SortedIndividualInt32List();
334 
335                                 using MyList::Count;
336 
337                                 /// @return  element on position nIndex or 0 on invalid index
338     inline sal_Int32            Get( sal_uInt32 nIndex ) const
339                                     { return (sal_Int32)(sal_IntPtr) MyList::GetObject( nIndex ); }
340 
341                                 /// @return  sal_True if nVal (internal date representation) is contained
342     sal_Bool                    Find( sal_Int32 nVal ) const;
343 
344                                 /** @param rAnyConv  is an initialized or uninitialized ScaAnyConverter
345                                     @param bInsertOnWeekend  insertion mode: sal_False = holidays on weekend are omitted */
346     void                        InsertHolidayList(
347                                     ScaAnyConverter& rAnyConv,
348                                     const CSS::uno::Reference< CSS::beans::XPropertySet >& xOptions,
349                                     const CSS::uno::Any& rHolAny,
350                                     sal_Int32 nNullDate,
351                                     sal_Bool bInsertOnWeekend ) throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
352 };
353 
354 
355 //-----------------------------------------------------------------------------
356 
357 class ScaDoubleList : protected MyList
358 {
359 protected:
360     inline void                 ListAppend( double fValue ) { MyList::Append( new double( fValue ) ); }
361 
362     using MyList::Append;
363     inline void                 Append( double fValue ) throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException )
364                                     { if( CheckInsert( fValue ) ) ListAppend( fValue ); }
365 
366                                 /** @param rAnyConv  must be an initialized ScaAnyConmverter
367                                     @param bIgnoreEmpty  handling of empty Any's/strings: sal_False = inserted as 0.0; sal_True = omitted */
368     void                        Append(
369                                     const ScaAnyConverter& rAnyConv,
370                                     const CSS::uno::Any& rAny,
371                                     sal_Bool bIgnoreEmpty ) throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
372 
373                                 /** @param rAnyConv  must be an initialized ScaAnyConmverter
374                                     @param bIgnoreEmpty  handling of empty Any's/strings: sal_False = inserted as 0.0; sal_True = omitted */
375     void                        Append(
376                                     const ScaAnyConverter& rAnyConv,
377                                     const CSS::uno::Sequence< CSS::uno::Any >& rAnySeq,
378                                     sal_Bool bIgnoreEmpty ) throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
379 
380                                 /** @param rAnyConv  must be an initialized ScaAnyConmverter
381                                     @param bIgnoreEmpty  handling of empty Any's/strings: sal_False = inserted as 0.0; sal_True = omitted */
382     void                        Append(
383                                     const ScaAnyConverter& rAnyConv,
384                                     const CSS::uno::Sequence< CSS::uno::Sequence< CSS::uno::Any > >& rAnySeq,
385                                     sal_Bool bIgnoreEmpty ) throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
386 
387 public:
388     virtual                     ~ScaDoubleList();
389 
390                                 using MyList::Count;
391     inline const double*        Get( sal_uInt32 nIndex ) const
392                                         { return static_cast< const double* >( MyList::GetObject( nIndex ) ); }
393 
394     inline const double*        First() { return static_cast< const double* >( MyList::First() ); }
395     inline const double*        Next()  { return static_cast< const double* >( MyList::Next() ); }
396 
397     void                        Append( const CSS::uno::Sequence< CSS::uno::Sequence< double > >& rValueArr )
398                                     throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
399     void                        Append( const CSS::uno::Sequence< CSS::uno::Sequence< sal_Int32 > >& rValueArr )
400                                     throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
401 
402                                 /** @param rAnyConv  is an initialized or uninitialized ScaAnyConverter
403                                     @param bIgnoreEmpty  handling of empty Any's/strings: sal_False = inserted as 0.0; sal_True = omitted */
404     void                        Append(
405                                     ScaAnyConverter& rAnyConv,
406                                     const CSS::uno::Reference< CSS::beans::XPropertySet >& xOpt,
407                                     const CSS::uno::Sequence< CSS::uno::Any >& rAnySeq,
408                                     sal_Bool bIgnoreEmpty = sal_True ) throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
409 
410     virtual sal_Bool            CheckInsert( double fValue ) const
411                                     throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
412 };
413 
414 
415 //-----------------------------------------------------------------------------
416 
417 /// stores double values >0.0, throws exception for double values <0.0, does nothing for 0.0
418 class ScaDoubleListGT0 : public ScaDoubleList
419 {
420 public:
421     virtual sal_Bool            CheckInsert( double fValue ) const
422                                     throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
423 };
424 
425 
426 //-----------------------------------------------------------------------------
427 
428 /// stores double values >=0.0, throws exception for double values <0.0
429 class ScaDoubleListGE0 : public ScaDoubleList
430 {
431 public:
432     virtual sal_Bool            CheckInsert( double fValue ) const
433                                     throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
434 };
435 
436 
437 //-----------------------------------------------------------------------------
438 
439 class Complex
440 {
441 	double					r;
442 	double					i;
443     sal_Unicode             c;
444 
445 public:
446     inline                  Complex( double fReal, double fImag = 0.0, sal_Char cC = '\0' );
447 							Complex( const STRING& rComplexAsString ) THROWDEF_RTE_IAE;
448 
449 	inline static sal_Bool	IsImagUnit( sal_Unicode c );
450 	static sal_Bool			ParseString( const STRING& rComplexAsString, Complex& rReturn );
451     STRING                  GetString() const THROWDEF_RTE_IAE;
452 
453 	inline double			Real( void ) const;
454 	inline double			Imag( void ) const;
455 
456 	double					Arg( void ) const THROWDEF_RTE_IAE;
457 	inline double			Abs( void ) const;
458 
459 	// following functions change the complex number itself to avoid unnecessary copy actions!
460 	void					Power( double fPower ) THROWDEF_RTE_IAE;
461 	void					Sqrt( void );
462 	void					Sin( void ) THROWDEF_RTE_IAE;
463 	void					Cos( void ) THROWDEF_RTE_IAE;
464 	void					Div( const Complex& rDivisor ) THROWDEF_RTE_IAE;
465 	void					Exp( void );
466 	inline void				Conjugate( void );
467 	void					Ln( void ) THROWDEF_RTE_IAE;
468 	void					Log10( void ) THROWDEF_RTE_IAE;
469 	void					Log2( void ) THROWDEF_RTE_IAE;
470 	inline void				Mult( double fFact );
471 	inline void				Mult( const Complex& rMult );
472 	inline void				Sub( const Complex& rMult );
473 	inline void				Add( const Complex& rAdd );
474 };
475 
476 
477 
478 
479 enum ComplListAppendHandl
480 {
481 	AH_EmptyAsErr,
482 	AH_EmpyAs0,
483 	AH_IgnoreEmpty
484 };
485 
486 
487 class ComplexList : protected MyList
488 {
489 public:
490 	virtual					~ComplexList();
491 
492 	inline const Complex*	Get( sal_uInt32 nIndex ) const;
493 	inline const Complex*	First( void );
494 	inline const Complex*	Next( void );
495 
496 	using MyList::Count;
497 
498     using MyList::Append;
499 	inline void				Append( Complex* pNew );
500 	void					Append( const SEQSEQ( STRING )& rComplexNumList, ComplListAppendHandl eAH = AH_EmpyAs0 ) THROWDEF_RTE_IAE;
501 	void					Append( const SEQ( ANY )& aMultPars,ComplListAppendHandl eAH = AH_EmpyAs0 ) THROWDEF_RTE_IAE;
502 };
503 
504 
505 
506 
507 enum ConvertDataClass
508 {
509 	CDC_Mass, CDC_Length, CDC_Time, CDC_Pressure, CDC_Force, CDC_Energy, CDC_Power, CDC_Magnetism,
510 	CDC_Temperature, CDC_Volume, CDC_Area, CDC_Speed, CDC_Information
511 };
512 
513 
514 #define	INV_MATCHLEV		1764					// guess, what this is... :-)
515 
516 
517 class ConvertDataList;
518 
519 
520 
521 
522 class ConvertData
523 {
524 protected:
525 	friend class ConvertDataList;
526 	double					fConst;
527 	STRING					aName;
528 	ConvertDataClass		eClass;
529     sal_Bool                bPrefixSupport;
530 public:
531 							ConvertData(
532 								const sal_Char		pUnitName[],
533 								double				fConvertConstant,
534 								ConvertDataClass	eClass,
535                                 sal_Bool            bPrefSupport = sal_False );
536 
537     virtual                 ~ConvertData();
538 
539 	sal_Int16				GetMatchingLevel( const STRING& rRef ) const;
540 									// 0.0 = no equality
541 									// 1.0 = matches exact
542 									// rest = matches without an assumed prefix of one character
543 									//  rest gives power for 10 represented by the prefix (e.g. 3 for k or -9 for n
544 
545 	virtual double			Convert( double fVal, const ConvertData& rTo,
546 								sal_Int16 nMatchLevelFrom, sal_Int16 nMatchLevelTo ) const THROWDEF_RTE_IAE;
547 									// converts fVal from this unit to rFrom unit
548 									// throws exception if not from same class
549 									// this implementation is for proportional cases only
550 	virtual double			ConvertToBase( double fVal, sal_Int16 nMatchLevel ) const;
551 	virtual double			ConvertFromBase( double fVal, sal_Int16 nMatchLevel ) const;
552 
553 	inline ConvertDataClass	Class( void ) const;
554     inline sal_Bool         IsPrefixSupport( void ) const;
555 };
556 
557 
558 
559 
560 class ConvertDataLinear : public ConvertData
561 {
562 protected:
563 	double					fOffs;
564 public:
565 	inline					ConvertDataLinear(
566 								const sal_Char		pUnitName[],
567 								double				fConvertConstant,
568 								double				fConvertOffset,
569 								ConvertDataClass	eClass,
570                                 sal_Bool            bPrefSupport = sal_False );
571 
572     virtual                 ~ConvertDataLinear();
573 
574 	virtual double			Convert( double fVal, const ConvertData& rTo,
575 								sal_Int16 nMatchLevelFrom, sal_Int16 nMatchLevelTo ) const THROWDEF_RTE_IAE;
576 									// for cases where f(x) = a + bx applies (e.g. Temperatures)
577 
578 	virtual double			ConvertToBase( double fVal, sal_Int16 nMatchLevel ) const;
579 	virtual double			ConvertFromBase( double fVal, sal_Int16 nMatchLevel ) const;
580 };
581 
582 
583 
584 
585 class ConvertDataList : protected MyList
586 {
587 private:
588 protected:
589 	inline ConvertData*		First( void );
590 	inline ConvertData*		Next( void );
591 public:
592 							ConvertDataList( void );
593 	virtual					~ConvertDataList();
594 
595 	double					Convert( double fVal, const STRING& rFrom, const STRING& rTo ) THROWDEF_RTE_IAE;
596 };
597 
598 
599 
600 
601 inline sal_Bool IsLeapYear( sal_uInt16 n )
602 {
603     return ( (( ( n % 4 ) == 0 ) && ( ( n % 100 ) != 0)) || ( ( n % 400 ) == 0 ) );
604 }
605 
606 
607 inline sal_Int32 GetDiffDate360( constREFXPS& xOpt, sal_Int32 nDate1, sal_Int32 nDate2, sal_Bool bUSAMethod )
608 {
609 	return GetDiffDate360( GetNullDate( xOpt ), nDate1, nDate2, bUSAMethod );
610 }
611 
612 
613 inline sal_Int16 GetDayOfWeek( sal_Int32 n )
614 {	// monday = 0, ..., sunday = 6
615     return static_cast< sal_Int16 >( ( n - 1 ) % 7 );
616 }
617 
618 
619 inline double GetYearFrac( constREFXPS& xOpt, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode ) THROWDEF_RTE_IAE
620 {
621 	return GetYearFrac( GetNullDate( xOpt ), nStartDate, nEndDate, nMode );
622 }
623 
624 
625 inline void AlignDate( sal_uInt16& rD, sal_uInt16 nM, sal_uInt16 nY )
626 {
627 	sal_uInt16	nMax = DaysInMonth( nM, nY );
628 
629 	if( rD > nMax )
630 		rD = nMax;
631 }
632 
633 
634 inline void MyList::Grow( void )
635 {
636 	if( nNew >= nSize )
637 		_Grow();
638 }
639 
640 
641 inline const void* MyList::GetObject( sal_uInt32 n ) const
642 {
643 	if( n < nNew )
644 		return pData[ n ];
645 	else
646 		return NULL;
647 }
648 
649 
650 inline const void* MyList::First( void )
651 {
652 	nAct = 0;
653 	if( nNew )
654 		return pData[ 0 ];
655 	else
656 		return NULL;
657 }
658 
659 
660 inline const void* MyList::Next( void )
661 {
662 	nAct++;
663 	if( nAct < nNew )
664 		return pData[ nAct ];
665 	else
666 	{
667 		nAct--;
668 		return NULL;
669 	}
670 }
671 
672 
673 inline void MyList::Append( void* p )
674 {
675 	Grow();
676 	pData[ nNew ] = p;
677 	nNew++;
678 }
679 
680 
681 inline sal_uInt32 MyList::Count( void ) const
682 {
683 	return nNew;
684 }
685 
686 
687 
688 
689 inline const STRING* StringList::First( void )
690 {
691 	return ( const STRING* ) MyList::First();
692 }
693 
694 
695 inline const STRING* StringList::Next( void )
696 {
697 	return ( const STRING* ) MyList::Next();
698 }
699 
700 
701 inline const STRING* StringList::Get( sal_uInt32 n ) const
702 {
703 	return ( const STRING* ) MyList::GetObject( n );
704 }
705 
706 
707 inline void StringList::Append( STRING* p )
708 {
709 	MyList::Append( p );
710 }
711 
712 
713 inline void StringList::Append( const STRING& r )
714 {
715 	MyList::Append( new STRING( r ) );
716 }
717 
718 
719 
720 
721 inline sal_uInt16 FuncData::GetUINameID( void ) const
722 {
723 	return nUINameID;
724 }
725 
726 
727 inline sal_uInt16 FuncData::GetDescrID( void ) const
728 {
729 	return nDescrID;
730 }
731 
732 
733 inline sal_Bool FuncData::IsDouble( void ) const
734 {
735 	return bDouble;
736 }
737 
738 
739 inline sal_Bool FuncData::HasIntParam( void ) const
740 {
741 	return bWithOpt;
742 }
743 
744 
745 inline sal_Bool FuncData::Is( const ::rtl::OUString& r ) const
746 {
747 	return aIntName == r;
748 }
749 
750 
751 inline const StringList& FuncData::GetCompNameList( void ) const
752 {
753 	return aCompList;
754 }
755 
756 
757 inline FDCategory FuncData::GetCategory( void ) const
758 {
759 	return eCat;
760 }
761 
762 
763 
764 
765 inline void CStrList::Append( const sal_Char* p )
766 {
767 	MyList::Append( ( void* ) p );
768 }
769 
770 
771 inline const sal_Char* CStrList::Get( sal_uInt32 n ) const
772 {
773 	return ( const sal_Char* ) MyList::GetObject( n );
774 }
775 
776 
777 
778 
779 inline void FuncDataList::Append( FuncData* p )
780 {
781 	MyList::Append( p );
782 }
783 
784 
785 inline const FuncData* FuncDataList::Get( sal_uInt32 n ) const
786 {
787 	return ( const FuncData* ) MyList::GetObject( n );
788 }
789 
790 
791 inline Complex::Complex( double fReal, double fImag, sal_Char cC ) :
792 		r( fReal ), i( fImag ), c( cC )
793 {
794 }
795 
796 
797 inline double Complex::Real( void ) const
798 {
799 	return r;
800 }
801 
802 
803 inline double Complex::Imag( void ) const
804 {
805 	return i;
806 }
807 
808 
809 inline double Complex::Abs( void ) const
810 {
811 	return sqrt( r * r + i * i );
812 }
813 
814 
815 void Complex::Conjugate( void )
816 {
817 	i = -i;
818 }
819 
820 
821 inline void Complex::Mult( double f )
822 {
823 	i *= f;
824 	r *= f;
825 }
826 
827 
828 inline void Complex::Mult( const Complex& rM )
829 {
830 	double	r_ = r;
831 	double	i_ = i;
832 
833 	r = r_ * rM.r - i_ * rM.i;
834 	i = r_ * rM.i + i_ * rM.r;
835 
836     if( !c ) c = rM.c;
837 }
838 
839 
840 inline void Complex::Sub( const Complex& rC )
841 {
842 	r -= rC.r;
843 	i -= rC.i;
844     if( !c ) c = rC.c;
845 }
846 
847 
848 inline void Complex::Add( const Complex& rAdd )
849 {
850 	r += rAdd.r;
851 	i += rAdd.i;
852     if( !c ) c = rAdd.c;
853 }
854 
855 
856 
857 
858 inline const Complex* ComplexList::Get( sal_uInt32 n ) const
859 {
860 	return ( const Complex* ) MyList::GetObject( n );
861 }
862 
863 
864 inline const Complex* ComplexList::First( void )
865 {
866 	return ( const Complex* ) MyList::First();
867 }
868 
869 
870 inline const Complex* ComplexList::Next( void )
871 {
872 	return ( const Complex* ) MyList::Next();
873 }
874 
875 
876 inline void ComplexList::Append( Complex* p )
877 {
878 	MyList::Append( p );
879 }
880 
881 
882 
883 
884 inline ConvertDataClass	ConvertData::Class( void ) const
885 {
886 	return eClass;
887 }
888 
889 
890 
891 inline sal_Bool ConvertData::IsPrefixSupport( void ) const
892 {
893     return bPrefixSupport;
894 }
895 
896 inline ConvertDataLinear::ConvertDataLinear( const sal_Char* p, double fC, double fO, ConvertDataClass e,
897         sal_Bool bPrefSupport ) :
898 	ConvertData( p, fC, e, bPrefSupport ),
899 	fOffs( fO )
900 {
901 }
902 
903 
904 
905 
906 inline ConvertData* ConvertDataList::First( void )
907 {
908 	return ( ConvertData* ) MyList::First();
909 }
910 
911 
912 inline ConvertData* ConvertDataList::Next( void )
913 {
914 	return ( ConvertData* ) MyList::Next();
915 }
916 
917 //-----------------------------------------------------------------------------
918 
919 /// Helper class for date calculation for various financial functions
920 class ScaDate
921 {
922 private:
923     sal_uInt16                  nOrigDay;           /// is the day of the original date.
924     sal_uInt16                  nDay;               /// is the calculated day depending on the current month/year.
925     sal_uInt16                  nMonth;             /// is the current month (one-based).
926     sal_uInt16                  nYear;              /// is the current year.
927     sal_Bool                    bLastDayMode : 1;   /// if sal_True, recalculate nDay after every calculation.
928     sal_Bool                    bLastDay : 1;       /// is sal_True, if original date was the last day in month.
929     sal_Bool                    b30Days : 1;        /// is sal_True, if every month has 30 days in calculations.
930     sal_Bool                    bUSMode : 1;        /// is sal_True, if the US method of 30-day-calculations is used.
931 
932                                 /// Calculates nDay from nOrigDay and current date.
933     void                        setDay();
934 
935                                 /// @return  count of days in current month
936     inline sal_uInt16           getDaysInMonth() const;
937                                 /// @return  count of days in given month
938     inline sal_uInt16           getDaysInMonth( sal_uInt16 _nMon ) const;
939 
940                                 /// @ return  count of days in the given month range
941     sal_Int32                   getDaysInMonthRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const;
942                                 /// @ return  count of days in the given year range
943     sal_Int32                   getDaysInYearRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const;
944 
945                                 /// Adds/subtracts the given count of years, does not adjust day.
946     void                        doAddYears( sal_Int32 nYearCount ) throw( CSS::lang::IllegalArgumentException );
947 
948 public:
949                                 ScaDate();
950                                 /** @param nBase
951                                         date handling mode (days in month / days in year):
952                                         0 = 30 days / 360 days (US NASD)
953                                         1 = exact / exact
954                                         2 = exact / 360
955                                         3 = exact / 365
956                                         4 = 30 days / 360 days (Europe)
957                                         5 = exact / exact (no last day adjustment) */
958                                 ScaDate( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nBase );
959                                 ScaDate( const ScaDate& rCopy );
960     ScaDate&                    operator=( const ScaDate& rCopy );
961 
962                                 /// @return  the current month.
963     inline sal_uInt16           getMonth() const    { return nMonth; };
964                                 /// @return  the current year.
965     inline sal_uInt16           getYear() const     { return nYear; };
966 
967                                 /// adds/subtracts the given count of months, adjusts day
968     void                        addMonths( sal_Int32 nMonthCount ) throw( CSS::lang::IllegalArgumentException );
969 
970                                 /// sets the given year, adjusts day
971     inline void                 setYear( sal_uInt16 nNewYear );
972                                 /// adds/subtracts the given count of years, adjusts day
973     inline void                 addYears( sal_Int32 nYearCount ) throw( CSS::lang::IllegalArgumentException );
974 
975                                 /// @return  the internal number of the current date
976     sal_Int32                   getDate( sal_Int32 nNullDate ) const;
977                                 /// @return  the number of days between the two dates
978     static sal_Int32            getDiff( const ScaDate& rFrom, const ScaDate& rTo ) throw( CSS::lang::IllegalArgumentException );
979 
980     sal_Bool                    operator<( const ScaDate& rCmp ) const;
981     inline sal_Bool             operator<=( const ScaDate& rCmp ) const { return !(rCmp < *this); }
982     inline sal_Bool             operator>( const ScaDate& rCmp ) const  { return rCmp < *this; }
983     inline sal_Bool             operator>=( const ScaDate& rCmp ) const { return !(*this < rCmp); }
984 };
985 
986 inline sal_uInt16 ScaDate::getDaysInMonth() const
987 {
988     return getDaysInMonth( nMonth );
989 }
990 
991 inline sal_uInt16 ScaDate::getDaysInMonth( sal_uInt16 _nMon ) const
992 {
993     return b30Days ? 30 : DaysInMonth( _nMon, nYear );
994 }
995 
996 inline void ScaDate::setYear( sal_uInt16 nNewYear )
997 {
998     nYear = nNewYear;
999     setDay();
1000 }
1001 
1002 inline void ScaDate::addYears( sal_Int32 nYearCount ) throw( CSS::lang::IllegalArgumentException )
1003 {
1004     doAddYears( nYearCount );
1005     setDay();
1006 }
1007 
1008 
1009 //-----------------------------------------------------------------------------
1010 
1011 /// Helper class for Any->double conversion, using current language settings
1012 class ScaAnyConverter
1013 {
1014 private:
1015     CSS::uno::Reference< CSS::util::XNumberFormatter > xFormatter;
1016     sal_Int32                   nDefaultFormat;
1017     sal_Bool                    bHasValidFormat;
1018 
1019                                 /** Converts a string to double using the number formatter. If the formatter is not
1020                                     valid, ::rtl::math::stringToDouble() with english separators will be used.
1021                                     @throws com::sun::star::lang::IllegalArgumentException
1022                                         on strings not representing any double value.
1023                                     @return  the converted double value. */
1024     double                      convertToDouble(
1025                                     const ::rtl::OUString& rString ) const
1026                                 throw( CSS::lang::IllegalArgumentException );
1027 
1028 public:
1029                                 ScaAnyConverter(
1030                                     const CSS::uno::Reference< CSS::lang::XMultiServiceFactory >& xServiceFact );
1031                                 ~ScaAnyConverter();
1032 
1033                                 /// Initializing with current language settings
1034     void                        init(
1035                                     const CSS::uno::Reference< CSS::beans::XPropertySet >& xPropSet )
1036                                 throw( CSS::uno::RuntimeException );
1037 
1038                                 /** Converts an Any to double (without initialization).
1039                                     The Any can be empty or contain a double or string.
1040                                     @throws com::sun::star::lang::IllegalArgumentException
1041                                         on other Any types or on invalid strings.
1042                                     @return  sal_True if the Any contains a double or a non-empty valid string,
1043                                              sal_False if the Any is empty or the string is empty */
1044     sal_Bool                    getDouble(
1045                                     double& rfResult,
1046                                     const CSS::uno::Any& rAny ) const
1047                                 throw( CSS::lang::IllegalArgumentException );
1048 
1049                                 /** Converts an Any to double (with initialization).
1050                                     The Any can be empty or contain a double or string.
1051                                     @throws com::sun::star::lang::IllegalArgumentException
1052                                         on other Any types or on invalid strings.
1053                                     @return  sal_True if the Any contains a double or a non-empty valid string,
1054                                              sal_False if the Any is empty or the string is empty */
1055     sal_Bool                    getDouble(
1056                                     double& rfResult,
1057                                     const CSS::uno::Reference< CSS::beans::XPropertySet >& xPropSet,
1058                                     const CSS::uno::Any& rAny )
1059                                 throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
1060 
1061                                 /** Converts an Any to double (with initialization).
1062                                     The Any can be empty or contain a double or string.
1063                                     @throws com::sun::star::lang::IllegalArgumentException
1064                                         on other Any types or on invalid strings.
1065                                     @return  the value of the double or string or fDefault if the Any or string is empty */
1066     double                      getDouble(
1067                                     const CSS::uno::Reference< CSS::beans::XPropertySet >& xPropSet,
1068                                     const CSS::uno::Any& rAny,
1069                                     double fDefault )
1070                                 throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
1071 
1072                                 /** Converts an Any to sal_Int32 (with initialization).
1073                                     The Any can be empty or contain a double or string.
1074                                     @throws com::sun::star::lang::IllegalArgumentException
1075                                         on other Any types or on invalid values or strings.
1076                                     @return  sal_True if the Any contains a double or a non-empty valid string,
1077                                              sal_False if the Any is empty or the string is empty */
1078     sal_Bool                    getInt32(
1079                                     sal_Int32& rnResult,
1080                                     const CSS::uno::Reference< CSS::beans::XPropertySet >& xPropSet,
1081                                     const CSS::uno::Any& rAny )
1082                                 throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
1083 
1084                                 /** Converts an Any to sal_Int32 (with initialization).
1085                                     The Any can be empty or contain a double or string.
1086                                     @throws com::sun::star::lang::IllegalArgumentException
1087                                         on other Any types or on invalid values or strings.
1088                                     @return  the truncated value of the double or string or nDefault if the Any or string is empty */
1089     sal_Int32                   getInt32(
1090                                     const CSS::uno::Reference< CSS::beans::XPropertySet >& xPropSet,
1091                                     const CSS::uno::Any& rAny,
1092                                     sal_Int32 nDefault )
1093                                 throw( CSS::uno::RuntimeException, CSS::lang::IllegalArgumentException );
1094 };
1095 
1096 
1097 //-----------------------------------------------------------------------------
1098 
1099 
1100 #endif
1101 
1102