xref: /AOO41X/main/scaddins/source/analysis/analysis.cxx (revision 5b073cc73f469eeafd4f39090bb6a267e5cc1ca6)
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