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