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