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