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