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