1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "analysis.hxx" 25 26 #include <cppuhelper/factory.hxx> 27 #include <osl/diagnose.h> 28 #include <rtl/ustrbuf.hxx> 29 #include <rtl/math.hxx> 30 #include <rtl/random.h> 31 #include <string.h> 32 33 #include <tools/resmgr.hxx> 34 #include <tools/rcid.h> 35 #include "analysis.hrc" 36 #include "bessel.hxx" 37 38 #define ADDIN_SERVICE "com.sun.star.sheet.AddIn" 39 #define MY_SERVICE "com.sun.star.sheet.addin.Analysis" 40 #define MY_IMPLNAME "com.sun.star.sheet.addin.AnalysisImpl" 41 42 using namespace ::rtl; 43 using namespace ::com::sun::star; 44 45 //------------------------------------------------------------------ 46 // 47 // entry points for service registration / instantiation 48 // 49 //------------------------------------------------------------------ 50 51 extern "C" { 52 53 54 void SAL_CALL component_getImplementationEnvironment( const sal_Char** ppEnvTypeName, uno_Environment** /*ppEnv*/ ) 55 { 56 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 57 } 58 59 void* SAL_CALL component_getFactory( const sal_Char* pImplName, void* pServiceManager, void* /*pRegistryKey*/ ) 60 { 61 void* pRet = 0; 62 63 if( pServiceManager && STRING::createFromAscii( pImplName ) == AnalysisAddIn::getImplementationName_Static() ) 64 { 65 REF( lang::XSingleServiceFactory ) xFactory( cppu::createOneInstanceFactory( 66 reinterpret_cast< lang::XMultiServiceFactory* >( pServiceManager ), 67 AnalysisAddIn::getImplementationName_Static(), 68 AnalysisAddIn_CreateInstance, 69 AnalysisAddIn::getSupportedServiceNames_Static() ) ); 70 71 if( xFactory.is() ) 72 { 73 xFactory->acquire(); 74 pRet = xFactory.get(); 75 } 76 } 77 78 return pRet; 79 } 80 81 82 } // extern C 83 84 85 86 87 //------------------------------------------------------------------------ 88 // 89 // "normal" service implementation 90 // 91 //------------------------------------------------------------------------ 92 93 94 ResMgr& AnalysisAddIn::GetResMgr( void ) THROWDEF_RTE 95 { 96 if( !pResMgr ) 97 { 98 InitData(); // try to get resource manager 99 100 if( !pResMgr ) 101 THROW_RTE; 102 } 103 104 return *pResMgr; 105 } 106 107 108 STRING AnalysisAddIn::GetDisplFuncStr( sal_uInt16 nFuncNum ) THROWDEF_RTE 109 { 110 return String( AnalysisRscStrLoader( RID_ANALYSIS_FUNCTION_NAMES, nFuncNum, GetResMgr() ).GetString() ); 111 } 112 113 114 class AnalysisResourcePublisher : public Resource 115 { 116 public: 117 AnalysisResourcePublisher( const AnalysisResId& rId ) : Resource( rId ) {} 118 sal_Bool IsAvailableRes( const ResId& rId ) const { return Resource::IsAvailableRes( rId ); } 119 void FreeResource() { Resource::FreeResource(); } 120 }; 121 122 123 class AnalysisFuncRes : public Resource 124 { 125 public: 126 AnalysisFuncRes( ResId& rRes, ResMgr& rResMgr, sal_uInt16 nInd, STRING& rRet ); 127 }; 128 129 130 AnalysisFuncRes::AnalysisFuncRes( ResId& rRes, ResMgr& rResMgr, sal_uInt16 nInd, STRING& rRet ) : Resource( rRes ) 131 { 132 rRet = String( AnalysisResId( nInd, rResMgr ) ); 133 134 FreeResource(); 135 } 136 137 138 STRING AnalysisAddIn::GetFuncDescrStr( sal_uInt16 nResId, sal_uInt16 nStrIndex ) THROWDEF_RTE 139 { 140 STRING aRet; 141 AnalysisResourcePublisher aResPubl( AnalysisResId( RID_ANALYSIS_FUNCTION_DESCRIPTIONS, GetResMgr() ) ); 142 AnalysisResId aRes( nResId, GetResMgr() ); 143 aRes.SetRT( RSC_RESOURCE ); 144 if( aResPubl.IsAvailableRes( aRes ) ) 145 { 146 AnalysisFuncRes aSubRes( aRes, GetResMgr(), nStrIndex, aRet ); 147 } 148 149 aResPubl.FreeResource(); 150 151 return aRet; 152 } 153 154 155 void AnalysisAddIn::InitData( void ) 156 { 157 if( pResMgr ) 158 delete pResMgr; 159 160 OString aModName( "analysis" ); 161 pResMgr = ResMgr::CreateResMgr( ( const sal_Char* ) aModName, 162 aFuncLoc ); 163 164 if( pFD ) 165 delete pFD; 166 167 if( pResMgr ) 168 pFD = new FuncDataList( *pResMgr ); 169 else 170 pFD = NULL; 171 172 if( pDefLocales ) 173 { 174 delete pDefLocales; 175 pDefLocales = NULL; 176 } 177 } 178 179 180 AnalysisAddIn::AnalysisAddIn( const uno::Reference< lang::XMultiServiceFactory >& xServiceFact ) : 181 pDefLocales( NULL ), 182 pFD( NULL ), 183 pFactDoubles( NULL ), 184 pCDL( NULL ), 185 pResMgr( NULL ), 186 aAnyConv( xServiceFact ) 187 { 188 } 189 190 191 AnalysisAddIn::~AnalysisAddIn() 192 { 193 if( pFD ) 194 delete pFD; 195 196 if( pFactDoubles ) 197 delete[] pFactDoubles; 198 199 if( pCDL ) 200 delete pCDL; 201 202 // if( pResMgr ) no delete, because _all_ resource managers are deleted _before_ this dtor is called 203 // delete pResMgr; 204 205 if( pDefLocales ) 206 delete[] pDefLocales; 207 } 208 209 210 sal_Int32 AnalysisAddIn::getDateMode( 211 const uno::Reference< beans::XPropertySet >& xPropSet, 212 const uno::Any& rAny ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 213 { 214 sal_Int32 nMode = aAnyConv.getInt32( xPropSet, rAny, 0 ); 215 if( (nMode < 0) || (nMode > 4) ) 216 throw lang::IllegalArgumentException(); 217 return nMode; 218 } 219 220 221 222 //----------------------------------------------------------------------------- 223 224 225 #define MAXFACTDOUBLE 300 226 227 double AnalysisAddIn::FactDouble( sal_Int32 nNum ) THROWDEF_RTE_IAE 228 { 229 if( nNum < 0 || nNum > MAXFACTDOUBLE ) 230 THROW_IAE; 231 232 if( !pFactDoubles ) 233 { 234 pFactDoubles = new double[ MAXFACTDOUBLE + 1 ]; 235 236 pFactDoubles[ 0 ] = 1.0; // by default 237 238 double fOdd = 1.0; 239 double fEven = 2.0; 240 241 pFactDoubles[ 1 ] = fOdd; 242 pFactDoubles[ 2 ] = fEven; 243 244 sal_Bool bOdd = sal_True; 245 246 for( sal_uInt16 nCnt = 3 ; nCnt <= MAXFACTDOUBLE ; nCnt++ ) 247 { 248 if( bOdd ) 249 { 250 fOdd *= nCnt; 251 pFactDoubles[ nCnt ] = fOdd; 252 } 253 else 254 { 255 fEven *= nCnt; 256 pFactDoubles[ nCnt ] = fEven; 257 } 258 259 bOdd = !bOdd; 260 261 } 262 } 263 264 return pFactDoubles[ nNum ]; 265 } 266 267 268 STRING AnalysisAddIn::getImplementationName_Static() 269 { 270 return STRFROMASCII( MY_IMPLNAME ); 271 } 272 273 274 SEQ( STRING ) AnalysisAddIn::getSupportedServiceNames_Static() 275 { 276 SEQ( STRING ) aRet(2); 277 STRING* pArray = aRet.getArray(); 278 pArray[0] = STRFROMASCII( ADDIN_SERVICE ); 279 pArray[1] = STRFROMASCII( MY_SERVICE ); 280 return aRet; 281 } 282 283 284 REF( uno::XInterface ) SAL_CALL AnalysisAddIn_CreateInstance( 285 const uno::Reference< lang::XMultiServiceFactory >& xServiceFact ) 286 { 287 static uno::Reference< uno::XInterface > xInst = (cppu::OWeakObject*) new AnalysisAddIn( xServiceFact ); 288 return xInst; 289 } 290 291 292 // XServiceName 293 294 STRING SAL_CALL AnalysisAddIn::getServiceName() THROWDEF_RTE 295 { 296 // name of specific AddIn service 297 return STRFROMASCII( MY_SERVICE ); 298 } 299 300 301 // XServiceInfo 302 303 STRING SAL_CALL AnalysisAddIn::getImplementationName() THROWDEF_RTE 304 { 305 return getImplementationName_Static(); 306 } 307 308 309 sal_Bool SAL_CALL AnalysisAddIn::supportsService( const STRING& aName ) THROWDEF_RTE 310 { 311 return aName.compareToAscii( ADDIN_SERVICE ) == 0 || aName.compareToAscii( MY_SERVICE ) == 0; 312 } 313 314 315 SEQ( STRING ) SAL_CALL AnalysisAddIn::getSupportedServiceNames() THROWDEF_RTE 316 { 317 return getSupportedServiceNames_Static(); 318 } 319 320 321 // XLocalizable 322 323 void SAL_CALL AnalysisAddIn::setLocale( const lang::Locale& eLocale ) THROWDEF_RTE 324 { 325 aFuncLoc = eLocale; 326 327 InitData(); // change of locale invalidates resources! 328 } 329 330 lang::Locale SAL_CALL AnalysisAddIn::getLocale() THROWDEF_RTE 331 { 332 return aFuncLoc; 333 } 334 335 336 // XAddIn 337 338 STRING SAL_CALL AnalysisAddIn::getProgrammaticFuntionName( const STRING& ) THROWDEF_RTE 339 { 340 // not used by calc 341 // (but should be implemented for other uses of the AddIn service) 342 343 return STRING(); 344 } 345 346 347 STRING SAL_CALL AnalysisAddIn::getDisplayFunctionName( const STRING& aProgrammaticName ) THROWDEF_RTE 348 { 349 STRING aRet; 350 351 const FuncData* p = pFD->Get( aProgrammaticName ); 352 if( p ) 353 { 354 aRet = GetDisplFuncStr( p->GetUINameID() ); 355 if( p->IsDouble() ) 356 aRet += STRFROMANSI( "_ADD" ); 357 } 358 else 359 { 360 aRet = STRFROMANSI( "UNKNOWNFUNC_" ); 361 aRet += aProgrammaticName; 362 } 363 364 return aRet; 365 } 366 367 368 STRING SAL_CALL AnalysisAddIn::getFunctionDescription( const STRING& aProgrammaticName ) THROWDEF_RTE 369 { 370 STRING aRet; 371 372 const FuncData* p = pFD->Get( aProgrammaticName ); 373 if( p ) 374 aRet = GetFuncDescrStr( p->GetDescrID(), 1 ); 375 376 return aRet; 377 } 378 379 380 STRING SAL_CALL AnalysisAddIn::getDisplayArgumentName( const STRING& aName, sal_Int32 nArg ) THROWDEF_RTE 381 { 382 STRING aRet; 383 384 const FuncData* p = pFD->Get( aName ); 385 if( p && nArg <= 0xFFFF ) 386 { 387 sal_uInt16 nStr = p->GetStrIndex( sal_uInt16( nArg ) ); 388 if( nStr /*&& nStr < 4*/ ) 389 aRet = GetFuncDescrStr( p->GetDescrID(), nStr ); 390 else 391 aRet = STRFROMANSI( "internal" ); 392 } 393 394 return aRet; 395 } 396 397 398 STRING SAL_CALL AnalysisAddIn::getArgumentDescription( const STRING& aName, sal_Int32 nArg ) THROWDEF_RTE 399 { 400 STRING aRet; 401 402 const FuncData* p = pFD->Get( aName ); 403 if( p && nArg <= 0xFFFF ) 404 { 405 sal_uInt16 nStr = p->GetStrIndex( sal_uInt16( nArg ) ); 406 if( nStr /*&& nStr < 4*/ ) 407 aRet = GetFuncDescrStr( p->GetDescrID(), nStr + 1 ); 408 else 409 aRet = STRFROMANSI( "for internal use only" ); 410 } 411 412 return aRet; 413 } 414 415 416 static const char* pDefCatName = "Add-In"; 417 418 419 STRING SAL_CALL AnalysisAddIn::getProgrammaticCategoryName( const STRING& aName ) THROWDEF_RTE 420 { 421 // return non-translated strings 422 // return STRFROMASCII( "Add-In" ); 423 const FuncData* p = pFD->Get( aName ); 424 STRING aRet; 425 if( p ) 426 { 427 const sal_Char* pStr; 428 429 switch( p->GetCategory() ) 430 { 431 case FDCat_DateTime: pStr = "Date&Time"; break; 432 case FDCat_Finance: pStr = "Financial"; break; 433 case FDCat_Inf: pStr = "Information"; break; 434 case FDCat_Math: pStr = "Mathematical"; break; 435 case FDCat_Tech: pStr = "Technical"; break; 436 default: 437 pStr = pDefCatName; break; 438 } 439 440 aRet = STRFROMASCII( pStr ); 441 } 442 else 443 aRet = STRFROMASCII( pDefCatName ); 444 445 return aRet; 446 } 447 448 449 STRING SAL_CALL AnalysisAddIn::getDisplayCategoryName( const STRING& aProgrammaticFunctionName ) THROWDEF_RTE 450 { 451 // return translated strings, not used for predefined categories 452 // return STRFROMASCII( "Add-In" ); 453 const FuncData* p = pFD->Get( aProgrammaticFunctionName ); 454 STRING aRet; 455 if( p ) 456 { 457 const sal_Char* pStr; 458 459 switch( p->GetCategory() ) 460 { 461 case FDCat_DateTime: pStr = "Date&Time"; break; 462 case FDCat_Finance: pStr = "Financial"; break; 463 case FDCat_Inf: pStr = "Information"; break; 464 case FDCat_Math: pStr = "Mathematical"; break; 465 case FDCat_Tech: pStr = "Technical"; break; 466 default: 467 pStr = pDefCatName; break; 468 } 469 470 aRet = STRFROMASCII( pStr ); 471 } 472 else 473 aRet = STRFROMASCII( pDefCatName ); 474 475 return aRet; 476 } 477 478 479 static const sal_Char* pLang[] = { "de", "en" }; 480 static const sal_Char* pCoun[] = { "DE", "US" }; 481 static const sal_uInt32 nNumOfLoc = sizeof( pLang ) / sizeof( sal_Char* ); 482 483 484 void AnalysisAddIn::InitDefLocales( void ) 485 { 486 pDefLocales = new CSS::lang::Locale[ nNumOfLoc ]; 487 488 for( sal_uInt32 n = 0 ; n < nNumOfLoc ; n++ ) 489 { 490 pDefLocales[ n ].Language = STRING::createFromAscii( pLang[ n ] ); 491 pDefLocales[ n ].Country = STRING::createFromAscii( pCoun[ n ] ); 492 } 493 } 494 495 496 inline const CSS::lang::Locale& AnalysisAddIn::GetLocale( sal_uInt32 nInd ) 497 { 498 if( !pDefLocales ) 499 InitDefLocales(); 500 501 if( nInd < sizeof( pLang ) ) 502 return pDefLocales[ nInd ]; 503 else 504 return aFuncLoc; 505 } 506 507 508 SEQofLocName SAL_CALL AnalysisAddIn::getCompatibilityNames( const STRING& aProgrammaticName ) THROWDEF_RTE 509 { 510 const FuncData* p = pFD->Get( aProgrammaticName ); 511 512 if( !p ) 513 return SEQofLocName( 0 ); 514 515 const StringList& r = p->GetCompNameList(); 516 sal_uInt32 nCount = r.Count(); 517 518 SEQofLocName aRet( nCount ); 519 520 CSS::sheet::LocalizedName* pArray = aRet.getArray(); 521 522 for( sal_uInt32 n = 0 ; n < nCount ; n++ ) 523 { 524 pArray[ n ] = CSS::sheet::LocalizedName( GetLocale( n ), *r.Get( n ) ); 525 } 526 527 return aRet; 528 } 529 530 531 // XAnalysis 532 533 /*double SAL_CALL AnalysisAddIn::get_Test( constREFXPS&, 534 sal_Int32 nMode, double f1, double f2, double f3 ) THROWDEF_RTE 535 { 536 return _Test( nMode, f1, f2, f3 ); 537 }*/ 538 539 540 /** 541 * Workday 542 */ 543 544 sal_Int32 SAL_CALL AnalysisAddIn::getWorkday( constREFXPS& xOptions, 545 sal_Int32 nDate, sal_Int32 nDays, const ANY& aHDay ) THROWDEF_RTE_IAE 546 { 547 if( !nDays ) 548 return nDate; 549 550 sal_Int32 nNullDate = GetNullDate( xOptions ); 551 552 SortedIndividualInt32List aSrtLst; 553 554 aSrtLst.InsertHolidayList( aAnyConv, xOptions, aHDay, nNullDate, sal_False ); 555 556 sal_Int32 nActDate = nDate + nNullDate; 557 558 if( nDays > 0 ) 559 { 560 if( GetDayOfWeek( nActDate ) == 5 ) 561 // when starting on Saturday, assuming we're starting on Sunday to get the jump over the weekend 562 nActDate++; 563 564 while( nDays ) 565 { 566 nActDate++; 567 568 if( GetDayOfWeek( nActDate ) < 5 ) 569 { 570 if( !aSrtLst.Find( nActDate ) ) 571 nDays--; 572 } 573 else 574 nActDate++; // jump over weekend 575 } 576 } 577 else 578 { 579 if( GetDayOfWeek( nActDate ) == 6 ) 580 // when starting on Sunday, assuming we're starting on Saturday to get the jump over the weekend 581 nActDate--; 582 583 while( nDays ) 584 { 585 nActDate--; 586 587 if( GetDayOfWeek( nActDate ) < 5 ) 588 { 589 if( !aSrtLst.Find( nActDate ) ) 590 nDays++; 591 } 592 else 593 nActDate--; // jump over weekend 594 } 595 } 596 597 return nActDate - nNullDate; 598 } 599 600 601 /** 602 * Yearfrac 603 */ 604 605 double SAL_CALL AnalysisAddIn::getYearfrac( constREFXPS& xOpt, 606 sal_Int32 nStartDate, sal_Int32 nEndDate, const ANY& rMode ) THROWDEF_RTE_IAE 607 { 608 double fRet = GetYearFrac( xOpt, nStartDate, nEndDate, getDateMode( xOpt, rMode ) ); 609 RETURN_FINITE( fRet ); 610 } 611 612 613 sal_Int32 SAL_CALL AnalysisAddIn::getEdate( constREFXPS& xOpt, sal_Int32 nStartDate, sal_Int32 nMonths ) THROWDEF_RTE_IAE 614 { 615 sal_Int32 nNullDate = GetNullDate( xOpt ); 616 ScaDate aDate( nNullDate, nStartDate, 5 ); 617 aDate.addMonths( nMonths ); 618 return aDate.getDate( nNullDate ); 619 } 620 621 622 sal_Int32 SAL_CALL AnalysisAddIn::getWeeknum( constREFXPS& xOpt, sal_Int32 nDate, sal_Int32 nMode ) THROWDEF_RTE_IAE 623 { 624 nDate += GetNullDate( xOpt ); 625 626 sal_uInt16 nDay, nMonth, nYear; 627 DaysToDate( nDate, nDay, nMonth, nYear ); 628 629 sal_Int32 nFirstInYear = DateToDays( 1, 1, nYear ); 630 sal_uInt16 nFirstDayInYear = GetDayOfWeek( nFirstInYear ); 631 632 return ( nDate - nFirstInYear + ( ( nMode == 1 )? ( nFirstDayInYear + 1 ) % 7 : nFirstDayInYear ) ) / 7 + 1; 633 } 634 635 636 sal_Int32 SAL_CALL AnalysisAddIn::getEomonth( constREFXPS& xOpt, sal_Int32 nDate, sal_Int32 nMonths ) THROWDEF_RTE_IAE 637 { 638 sal_Int32 nNullDate = GetNullDate( xOpt ); 639 nDate += nNullDate; 640 sal_uInt16 nDay, nMonth, nYear; 641 DaysToDate( nDate, nDay, nMonth, nYear ); 642 643 sal_Int32 nNewMonth = nMonth + nMonths; 644 645 if( nNewMonth > 12 ) 646 { 647 nYear = sal::static_int_cast<sal_uInt16>( nYear + ( nNewMonth / 12 ) ); 648 nNewMonth %= 12; 649 } 650 else if( nNewMonth < 1 ) 651 { 652 nNewMonth = -nNewMonth; 653 nYear = sal::static_int_cast<sal_uInt16>( nYear - ( nNewMonth / 12 ) ); 654 nYear--; 655 nNewMonth %= 12; 656 nNewMonth = 12 - nNewMonth; 657 } 658 659 return DateToDays( DaysInMonth( sal_uInt16( nNewMonth ), nYear ), sal_uInt16( nNewMonth ), nYear ) - nNullDate; 660 } 661 662 663 sal_Int32 SAL_CALL AnalysisAddIn::getNetworkdays( constREFXPS& xOpt, 664 sal_Int32 nStartDate, sal_Int32 nEndDate, const ANY& aHDay ) THROWDEF_RTE_IAE 665 { 666 sal_Int32 nNullDate = GetNullDate( xOpt ); 667 668 SortedIndividualInt32List aSrtLst; 669 670 aSrtLst.InsertHolidayList( aAnyConv, xOpt, aHDay, nNullDate, sal_False ); 671 672 sal_Int32 nActDate = nStartDate + nNullDate; 673 sal_Int32 nStopDate = nEndDate + nNullDate; 674 sal_Int32 nCnt = 0; 675 676 if( nActDate <= nStopDate ) 677 { 678 while( nActDate <= nStopDate ) 679 { 680 if( GetDayOfWeek( nActDate ) < 5 && !aSrtLst.Find( nActDate ) ) 681 nCnt++; 682 683 nActDate++; 684 } 685 } 686 else 687 { 688 while( nActDate >= nStopDate ) 689 { 690 if( GetDayOfWeek( nActDate ) < 5 && !aSrtLst.Find( nActDate ) ) 691 nCnt--; 692 693 nActDate--; 694 } 695 } 696 697 return nCnt; 698 } 699 700 701 sal_Int32 SAL_CALL AnalysisAddIn::getIseven( sal_Int32 nVal ) THROWDEF_RTE_IAE 702 { 703 return ( nVal & 0x00000001 )? 0 : 1; 704 } 705 706 707 sal_Int32 SAL_CALL AnalysisAddIn::getIsodd( sal_Int32 nVal ) THROWDEF_RTE_IAE 708 { 709 return ( nVal & 0x00000001 )? 1 : 0; 710 } 711 712 double SAL_CALL 713 AnalysisAddIn::getMultinomial( constREFXPS& xOpt, const SEQSEQ( sal_Int32 )& aVLst, 714 const SEQ( uno::Any )& aOptVLst ) THROWDEF_RTE_IAE 715 { 716 ScaDoubleListGE0 aValList; 717 718 aValList.Append( aVLst ); 719 aValList.Append( aAnyConv, xOpt, aOptVLst ); 720 721 if( aValList.Count() == 0 ) 722 return 0.0; 723 724 sal_Int32 nZ = 0; 725 double fN = 1.0; 726 727 for( const double *p = aValList.First(); p; p = aValList.Next() ) 728 { 729 double fInt = (*p >= 0.0) ? rtl::math::approxFloor( *p ) : rtl::math::approxCeil( *p ); 730 if ( fInt < 0.0 || fInt > 170.0 ) 731 THROW_IAE; 732 sal_Int32 n = static_cast< sal_Int32 >( fInt ); 733 if( n > 0 ) 734 { 735 nZ += n; 736 fN *= Fak( n ); 737 } 738 } 739 740 if( nZ > 170 ) 741 THROW_IAE; 742 743 double fRet = Fak( nZ ) / fN; 744 RETURN_FINITE( fRet ); 745 } 746 747 748 double SAL_CALL AnalysisAddIn::getSeriessum( double fX, double fN, double fM, const SEQSEQ( double )& aCoeffList ) THROWDEF_RTE_IAE 749 { 750 double fRet = 0.0; 751 752 // #i32269# 0^0 is undefined, Excel returns #NUM! error 753 if( fX == 0.0 && fN == 0 ) 754 THROW_RTE; 755 756 if( fX != 0.0 ) 757 { 758 sal_Int32 n1, n2; 759 sal_Int32 nE1 = aCoeffList.getLength(); 760 sal_Int32 nE2; 761 //sal_Int32 nZ = 0; 762 763 for( n1 = 0 ; n1 < nE1 ; n1++ ) 764 { 765 const SEQ( double )& rList = aCoeffList[ n1 ]; 766 nE2 = rList.getLength(); 767 const double* pList = rList.getConstArray(); 768 769 for( n2 = 0 ; n2 < nE2 ; n2++ ) 770 { 771 fRet += pList[ n2 ] * pow( fX, fN ); 772 773 fN += fM; 774 } 775 } 776 } 777 778 RETURN_FINITE( fRet ); 779 } 780 781 782 double SAL_CALL AnalysisAddIn::getQuotient( double fNum, double fDenom ) THROWDEF_RTE_IAE 783 { 784 double fRet; 785 if( (fNum < 0) != (fDenom < 0) ) 786 fRet = ::rtl::math::approxCeil( fNum / fDenom ); 787 else 788 fRet = ::rtl::math::approxFloor( fNum / fDenom ); 789 RETURN_FINITE( fRet ); 790 } 791 792 793 double SAL_CALL AnalysisAddIn::getMround( double fNum, double fMult ) THROWDEF_RTE_IAE 794 { 795 if( fMult == 0.0 ) 796 return fMult; 797 798 double fRet = fMult * ::rtl::math::round( fNum / fMult ); 799 RETURN_FINITE( fRet ); 800 } 801 802 803 double SAL_CALL AnalysisAddIn::getSqrtpi( double fNum ) THROWDEF_RTE_IAE 804 { 805 double fRet = sqrt( fNum * PI ); 806 RETURN_FINITE( fRet ); 807 } 808 809 810 double SAL_CALL AnalysisAddIn::getRandbetween( double fMin, double fMax ) THROWDEF_RTE_IAE 811 { 812 static sal_Int32 nScRandomIx = 0, nScRandomIy = 0, nScRandomIz = 0, nScRandomIt = 0; 813 static rtlRandomPool aPool = rtl_random_createPool(); 814 double fScRandomW; 815 816 fMin = ::rtl::math::round( fMin, 0, rtl_math_RoundingMode_Up ); 817 fMax = ::rtl::math::round( fMax, 0, rtl_math_RoundingMode_Up ); 818 if( fMin > fMax ) 819 THROW_IAE; 820 821 // Seeding for the PRNG: should be good enough but we 822 // monitor the values to keep things under control. 823 if (nScRandomIx <= 0) 824 rtl_random_getBytes(aPool, &nScRandomIx, sizeof(nScRandomIx)); 825 if (nScRandomIy <= 0) 826 rtl_random_getBytes(aPool, &nScRandomIy, sizeof(nScRandomIy)); 827 if (nScRandomIz <= 0) 828 rtl_random_getBytes(aPool, &nScRandomIz, sizeof(nScRandomIz)); 829 if (nScRandomIt <= 0) 830 rtl_random_getBytes(aPool, &nScRandomIt, sizeof(nScRandomIt)); 831 832 // Basically unmodified algorithm from 833 // Wichman and Hill, "Generating good pseudo-random numbers", 834 // December 5, 2005. 835 836 nScRandomIx = 11600L * (nScRandomIx % 185127L) - 10379L * (nScRandomIx / 185127L); 837 nScRandomIy = 47003L * (nScRandomIy % 45688L) - 10479L * (nScRandomIy / 45688L); 838 nScRandomIz = 23000L * (nScRandomIz % 93368L) - 19423L * (nScRandomIz / 93368L); 839 nScRandomIt = 33000L * (nScRandomIt % 65075L) - 8123L * (nScRandomIt / 65075L); 840 if (nScRandomIx < 0) 841 nScRandomIx += 2147483579L; 842 if (nScRandomIy < 0) 843 nScRandomIy += 2147483543L; 844 if (nScRandomIz < 0) 845 nScRandomIz += 2147483123L; 846 if (nScRandomIt < 0) 847 nScRandomIt += 2147483123L; 848 849 fScRandomW = (double)nScRandomIx*0.0000000004656613022670 + 850 (double)nScRandomIy*0.0000000004656613100760 + 851 (double)nScRandomIz*0.0000000004656613360968 + 852 (double)nScRandomIt*0.0000000004656614011490; 853 854 855 // fMax -> range 856 double fRet = fMax - fMin + 1.0; 857 fRet *= fScRandomW - (sal_Int32)fScRandomW ; 858 fRet += fMin; 859 fRet = floor( fRet ); // simple floor is sufficient here 860 RETURN_FINITE( fRet ); 861 } 862 863 864 double SAL_CALL AnalysisAddIn::getGcd( constREFXPS& xOpt, const SEQSEQ( double )& aVLst, const SEQ( uno::Any )& aOptVLst ) THROWDEF_RTE_IAE 865 { 866 ScaDoubleListGT0 aValList; 867 868 aValList.Append( aVLst ); 869 aValList.Append( aAnyConv, xOpt, aOptVLst ); 870 871 if( aValList.Count() == 0 ) 872 return 0.0; 873 874 const double* p = aValList.First(); 875 double f = *p; 876 877 p = aValList.Next(); 878 879 while( p ) 880 { 881 f = GetGcd( *p, f ); 882 p = aValList.Next(); 883 } 884 885 RETURN_FINITE( f ); 886 } 887 888 889 double SAL_CALL AnalysisAddIn::getLcm( constREFXPS& xOpt, const SEQSEQ( double )& aVLst, const SEQ( uno::Any )& aOptVLst ) THROWDEF_RTE_IAE 890 { 891 ScaDoubleListGE0 aValList; 892 893 aValList.Append( aVLst ); 894 aValList.Append( aAnyConv, xOpt, aOptVLst ); 895 896 if( aValList.Count() == 0 ) 897 return 0.0; 898 899 const double* p = aValList.First(); 900 double f = *p; 901 902 if( f == 0.0 ) 903 return f; 904 905 p = aValList.Next(); 906 907 while( p ) 908 { 909 double fTmp = *p; 910 if( f == 0.0 ) 911 return f; 912 else 913 f = fTmp * f / GetGcd( fTmp, f ); 914 p = aValList.Next(); 915 } 916 917 RETURN_FINITE( f ); 918 } 919 920 921 double SAL_CALL AnalysisAddIn::getBesseli( double fNum, sal_Int32 nOrder ) THROWDEF_RTE_IAE_NCE 922 { 923 double fRet = sca::analysis::BesselI( fNum, nOrder ); 924 RETURN_FINITE( fRet ); 925 } 926 927 928 double SAL_CALL AnalysisAddIn::getBesselj( double fNum, sal_Int32 nOrder ) THROWDEF_RTE_IAE_NCE 929 { 930 double fRet = sca::analysis::BesselJ( fNum, nOrder ); 931 RETURN_FINITE( fRet ); 932 } 933 934 935 double SAL_CALL AnalysisAddIn::getBesselk( double fNum, sal_Int32 nOrder ) THROWDEF_RTE_IAE_NCE 936 { 937 if( nOrder < 0 || fNum <= 0.0 ) 938 THROW_IAE; 939 940 double fRet = sca::analysis::BesselK( fNum, nOrder ); 941 RETURN_FINITE( fRet ); 942 } 943 944 945 double SAL_CALL AnalysisAddIn::getBessely( double fNum, sal_Int32 nOrder ) THROWDEF_RTE_IAE_NCE 946 { 947 if( nOrder < 0 || fNum <= 0.0 ) 948 THROW_IAE; 949 950 // return yn( nOrder, fNum ); 951 double fRet = sca::analysis::BesselY( fNum, nOrder ); 952 RETURN_FINITE( fRet ); 953 } 954 955 956 const double SCA_MAX2 = 511.0; // min. val for binary numbers (9 bits + sign) 957 const double SCA_MIN2 = -SCA_MAX2-1.0; // min. val for binary numbers (9 bits + sign) 958 const double SCA_MAX8 = 536870911.0; // max. val for octal numbers (29 bits + sign) 959 const double SCA_MIN8 = -SCA_MAX8-1.0; // min. val for octal numbers (29 bits + sign) 960 const double SCA_MAX16 = 549755813888.0; // max. val for hexadecimal numbers (39 bits + sign) 961 const double SCA_MIN16 = -SCA_MAX16-1.0; // min. val for hexadecimal numbers (39 bits + sign) 962 const sal_Int32 SCA_MAXPLACES = 10; // max. number of places 963 964 965 STRING SAL_CALL AnalysisAddIn::getBin2Oct( constREFXPS& xOpt, const STRING& aNum, const ANY& rPlaces ) THROWDEF_RTE_IAE 966 { 967 double fVal = ConvertToDec( aNum, 2, SCA_MAXPLACES ); 968 sal_Int32 nPlaces = 0; 969 sal_Bool bUsePlaces = aAnyConv.getInt32( nPlaces, xOpt, rPlaces ); 970 return ConvertFromDec( fVal, SCA_MIN8, SCA_MAX8, 8, nPlaces, SCA_MAXPLACES, bUsePlaces ); 971 } 972 973 974 double SAL_CALL AnalysisAddIn::getBin2Dec( const STRING& aNum ) THROWDEF_RTE_IAE 975 { 976 double fRet = ConvertToDec( aNum, 2, SCA_MAXPLACES ); 977 RETURN_FINITE( fRet ); 978 } 979 980 981 STRING SAL_CALL AnalysisAddIn::getBin2Hex( constREFXPS& xOpt, const STRING& aNum, const ANY& rPlaces ) THROWDEF_RTE_IAE 982 { 983 double fVal = ConvertToDec( aNum, 2, SCA_MAXPLACES ); 984 sal_Int32 nPlaces = 0; 985 sal_Bool bUsePlaces = aAnyConv.getInt32( nPlaces, xOpt, rPlaces ); 986 return ConvertFromDec( fVal, SCA_MIN16, SCA_MAX16, 16, nPlaces, SCA_MAXPLACES, bUsePlaces ); 987 } 988 989 990 STRING SAL_CALL AnalysisAddIn::getOct2Bin( constREFXPS& xOpt, const STRING& aNum, const ANY& rPlaces ) THROWDEF_RTE_IAE 991 { 992 double fVal = ConvertToDec( aNum, 8, SCA_MAXPLACES ); 993 sal_Int32 nPlaces = 0; 994 sal_Bool bUsePlaces = aAnyConv.getInt32( nPlaces, xOpt, rPlaces ); 995 return ConvertFromDec( fVal, SCA_MIN2, SCA_MAX2, 2, nPlaces, SCA_MAXPLACES, bUsePlaces ); 996 } 997 998 999 double SAL_CALL AnalysisAddIn::getOct2Dec( const STRING& aNum ) THROWDEF_RTE_IAE 1000 { 1001 double fRet = ConvertToDec( aNum, 8, SCA_MAXPLACES ); 1002 RETURN_FINITE( fRet ); 1003 } 1004 1005 1006 STRING SAL_CALL AnalysisAddIn::getOct2Hex( constREFXPS& xOpt, const STRING& aNum, const ANY& rPlaces ) THROWDEF_RTE_IAE 1007 { 1008 double fVal = ConvertToDec( aNum, 8, SCA_MAXPLACES ); 1009 sal_Int32 nPlaces = 0; 1010 sal_Bool bUsePlaces = aAnyConv.getInt32( nPlaces, xOpt, rPlaces ); 1011 return ConvertFromDec( fVal, SCA_MIN16, SCA_MAX16, 16, nPlaces, SCA_MAXPLACES, bUsePlaces ); 1012 } 1013 1014 1015 STRING SAL_CALL AnalysisAddIn::getDec2Bin( constREFXPS& xOpt, sal_Int32 nNum, const ANY& rPlaces ) THROWDEF_RTE_IAE 1016 { 1017 sal_Int32 nPlaces = 0; 1018 sal_Bool bUsePlaces = aAnyConv.getInt32( nPlaces, xOpt, rPlaces ); 1019 return ConvertFromDec( nNum, SCA_MIN2, SCA_MAX2, 2, nPlaces, SCA_MAXPLACES, bUsePlaces ); 1020 } 1021 1022 1023 STRING SAL_CALL AnalysisAddIn::getDec2Oct( constREFXPS& xOpt, sal_Int32 nNum, const ANY& rPlaces ) THROWDEF_RTE_IAE 1024 { 1025 sal_Int32 nPlaces = 0; 1026 sal_Bool bUsePlaces = aAnyConv.getInt32( nPlaces, xOpt, rPlaces ); 1027 return ConvertFromDec( nNum, SCA_MIN8, SCA_MAX8, 8, nPlaces, SCA_MAXPLACES, bUsePlaces ); 1028 } 1029 1030 1031 STRING SAL_CALL AnalysisAddIn::getDec2Hex( constREFXPS& xOpt, double fNum, const ANY& rPlaces ) THROWDEF_RTE_IAE 1032 { 1033 sal_Int32 nPlaces = 0; 1034 sal_Bool bUsePlaces = aAnyConv.getInt32( nPlaces, xOpt, rPlaces ); 1035 return ConvertFromDec( fNum, SCA_MIN16, SCA_MAX16, 16, nPlaces, SCA_MAXPLACES, bUsePlaces ); 1036 } 1037 1038 1039 STRING SAL_CALL AnalysisAddIn::getHex2Bin( constREFXPS& xOpt, const STRING& aNum, const ANY& rPlaces ) THROWDEF_RTE_IAE 1040 { 1041 double fVal = ConvertToDec( aNum, 16, SCA_MAXPLACES ); 1042 sal_Int32 nPlaces = 0; 1043 sal_Bool bUsePlaces = aAnyConv.getInt32( nPlaces, xOpt, rPlaces ); 1044 return ConvertFromDec( fVal, SCA_MIN2, SCA_MAX2, 2, nPlaces, SCA_MAXPLACES, bUsePlaces ); 1045 } 1046 1047 1048 double SAL_CALL AnalysisAddIn::getHex2Dec( const STRING& aNum ) THROWDEF_RTE_IAE 1049 { 1050 double fRet = ConvertToDec( aNum, 16, SCA_MAXPLACES ); 1051 RETURN_FINITE( fRet ); 1052 } 1053 1054 1055 STRING SAL_CALL AnalysisAddIn::getHex2Oct( constREFXPS& xOpt, const STRING& aNum, const ANY& rPlaces ) THROWDEF_RTE_IAE 1056 { 1057 double fVal = ConvertToDec( aNum, 16, SCA_MAXPLACES ); 1058 sal_Int32 nPlaces = 0; 1059 sal_Bool bUsePlaces = aAnyConv.getInt32( nPlaces, xOpt, rPlaces ); 1060 return ConvertFromDec( fVal, SCA_MIN8, SCA_MAX8, 8, nPlaces, SCA_MAXPLACES, bUsePlaces ); 1061 } 1062 1063 1064 sal_Int32 SAL_CALL AnalysisAddIn::getDelta( constREFXPS& xOpt, double fNum1, const ANY& rNum2 ) THROWDEF_RTE_IAE 1065 { 1066 return fNum1 == aAnyConv.getDouble( xOpt, rNum2, 0.0 ); 1067 } 1068 1069 1070 double SAL_CALL AnalysisAddIn::getErf( constREFXPS& xOpt, double fLL, const ANY& rUL ) THROWDEF_RTE_IAE 1071 { 1072 double fUL, fRet; 1073 sal_Bool bContainsValue = aAnyConv.getDouble( fUL, xOpt, rUL ); 1074 1075 fRet = bContainsValue ? (Erf( fUL ) - Erf( fLL )) : Erf( fLL ); 1076 RETURN_FINITE( fRet ); 1077 } 1078 1079 1080 double SAL_CALL AnalysisAddIn::getErfc( double f ) THROWDEF_RTE_IAE 1081 { 1082 double fRet = Erfc( f ); 1083 RETURN_FINITE( fRet ); 1084 } 1085 1086 1087 sal_Int32 SAL_CALL AnalysisAddIn::getGestep( constREFXPS& xOpt, double fNum, const ANY& rStep ) THROWDEF_RTE_IAE 1088 { 1089 return fNum >= aAnyConv.getDouble( xOpt, rStep, 0.0 ); 1090 } 1091 1092 1093 double SAL_CALL AnalysisAddIn::getFactdouble( sal_Int32 nNum ) THROWDEF_RTE_IAE 1094 { 1095 double fRet = FactDouble( nNum ); 1096 RETURN_FINITE( fRet ); 1097 } 1098 1099 1100 double SAL_CALL AnalysisAddIn::getImabs( const STRING& aNum ) THROWDEF_RTE_IAE 1101 { 1102 double fRet = Complex( aNum ).Abs(); 1103 RETURN_FINITE( fRet ); 1104 } 1105 1106 1107 double SAL_CALL AnalysisAddIn::getImaginary( const STRING& aNum ) THROWDEF_RTE_IAE 1108 { 1109 double fRet = Complex( aNum ).Imag(); 1110 RETURN_FINITE( fRet ); 1111 } 1112 1113 1114 STRING SAL_CALL AnalysisAddIn::getImpower( const STRING& aNum, double f ) THROWDEF_RTE_IAE 1115 { 1116 Complex z( aNum ); 1117 1118 z.Power( f ); 1119 1120 return z.GetString(); 1121 } 1122 1123 1124 double SAL_CALL AnalysisAddIn::getImargument( const STRING& aNum ) THROWDEF_RTE_IAE 1125 { 1126 double fRet = Complex( aNum ).Arg(); 1127 RETURN_FINITE( fRet ); 1128 } 1129 1130 1131 STRING SAL_CALL AnalysisAddIn::getImcos( const STRING& aNum ) THROWDEF_RTE_IAE 1132 { 1133 Complex z( aNum ); 1134 1135 z.Cos(); 1136 1137 return z.GetString(); 1138 } 1139 1140 1141 STRING SAL_CALL AnalysisAddIn::getImdiv( const STRING& aDivid, const STRING& aDivis ) THROWDEF_RTE_IAE 1142 { 1143 Complex z( aDivid ); 1144 1145 z.Div( Complex( aDivis ) ); 1146 1147 return z.GetString(); 1148 } 1149 1150 1151 STRING SAL_CALL AnalysisAddIn::getImexp( const STRING& aNum ) THROWDEF_RTE_IAE 1152 { 1153 Complex z( aNum ); 1154 1155 z.Exp(); 1156 1157 return z.GetString(); 1158 } 1159 1160 1161 STRING SAL_CALL AnalysisAddIn::getImconjugate( const STRING& aNum ) THROWDEF_RTE_IAE 1162 { 1163 Complex z( aNum ); 1164 1165 z.Conjugate(); 1166 1167 return z.GetString(); 1168 } 1169 1170 1171 STRING SAL_CALL AnalysisAddIn::getImln( const STRING& aNum ) THROWDEF_RTE_IAE 1172 { 1173 Complex z( aNum ); 1174 1175 z.Ln(); 1176 1177 return z.GetString(); 1178 } 1179 1180 1181 STRING SAL_CALL AnalysisAddIn::getImlog10( const STRING& aNum ) THROWDEF_RTE_IAE 1182 { 1183 Complex z( aNum ); 1184 1185 z.Log10(); 1186 1187 return z.GetString(); 1188 } 1189 1190 1191 STRING SAL_CALL AnalysisAddIn::getImlog2( const STRING& aNum ) THROWDEF_RTE_IAE 1192 { 1193 Complex z( aNum ); 1194 1195 z.Log2(); 1196 1197 return z.GetString(); 1198 } 1199 1200 1201 STRING SAL_CALL AnalysisAddIn::getImproduct( constREFXPS&, const SEQSEQ( STRING )& aNum1, const SEQ( uno::Any )& aNL ) THROWDEF_RTE_IAE 1202 { 1203 ComplexList z_list; 1204 1205 z_list.Append( aNum1, AH_IgnoreEmpty ); 1206 z_list.Append( aNL, AH_IgnoreEmpty ); 1207 1208 const Complex* p = z_list.First(); 1209 1210 if( !p ) 1211 return Complex( 0 ).GetString(); 1212 1213 Complex z( *p ); 1214 1215 for( p = z_list.Next() ; p ; p = z_list.Next() ) 1216 z.Mult( *p ); 1217 1218 return z.GetString(); 1219 } 1220 1221 1222 double SAL_CALL AnalysisAddIn::getImreal( const STRING& aNum ) THROWDEF_RTE_IAE 1223 { 1224 double fRet = Complex( aNum ).Real(); 1225 RETURN_FINITE( fRet ); 1226 } 1227 1228 1229 STRING SAL_CALL AnalysisAddIn::getImsin( const STRING& aNum ) THROWDEF_RTE_IAE 1230 { 1231 Complex z( aNum ); 1232 1233 z.Sin(); 1234 1235 return z.GetString(); 1236 } 1237 1238 1239 STRING SAL_CALL AnalysisAddIn::getImsub( const STRING& aNum1, const STRING& aNum2 ) THROWDEF_RTE_IAE 1240 { 1241 Complex z( aNum1 ); 1242 1243 z.Sub( Complex( aNum2 ) ); 1244 1245 return z.GetString(); 1246 } 1247 1248 1249 STRING SAL_CALL AnalysisAddIn::getImsum( constREFXPS&, const SEQSEQ( STRING )& aNum1, const SEQ( CSS::uno::Any )& aFollowingPars ) THROWDEF_RTE_IAE 1250 { 1251 ComplexList z_list; 1252 1253 z_list.Append( aNum1, AH_IgnoreEmpty ); 1254 z_list.Append( aFollowingPars, AH_IgnoreEmpty ); 1255 1256 const Complex* p = z_list.First(); 1257 1258 if( !p ) 1259 return Complex( 0 ).GetString(); 1260 1261 Complex z( *p ); 1262 1263 for( p = z_list.Next() ; p ; p = z_list.Next() ) 1264 z.Add( *p ); 1265 1266 return z.GetString(); 1267 } 1268 1269 1270 STRING SAL_CALL AnalysisAddIn::getImsqrt( const STRING& aNum ) THROWDEF_RTE_IAE 1271 { 1272 Complex z( aNum ); 1273 1274 // z.Power( 0.5 ); 1275 z.Sqrt(); 1276 1277 return z.GetString(); 1278 } 1279 1280 1281 STRING SAL_CALL AnalysisAddIn::getImtan( const STRING& aNum ) THROWDEF_RTE_IAE 1282 { 1283 Complex z( aNum ); 1284 1285 z.Tan(); 1286 1287 return z.GetString(); 1288 } 1289 1290 1291 STRING SAL_CALL AnalysisAddIn::getImsec( const STRING& aNum ) THROWDEF_RTE_IAE 1292 { 1293 Complex z( aNum ); 1294 1295 z.Sec(); 1296 1297 return z.GetString(); 1298 } 1299 1300 1301 STRING SAL_CALL AnalysisAddIn::getImcsc( const STRING& aNum ) THROWDEF_RTE_IAE 1302 { 1303 Complex z( aNum ); 1304 1305 z.Csc(); 1306 1307 return z.GetString(); 1308 } 1309 1310 1311 STRING SAL_CALL AnalysisAddIn::getImcot( const STRING& aNum ) THROWDEF_RTE_IAE 1312 { 1313 Complex z( aNum ); 1314 1315 z.Cot(); 1316 1317 return z.GetString(); 1318 } 1319 1320 1321 STRING SAL_CALL AnalysisAddIn::getImsinh( const STRING& aNum ) THROWDEF_RTE_IAE 1322 { 1323 Complex z( aNum ); 1324 1325 z.Sinh(); 1326 1327 return z.GetString(); 1328 } 1329 1330 1331 STRING SAL_CALL AnalysisAddIn::getImcosh( const STRING& aNum ) THROWDEF_RTE_IAE 1332 { 1333 Complex z( aNum ); 1334 1335 z.Cosh(); 1336 1337 return z.GetString(); 1338 } 1339 1340 1341 STRING SAL_CALL AnalysisAddIn::getImsech( const STRING& aNum ) THROWDEF_RTE_IAE 1342 { 1343 Complex z( aNum ); 1344 1345 z.Sech(); 1346 1347 return z.GetString(); 1348 } 1349 1350 1351 STRING SAL_CALL AnalysisAddIn::getImcsch( const STRING& aNum ) THROWDEF_RTE_IAE 1352 { 1353 Complex z( aNum ); 1354 1355 z.Csch(); 1356 1357 return z.GetString(); 1358 } 1359 1360 1361 STRING SAL_CALL AnalysisAddIn::getComplex( double fR, double fI, const ANY& rSuff ) THROWDEF_RTE_IAE 1362 { 1363 sal_Bool bi; 1364 1365 switch( rSuff.getValueTypeClass() ) 1366 { 1367 case uno::TypeClass_VOID: 1368 bi = sal_True; 1369 break; 1370 case uno::TypeClass_STRING: 1371 { 1372 const STRING* pSuff = ( const STRING* ) rSuff.getValue(); 1373 bi = pSuff->compareToAscii( "i" ) == 0 || pSuff->getLength() == 0; 1374 if( !bi && pSuff->compareToAscii( "j" ) != 0 ) 1375 THROW_IAE; 1376 } 1377 break; 1378 default: 1379 THROW_IAE; 1380 } 1381 1382 return Complex( fR, fI, bi ? 'i' : 'j' ).GetString(); 1383 } 1384 1385 1386 double SAL_CALL AnalysisAddIn::getConvert( double f, const STRING& aFU, const STRING& aTU ) THROWDEF_RTE_IAE 1387 { 1388 if( !pCDL ) 1389 pCDL = new ConvertDataList(); 1390 1391 double fRet = pCDL->Convert( f, aFU, aTU ); 1392 RETURN_FINITE( fRet ); 1393 } 1394 1395 1396