1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include <com/sun/star/util/XNumberFormatTypes.hpp> 29 30 #include <string.h> 31 #include <stdio.h> 32 #include <tools/resary.hxx> 33 #include <rtl/math.hxx> 34 #include "analysishelper.hxx" 35 #include "analysis.hrc" 36 37 using namespace ::rtl; 38 using namespace ::com::sun::star; 39 40 41 42 #define UNIQUE sal_False // function name does not exist in Calc 43 #define DOUBLE sal_True // function name exists in Calc 44 45 #define STDPAR sal_False // all parameters are described 46 #define INTPAR sal_True // first parameter is internal 47 48 #define FUNCDATA( FUNCNAME, DBL, OPT, NUMOFPAR, CAT ) \ 49 { "get" #FUNCNAME, ANALYSIS_FUNCNAME_##FUNCNAME, ANALYSIS_##FUNCNAME, DBL, OPT, ANALYSIS_DEFFUNCNAME_##FUNCNAME, NUMOFPAR, CAT } 50 51 const FuncDataBase pFuncDatas[] = 52 { 53 // UNIQUE or INTPAR or 54 // function name DOUBLE STDPAR # of param category 55 FUNCDATA( Workday, UNIQUE, INTPAR, 3, FDCat_DateTime ), 56 FUNCDATA( Yearfrac, UNIQUE, INTPAR, 3, FDCat_DateTime ), 57 FUNCDATA( Edate, UNIQUE, INTPAR, 2, FDCat_DateTime ), 58 FUNCDATA( Weeknum, DOUBLE, INTPAR, 2, FDCat_DateTime ), 59 FUNCDATA( Eomonth, UNIQUE, INTPAR, 2, FDCat_DateTime ), 60 FUNCDATA( Networkdays, UNIQUE, INTPAR, 3, FDCat_DateTime ), 61 FUNCDATA( Iseven, DOUBLE, STDPAR, 1, FDCat_Inf ), 62 FUNCDATA( Isodd, DOUBLE, STDPAR, 1, FDCat_Inf ), 63 FUNCDATA( Multinomial, UNIQUE, STDPAR, 1, FDCat_Math ), 64 FUNCDATA( Seriessum, UNIQUE, STDPAR, 4, FDCat_Math ), 65 FUNCDATA( Quotient, UNIQUE, STDPAR, 2, FDCat_Math ), 66 FUNCDATA( Mround, UNIQUE, STDPAR, 2, FDCat_Math ), 67 FUNCDATA( Sqrtpi, UNIQUE, STDPAR, 1, FDCat_Math ), 68 FUNCDATA( Randbetween, UNIQUE, STDPAR, 2, FDCat_Math ), 69 FUNCDATA( Gcd, DOUBLE, INTPAR, 1, FDCat_Math ), 70 FUNCDATA( Lcm, DOUBLE, INTPAR, 1, FDCat_Math ), 71 FUNCDATA( Besseli, UNIQUE, STDPAR, 2, FDCat_Tech ), 72 FUNCDATA( Besselj, UNIQUE, STDPAR, 2, FDCat_Tech ), 73 FUNCDATA( Besselk, UNIQUE, STDPAR, 2, FDCat_Tech ), 74 FUNCDATA( Bessely, UNIQUE, STDPAR, 2, FDCat_Tech ), 75 FUNCDATA( Bin2Oct, UNIQUE, INTPAR, 2, FDCat_Tech ), 76 FUNCDATA( Bin2Dec, UNIQUE, STDPAR, 1, FDCat_Tech ), 77 FUNCDATA( Bin2Hex, UNIQUE, INTPAR, 2, FDCat_Tech ), 78 FUNCDATA( Oct2Bin, UNIQUE, INTPAR, 2, FDCat_Tech ), 79 FUNCDATA( Oct2Dec, UNIQUE, STDPAR, 1, FDCat_Tech ), 80 FUNCDATA( Oct2Hex, UNIQUE, INTPAR, 2, FDCat_Tech ), 81 FUNCDATA( Dec2Bin, UNIQUE, INTPAR, 2, FDCat_Tech ), 82 FUNCDATA( Dec2Hex, UNIQUE, INTPAR, 2, FDCat_Tech ), 83 FUNCDATA( Dec2Oct, UNIQUE, INTPAR, 2, FDCat_Tech ), 84 FUNCDATA( Hex2Bin, UNIQUE, INTPAR, 2, FDCat_Tech ), 85 FUNCDATA( Hex2Dec, UNIQUE, STDPAR, 1, FDCat_Tech ), 86 FUNCDATA( Hex2Oct, UNIQUE, INTPAR, 2, FDCat_Tech ), 87 FUNCDATA( Delta, UNIQUE, INTPAR, 2, FDCat_Tech ), 88 FUNCDATA( Erf, UNIQUE, INTPAR, 2, FDCat_Tech ), 89 FUNCDATA( Erfc, UNIQUE, STDPAR, 1, FDCat_Tech ), 90 FUNCDATA( Gestep, UNIQUE, INTPAR, 2, FDCat_Tech ), 91 FUNCDATA( Factdouble, UNIQUE, STDPAR, 1, FDCat_Tech ), 92 FUNCDATA( Imabs, UNIQUE, STDPAR, 1, FDCat_Tech ), 93 FUNCDATA( Imaginary, UNIQUE, STDPAR, 1, FDCat_Tech ), 94 FUNCDATA( Impower, UNIQUE, STDPAR, 2, FDCat_Tech ), 95 FUNCDATA( Imargument, UNIQUE, STDPAR, 1, FDCat_Tech ), 96 FUNCDATA( Imcos, UNIQUE, STDPAR, 1, FDCat_Tech ), 97 FUNCDATA( Imdiv, UNIQUE, STDPAR, 2, FDCat_Tech ), 98 FUNCDATA( Imexp, UNIQUE, STDPAR, 1, FDCat_Tech ), 99 FUNCDATA( Imconjugate, UNIQUE, STDPAR, 1, FDCat_Tech ), 100 FUNCDATA( Imln, UNIQUE, STDPAR, 1, FDCat_Tech ), 101 FUNCDATA( Imlog10, UNIQUE, STDPAR, 1, FDCat_Tech ), 102 FUNCDATA( Imlog2, UNIQUE, STDPAR, 1, FDCat_Tech ), 103 FUNCDATA( Improduct, UNIQUE, INTPAR, 2, FDCat_Tech ), 104 FUNCDATA( Imreal, UNIQUE, STDPAR, 1, FDCat_Tech ), 105 FUNCDATA( Imsin, UNIQUE, STDPAR, 1, FDCat_Tech ), 106 FUNCDATA( Imsub, UNIQUE, STDPAR, 2, FDCat_Tech ), 107 FUNCDATA( Imsqrt, UNIQUE, STDPAR, 1, FDCat_Tech ), 108 FUNCDATA( Imsum, UNIQUE, INTPAR, 1, FDCat_Tech ), 109 FUNCDATA( Complex, UNIQUE, STDPAR, 3, FDCat_Tech ), 110 FUNCDATA( Convert, DOUBLE, STDPAR, 3, FDCat_Tech ), 111 FUNCDATA( Amordegrc, UNIQUE, INTPAR, 7, FDCat_Finance ), 112 FUNCDATA( Amorlinc, UNIQUE, INTPAR, 7, FDCat_Finance ), 113 FUNCDATA( Accrint, UNIQUE, INTPAR, 7, FDCat_Finance ), 114 FUNCDATA( Accrintm, UNIQUE, INTPAR, 5, FDCat_Finance ), 115 FUNCDATA( Received, UNIQUE, INTPAR, 5, FDCat_Finance ), 116 FUNCDATA( Disc, UNIQUE, INTPAR, 5, FDCat_Finance ), 117 FUNCDATA( Duration, DOUBLE, INTPAR, 6, FDCat_Finance ), 118 FUNCDATA( Effect, DOUBLE, STDPAR, 2, FDCat_Finance ), 119 FUNCDATA( Cumprinc, DOUBLE, STDPAR, 6, FDCat_Finance ), 120 FUNCDATA( Cumipmt, DOUBLE, STDPAR, 6, FDCat_Finance ), 121 FUNCDATA( Price, UNIQUE, INTPAR, 7, FDCat_Finance ), 122 FUNCDATA( Pricedisc, UNIQUE, INTPAR, 5, FDCat_Finance ), 123 FUNCDATA( Pricemat, UNIQUE, INTPAR, 6, FDCat_Finance ), 124 FUNCDATA( Mduration, UNIQUE, INTPAR, 6, FDCat_Finance ), 125 FUNCDATA( Nominal, DOUBLE, STDPAR, 2, FDCat_Finance ), 126 FUNCDATA( Dollarfr, UNIQUE, STDPAR, 2, FDCat_Finance ), 127 FUNCDATA( Dollarde, UNIQUE, STDPAR, 2, FDCat_Finance ), 128 FUNCDATA( Yield, UNIQUE, INTPAR, 7, FDCat_Finance ), 129 FUNCDATA( Yielddisc, UNIQUE, INTPAR, 5, FDCat_Finance ), 130 FUNCDATA( Yieldmat, UNIQUE, INTPAR, 6, FDCat_Finance ), 131 FUNCDATA( Tbilleq, UNIQUE, INTPAR, 3, FDCat_Finance ), 132 FUNCDATA( Tbillprice, UNIQUE, INTPAR, 3, FDCat_Finance ), 133 FUNCDATA( Tbillyield, UNIQUE, INTPAR, 3, FDCat_Finance ), 134 FUNCDATA( Oddfprice, UNIQUE, INTPAR, 9, FDCat_Finance ), 135 FUNCDATA( Oddfyield, UNIQUE, INTPAR, 9, FDCat_Finance ), 136 FUNCDATA( Oddlprice, UNIQUE, INTPAR, 8, FDCat_Finance ), 137 FUNCDATA( Oddlyield, UNIQUE, INTPAR, 8, FDCat_Finance ), 138 FUNCDATA( Xirr, UNIQUE, INTPAR, 3, FDCat_Finance ), 139 FUNCDATA( Xnpv, UNIQUE, STDPAR, 3, FDCat_Finance ), 140 FUNCDATA( Intrate, UNIQUE, INTPAR, 5, FDCat_Finance ), 141 FUNCDATA( Coupncd, UNIQUE, INTPAR, 4, FDCat_Finance ), 142 FUNCDATA( Coupdays, UNIQUE, INTPAR, 4, FDCat_Finance ), 143 FUNCDATA( Coupdaysnc, UNIQUE, INTPAR, 4, FDCat_Finance ), 144 FUNCDATA( Coupdaybs, UNIQUE, INTPAR, 4, FDCat_Finance ), 145 FUNCDATA( Couppcd, UNIQUE, INTPAR, 4, FDCat_Finance ), 146 FUNCDATA( Coupnum, UNIQUE, INTPAR, 4, FDCat_Finance ), 147 FUNCDATA( Fvschedule, UNIQUE, STDPAR, 2, FDCat_Finance ) 148 }; 149 #undef FUNCDATA 150 151 152 sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ) 153 { 154 if( (nMonth == 2) && IsLeapYear( nYear ) ) 155 return 29; 156 static const sal_uInt16 aDaysInMonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 157 return aDaysInMonth[ nMonth ]; 158 } 159 160 161 /** 162 * Convert a date to a count of days starting from 01/01/0001 163 * 164 * The internal representation of a Date used in this Addin 165 * is the number of days between 01/01/0001 and the date 166 * this function converts a Day , Month, Year representation 167 * to this internal Date value. 168 * 169 */ 170 171 sal_Int32 DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) 172 { 173 sal_Int32 nDays = ((sal_Int32)nYear-1) * 365; 174 nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400); 175 176 for( sal_uInt16 i = 1; i < nMonth; i++ ) 177 nDays += DaysInMonth(i,nYear); 178 nDays += nDay; 179 180 return nDays; 181 } 182 183 184 /** 185 * Convert a count of days starting from 01/01/0001 to a date 186 * 187 * The internal representation of a Date used in this Addin 188 * is the number of days between 01/01/0001 and the date 189 * this function converts this internal Date value 190 * to a Day , Month, Year representation of a Date. 191 * 192 */ 193 194 void DaysToDate( sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear ) 195 throw( lang::IllegalArgumentException ) 196 { 197 if( nDays < 0 ) 198 throw lang::IllegalArgumentException(); 199 200 sal_Int32 nTempDays; 201 sal_Int32 i = 0; 202 sal_Bool bCalc; 203 204 do 205 { 206 nTempDays = nDays; 207 rYear = (sal_uInt16)((nTempDays / 365) - i); 208 nTempDays -= ((sal_Int32) rYear -1) * 365; 209 nTempDays -= (( rYear -1) / 4) - (( rYear -1) / 100) + ((rYear -1) / 400); 210 bCalc = sal_False; 211 if ( nTempDays < 1 ) 212 { 213 i++; 214 bCalc = sal_True; 215 } 216 else 217 { 218 if ( nTempDays > 365 ) 219 { 220 if ( (nTempDays != 366) || !IsLeapYear( rYear ) ) 221 { 222 i--; 223 bCalc = sal_True; 224 } 225 } 226 } 227 } 228 while ( bCalc ); 229 230 rMonth = 1; 231 while ( (sal_Int32)nTempDays > DaysInMonth( rMonth, rYear ) ) 232 { 233 nTempDays -= DaysInMonth( rMonth, rYear ); 234 rMonth++; 235 } 236 rDay = (sal_uInt16)nTempDays; 237 } 238 239 240 /** 241 * Get the null date used by the spreadsheet document 242 * 243 * The internal representation of a Date used in this Addin 244 * is the number of days between 01/01/0001 and the date 245 * this function returns this internal Date value for the document null date 246 * 247 */ 248 249 sal_Int32 GetNullDate( constREFXPS& xOpt ) THROWDEF_RTE 250 { 251 if( xOpt.is() ) 252 { 253 try 254 { 255 ANY aAny = xOpt->getPropertyValue( STRFROMASCII( "NullDate" ) ); 256 util::Date aDate; 257 if( aAny >>= aDate ) 258 return DateToDays( aDate.Day, aDate.Month, aDate.Year ); 259 } 260 catch( uno::Exception& ) 261 { 262 } 263 } 264 265 // no null date available -> no calculations possible 266 throw uno::RuntimeException(); 267 } 268 269 270 sal_Int32 GetDiffDate360( 271 sal_uInt16 nDay1, sal_uInt16 nMonth1, sal_uInt16 nYear1, sal_Bool bLeapYear1, 272 sal_uInt16 nDay2, sal_uInt16 nMonth2, sal_uInt16 nYear2, 273 sal_Bool bUSAMethod ) 274 { 275 if( nDay1 == 31 ) 276 nDay1--; 277 else if( bUSAMethod && ( nMonth1 == 2 && ( nDay1 == 29 || ( nDay1 == 28 && !bLeapYear1 ) ) ) ) 278 nDay1 = 30; 279 280 if( nDay2 == 31 ) 281 { 282 if( bUSAMethod && nDay1 != 30 ) 283 { 284 //aDate2 += 1; -> 1.xx.yyyy 285 nDay2 = 1; 286 if( nMonth2 == 12 ) 287 { 288 nYear2++; 289 nMonth2 = 1; 290 } 291 else 292 nMonth2++; 293 } 294 else 295 nDay2 = 30; 296 } 297 298 return nDay2 + nMonth2 * 30 + nYear2 * 360 - nDay1 - nMonth1 * 30 - nYear1 * 360; 299 } 300 301 302 sal_Int32 GetDiffDate360( sal_Int32 nNullDate, sal_Int32 nDate1, sal_Int32 nDate2, sal_Bool bUSAMethod ) 303 { 304 nDate1 += nNullDate; 305 nDate2 += nNullDate; 306 307 sal_uInt16 nDay1, nMonth1, nYear1, nDay2, nMonth2, nYear2; 308 309 DaysToDate( nDate1, nDay1, nMonth1, nYear1 ); 310 DaysToDate( nDate2, nDay2, nMonth2, nYear2 ); 311 312 return GetDiffDate360( nDay1, nMonth1, nYear1, IsLeapYear( nYear1 ), nDay2, nMonth2, nYear2, bUSAMethod ); 313 } 314 315 316 sal_Int32 GetDaysInYears( sal_uInt16 nYear1, sal_uInt16 nYear2 ) 317 { 318 sal_uInt16 nLeaps = 0; 319 for( sal_uInt16 n = nYear1 ; n <= nYear2 ; n++ ) 320 { 321 if( IsLeapYear( n ) ) 322 nLeaps++; 323 } 324 325 sal_uInt32 nSum = 1; 326 nSum += nYear2; 327 nSum -= nYear1; 328 nSum *= 365; 329 nSum += nLeaps; 330 331 return nSum; 332 } 333 334 335 void GetDiffParam( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode, 336 sal_uInt16& rYears, sal_Int32& rDayDiffPart, sal_Int32& rDaysInYear ) THROWDEF_RTE_IAE 337 { 338 if( nStartDate > nEndDate ) 339 { 340 sal_Int32 n = nEndDate; 341 nEndDate = nStartDate; 342 nStartDate = n; 343 } 344 345 sal_Int32 nDate1 = nStartDate + nNullDate; 346 sal_Int32 nDate2 = nEndDate + nNullDate; 347 348 sal_uInt16 nDay1, nDay2; 349 sal_uInt16 nMonth1, nMonth2; 350 sal_uInt16 nYear1, nYear2; 351 352 DaysToDate( nDate1, nDay1, nMonth1, nYear1 ); 353 DaysToDate( nDate2, nDay2, nMonth2, nYear2 ); 354 355 sal_uInt16 nYears; 356 357 sal_Int32 nDayDiff, nDaysInYear; 358 359 switch( nMode ) 360 { 361 case 0: // 0=USA (NASD) 30/360 362 case 4: // 4=Europe 30/360 363 nDaysInYear = 360; 364 nYears = nYear2 - nYear1; 365 nDayDiff = GetDiffDate360( nDay1, nMonth1, nYear1, IsLeapYear( nYear1 ), 366 nDay2, nMonth2, nYear2, nMode == 0 ) - nYears * nDaysInYear; 367 break; 368 case 1: // 1=exact/exact 369 nYears = nYear2 - nYear1; 370 371 nDaysInYear = IsLeapYear( nYear1 )? 366 : 365; 372 373 if( nYears && ( nMonth1 > nMonth2 || ( nMonth1 == nMonth2 && nDay1 > nDay2 ) ) ) 374 nYears--; 375 376 if( nYears ) 377 nDayDiff = nDate2 - DateToDays( nDay1, nMonth1, nYear2 ); 378 else 379 nDayDiff = nDate2 - nDate1; 380 381 if( nDayDiff < 0 ) 382 nDayDiff += nDaysInYear; 383 384 break; 385 case 2: // 2=exact/360 386 nDaysInYear = 360; 387 nYears = sal_uInt16( ( nDate2 - nDate1 ) / nDaysInYear ); 388 nDayDiff = nDate2 - nDate1; 389 nDayDiff %= nDaysInYear; 390 break; 391 case 3: //3=exact/365 392 nDaysInYear = 365; 393 nYears = sal_uInt16( ( nDate2 - nDate1 ) / nDaysInYear ); 394 nDayDiff = nDate2 - nDate1; 395 nDayDiff %= nDaysInYear; 396 break; 397 default: 398 THROW_IAE; 399 } 400 401 rYears = nYears; 402 rDayDiffPart = nDayDiff; 403 rDaysInYear = nDaysInYear; 404 } 405 406 407 sal_Int32 GetDiffDate( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode, 408 sal_Int32* pOptDaysIn1stYear ) THROWDEF_RTE_IAE 409 { 410 sal_Bool bNeg = nStartDate > nEndDate; 411 412 if( bNeg ) 413 { 414 sal_Int32 n = nEndDate; 415 nEndDate = nStartDate; 416 nStartDate = n; 417 } 418 419 sal_Int32 nRet; 420 421 switch( nMode ) 422 { 423 case 0: // 0=USA (NASD) 30/360 424 case 4: // 4=Europe 30/360 425 { 426 sal_uInt16 nD1, nM1, nY1, nD2, nM2, nY2; 427 428 nStartDate += nNullDate; 429 nEndDate += nNullDate; 430 431 DaysToDate( nStartDate, nD1, nM1, nY1 ); 432 DaysToDate( nEndDate, nD2, nM2, nY2 ); 433 434 sal_Bool bLeap = IsLeapYear( nY1 ); 435 sal_Int32 nDays, nMonths/*, nYears*/; 436 437 nMonths = nM2 - nM1; 438 nDays = nD2 - nD1; 439 440 nMonths += ( nY2 - nY1 ) * 12; 441 442 nRet = nMonths * 30 + nDays; 443 if( nMode == 0 && nM1 == 2 && nM2 != 2 && nY1 == nY2 ) 444 nRet -= bLeap? 1 : 2; 445 446 if( pOptDaysIn1stYear ) 447 *pOptDaysIn1stYear = 360; 448 } 449 break; 450 case 1: // 1=exact/exact 451 if( pOptDaysIn1stYear ) 452 { 453 sal_uInt16 nD, nM, nY; 454 455 DaysToDate( nStartDate + nNullDate, nD, nM, nY ); 456 457 *pOptDaysIn1stYear = IsLeapYear( nY )? 366 : 365; 458 } 459 nRet = nEndDate - nStartDate; 460 break; 461 case 2: // 2=exact/360 462 nRet = nEndDate - nStartDate; 463 if( pOptDaysIn1stYear ) 464 *pOptDaysIn1stYear = 360; 465 break; 466 case 3: //3=exact/365 467 nRet = nEndDate - nStartDate; 468 if( pOptDaysIn1stYear ) 469 *pOptDaysIn1stYear = 365; 470 break; 471 default: 472 THROW_IAE; 473 } 474 475 return bNeg? -nRet : nRet; 476 } 477 478 479 double GetYearDiff( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode ) THROWDEF_RTE_IAE 480 { 481 sal_Int32 nDays1stYear; 482 sal_Int32 nTotalDays = GetDiffDate( nNullDate, nStartDate, nEndDate, nMode, &nDays1stYear ); 483 484 return double( nTotalDays ) / double( nDays1stYear ); 485 } 486 487 488 sal_Int32 GetDaysInYear( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nMode ) THROWDEF_RTE_IAE 489 { 490 switch( nMode ) 491 { 492 case 0: // 0=USA (NASD) 30/360 493 case 2: // 2=exact/360 494 case 4: // 4=Europe 30/360 495 return 360; 496 case 1: // 1=exact/exact 497 { 498 sal_uInt16 nD, nM, nY; 499 nDate += nNullDate; 500 DaysToDate( nDate, nD, nM, nY ); 501 return IsLeapYear( nY )? 366 : 365; 502 } 503 case 3: //3=exact/365 504 return 365; 505 default: 506 THROW_IAE; 507 } 508 } 509 510 511 double GetYearFrac( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode ) THROWDEF_RTE_IAE 512 { 513 if( nStartDate == nEndDate ) 514 return 0.0; // nothing to do... 515 516 sal_uInt16 nYears; 517 sal_Int32 nDayDiff, nDaysInYear; 518 519 GetDiffParam( nNullDate, nStartDate, nEndDate, nMode, nYears, nDayDiff, nDaysInYear ); 520 521 return double( nYears ) + double( nDayDiff ) / double( nDaysInYear ); 522 } 523 524 525 double Fak( sal_Int32 n ) 526 { 527 if( n > 0 ) 528 { 529 double fRet = n; 530 double f = n - 1; 531 532 while( f >= 2.0 ) 533 { 534 fRet *= f; 535 f--; 536 } 537 538 return fRet; 539 } 540 else if( !n ) 541 return 1.0; 542 else 543 return 0.0; 544 } 545 546 547 double GetGcd( double f1, double f2 ) 548 { 549 double f = fmod( f1, f2 ); 550 while( f > 0.0 ) 551 { 552 f1 = f2; 553 f2 = f; 554 f = fmod( f1, f2 ); 555 } 556 557 return f2; 558 } 559 560 561 double ConvertToDec( const STRING& aStr, sal_uInt16 nBase, sal_uInt16 nCharLim ) THROWDEF_RTE_IAE 562 { 563 if ( nBase < 2 || nBase > 36 ) 564 THROW_IAE; 565 566 sal_uInt32 nStrLen = aStr.getLength(); 567 if( nStrLen > nCharLim ) 568 THROW_IAE; 569 else if( !nStrLen ) 570 return 0.0; 571 572 double fVal = 0.0; 573 574 register const sal_Unicode* p = aStr.getStr(); 575 576 sal_uInt16 nFirstDig = 0; 577 sal_Bool bFirstDig = sal_True; 578 double fBase = nBase; 579 580 while ( *p ) 581 { 582 sal_uInt16 n; 583 584 if( '0' <= *p && *p <= '9' ) 585 n = *p - '0'; 586 else if( 'A' <= *p && *p <= 'Z' ) 587 n = 10 + ( *p - 'A' ); 588 else if ( 'a' <= *p && *p <= 'z' ) 589 n = 10 + ( *p - 'a' ); 590 else 591 n = nBase; 592 593 if( n < nBase ) 594 { 595 if( bFirstDig ) 596 { 597 bFirstDig = sal_False; 598 nFirstDig = n; 599 } 600 fVal = fVal * fBase + double( n ); 601 } 602 else 603 // illegal char! 604 THROW_IAE; 605 606 p++; 607 608 } 609 610 if( nStrLen == nCharLim && !bFirstDig && (nFirstDig >= nBase / 2) ) 611 { // handling negativ values 612 fVal = ( pow( double( nBase ), double( nCharLim ) ) - fVal ); // complement 613 fVal *= -1.0; 614 } 615 616 return fVal; 617 } 618 619 620 static inline sal_Char GetMaxChar( sal_uInt16 nBase ) 621 { 622 const sal_Char* c = "--123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 623 return c[ nBase ]; 624 } 625 626 627 STRING ConvertFromDec( double fNum, double fMin, double fMax, sal_uInt16 nBase, 628 sal_Int32 nPlaces, sal_Int32 nMaxPlaces, sal_Bool bUsePlaces ) THROWDEF_RTE_IAE 629 { 630 fNum = ::rtl::math::approxFloor( fNum ); 631 fMin = ::rtl::math::approxFloor( fMin ); 632 fMax = ::rtl::math::approxFloor( fMax ); 633 634 if( fNum < fMin || fNum > fMax || ( bUsePlaces && ( nPlaces <= 0 || nPlaces > nMaxPlaces ) ) ) 635 THROW_IAE; 636 637 sal_Int64 nNum = static_cast< sal_Int64 >( fNum ); 638 sal_Bool bNeg = nNum < 0; 639 if( bNeg ) 640 nNum = sal_Int64( pow( double( nBase ), double( nMaxPlaces ) ) ) + nNum; 641 642 STRING aRet( STRING::valueOf( nNum, nBase ).toAsciiUpperCase() ); 643 644 645 if( bUsePlaces ) 646 { 647 sal_Int32 nLen = aRet.getLength(); 648 if( !bNeg && nLen > nPlaces ) 649 { 650 THROW_IAE; 651 } 652 else if( ( bNeg && nLen < nMaxPlaces ) || ( !bNeg && nLen < nPlaces ) ) 653 { 654 sal_Int32 nLeft = nPlaces - nLen; 655 sal_Char* p = new sal_Char[ nLeft + 1 ]; 656 memset( p, bNeg? GetMaxChar( nBase ) : '0', nLeft ); 657 p[ nLeft ] = 0x00; 658 STRING aTmp( p, nLeft, RTL_TEXTENCODING_MS_1252 ); 659 aTmp += aRet; 660 aRet = aTmp; 661 662 delete[] p; 663 } 664 } 665 666 return aRet; 667 } 668 669 // implementation moved to module sal, see #i97091# 670 double Erf( double x ) 671 { 672 return ::rtl::math::erf(x); 673 } 674 675 // implementation moved to module sal, see #i97091# 676 double Erfc( double x ) 677 { 678 return ::rtl::math::erfc(x); 679 } 680 681 inline sal_Bool IsNum( sal_Unicode c ) 682 { 683 return c >= '0' && c <= '9'; 684 } 685 686 687 inline sal_Bool IsComma( sal_Unicode c ) 688 { 689 return c == '.' || c == ','; 690 } 691 692 693 inline sal_Bool IsExpStart( sal_Unicode c ) 694 { 695 return c == 'e' || c == 'E'; 696 } 697 698 699 inline sal_Bool IsImagUnit( sal_Unicode c ) 700 { 701 return c == 'i' || c == 'j'; 702 } 703 704 705 inline sal_uInt16 GetVal( sal_Unicode c ) 706 { 707 return sal_uInt16( c - '0' ); 708 } 709 710 711 sal_Bool ParseDouble( const sal_Unicode*& rp, double& rRet ) 712 { 713 double fInt = 0.0; 714 double fFrac = 0.0; 715 double fMult = 0.1; // multiplier to multiply digits with, when adding fractional ones 716 sal_Int32 nExp = 0; 717 sal_Int32 nMaxExp = 307; 718 sal_uInt16 nDigCnt = 18; // max. number of digits to read in, rest doesn't matter 719 720 enum State { S_End = 0, S_Sign, S_IntStart, S_Int, S_IgnoreIntDigs, S_Frac, S_IgnoreFracDigs, S_ExpSign, S_Exp }; 721 722 State eS = S_Sign; 723 724 sal_Bool bNegNum = sal_False; 725 sal_Bool bNegExp = sal_False; 726 727 const sal_Unicode* p = rp; 728 sal_Unicode c; 729 730 while( eS ) 731 { 732 c = *p; 733 switch( eS ) 734 { 735 case S_Sign: 736 if( IsNum( c ) ) 737 { 738 fInt = GetVal( c ); 739 nDigCnt--; 740 eS = S_Int; 741 } 742 else if( c == '-' ) 743 { 744 bNegNum = sal_True; 745 eS = S_IntStart; 746 } 747 else if( c == '+' ) 748 eS = S_IntStart; 749 else if( IsComma( c ) ) 750 eS = S_Frac; 751 else 752 return sal_False; 753 break; 754 case S_IntStart: 755 if( IsNum( c ) ) 756 { 757 fInt = GetVal( c ); 758 nDigCnt--; 759 eS = S_Int; 760 } 761 else if( IsComma( c ) ) 762 eS = S_Frac; 763 else if( IsImagUnit( c ) ) 764 { 765 rRet = 0.0; 766 return sal_True; 767 } 768 else 769 return sal_False; 770 break; 771 case S_Int: 772 if( IsNum( c ) ) 773 { 774 fInt *= 10.0; 775 fInt += double( GetVal( c ) ); 776 nDigCnt--; 777 if( !nDigCnt ) 778 eS = S_IgnoreIntDigs; 779 } 780 else if( IsComma( c ) ) 781 eS = S_Frac; 782 else if( IsExpStart( c ) ) 783 eS = S_ExpSign; 784 else 785 eS = S_End; 786 break; 787 case S_IgnoreIntDigs: 788 if( IsNum( c ) ) 789 nExp++; // just multiply num with 10... ;-) 790 else if( IsComma( c ) ) 791 eS = S_Frac; 792 else if( IsExpStart( c ) ) 793 eS = S_ExpSign; 794 else 795 eS = S_End; 796 break; 797 case S_Frac: 798 if( IsNum( c ) ) 799 { 800 fFrac += double( GetVal( c ) ) * fMult; 801 nDigCnt--; 802 if( nDigCnt ) 803 fMult *= 0.1; 804 else 805 eS = S_IgnoreFracDigs; 806 } 807 else if( IsExpStart( c ) ) 808 eS = S_ExpSign; 809 else 810 eS = S_End; 811 break; 812 case S_IgnoreFracDigs: 813 if( IsExpStart( c ) ) 814 eS = S_ExpSign; 815 else if( !IsNum( c ) ) 816 eS = S_End; 817 break; 818 case S_ExpSign: 819 if( IsNum( c ) ) 820 { 821 nExp = GetVal( c ); 822 eS = S_Exp; 823 } 824 else if( c == '-' ) 825 { 826 bNegExp = sal_True; 827 eS = S_Exp; 828 } 829 else if( c != '+' ) 830 eS = S_End; 831 break; 832 case S_Exp: 833 if( IsNum( c ) ) 834 { 835 nExp *= 10; 836 nExp += GetVal( c ); 837 if( nExp > nMaxExp ) 838 return sal_False; 839 } 840 else 841 eS = S_End; 842 break; 843 case S_End: // to avoid compiler warning 844 break; // loop exits anyway 845 } 846 847 p++; 848 } 849 850 p--; // set pointer back to last 851 rp = p; 852 853 fInt += fFrac; 854 sal_Int32 nLog10 = sal_Int32( log10( fInt ) ); 855 856 if( bNegExp ) 857 nExp = -nExp; 858 859 if( nLog10 + nExp > nMaxExp ) 860 return sal_False; 861 862 fInt = ::rtl::math::pow10Exp( fInt, nExp ); 863 864 if( bNegNum ) 865 fInt = -fInt; 866 867 rRet = fInt; 868 869 return sal_True; 870 } 871 872 873 STRING GetString( double f, sal_Bool bLeadingSign, sal_uInt16 nMaxDig ) 874 { 875 const int nBuff = 256; 876 sal_Char aBuff[ nBuff + 1 ]; 877 const char* pFormStr = bLeadingSign? "%+.*g" : "%.*g"; 878 int nLen = snprintf( aBuff, nBuff, pFormStr, int( nMaxDig ), f ); 879 // you never know which underlying implementation you get ... 880 aBuff[nBuff] = 0; 881 if ( nLen < 0 || nLen > nBuff ) 882 nLen = strlen( aBuff ); 883 884 STRING aRet( aBuff, nLen, RTL_TEXTENCODING_MS_1252 ); 885 886 return aRet; 887 } 888 889 890 double GetAmordegrc( sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer, 891 double fRestVal, double fPer, double fRate, sal_Int32 nBase ) THROWDEF_RTE_IAE 892 { 893 if( nBase == 2 ) 894 THROW_IAE; 895 896 sal_uInt32 nPer = sal_uInt32( fPer ); 897 double fUsePer = 1.0 / fRate; 898 double fAmorCoeff; 899 900 if( fUsePer < 3.0 ) 901 fAmorCoeff = 1.0; 902 else if( fUsePer < 5.0 ) 903 fAmorCoeff = 1.5; 904 else if( fUsePer <= 6.0 ) 905 fAmorCoeff = 2.0; 906 else 907 fAmorCoeff = 2.5; 908 909 fRate *= fAmorCoeff; 910 double fNRate = ::rtl::math::round( GetYearFrac( nNullDate, nDate, nFirstPer, nBase ) * fRate * fCost, 0 ); 911 fCost -= fNRate; 912 double fRest = fCost - fRestVal; // Anschaffungskosten - Restwert - Summe aller Abschreibungen 913 914 for( sal_uInt32 n = 0 ; n < nPer ; n++ ) 915 { 916 fNRate = ::rtl::math::round( fRate * fCost, 0 ); 917 fRest -= fNRate; 918 919 if( fRest < 0.0 ) 920 { 921 switch( nPer - n ) 922 { 923 case 0: 924 case 1: 925 return ::rtl::math::round( fCost * 0.5, 0 ); 926 default: 927 return 0.0; 928 } 929 } 930 931 fCost -= fNRate; 932 } 933 934 return fNRate; 935 } 936 937 938 double GetAmorlinc( sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer, 939 double fRestVal, double fPer, double fRate, sal_Int32 nBase ) THROWDEF_RTE_IAE 940 { 941 if( nBase == 2 ) 942 THROW_IAE; 943 944 sal_uInt32 nPer = sal_uInt32( fPer ); 945 double fOneRate = fCost * fRate; 946 double fCostDelta = fCost - fRestVal; 947 double f0Rate = GetYearFrac( nNullDate, nDate, nFirstPer, nBase ) * fRate * fCost; 948 sal_uInt32 nNumOfFullPeriods = sal_uInt32( ( fCost - fRestVal - f0Rate) / fOneRate ); 949 950 if( nPer == 0 ) 951 return f0Rate; 952 else if( nPer <= nNumOfFullPeriods ) 953 return fOneRate; 954 else if( nPer == nNumOfFullPeriods + 1 ) 955 return fCostDelta - fOneRate * nNumOfFullPeriods - f0Rate; 956 else 957 return 0.0; 958 } 959 960 961 double GetDuration( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup, 962 double fYield, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE 963 { 964 double fYearfrac = GetYearFrac( nNullDate, nSettle, nMat, nBase ); 965 double fNumOfCoups = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase ); 966 double fDur = 0.0; 967 const double f100 = 100.0; 968 fCoup *= f100 / double( nFreq ); // fCoup is used as cash flow 969 fYield /= nFreq; 970 fYield += 1.0; 971 972 double nDiff = fYearfrac * nFreq - fNumOfCoups; 973 974 double t; 975 976 for( t = 1.0 ; t < fNumOfCoups ; t++ ) 977 fDur += ( t + nDiff ) * ( fCoup ) / pow( fYield, t + nDiff ); 978 979 fDur += ( fNumOfCoups + nDiff ) * ( fCoup + f100 ) / pow( fYield, fNumOfCoups + nDiff ); 980 981 double p = 0.0; 982 for( t = 1.0 ; t < fNumOfCoups ; t++ ) 983 p += fCoup / pow( fYield, t + nDiff ); 984 985 p += ( fCoup + f100 ) / pow( fYield, fNumOfCoups + nDiff ); 986 987 fDur /= p; 988 fDur /= double( nFreq ); 989 990 return fDur; 991 } 992 993 994 double GetYieldmat( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue, 995 double fRate, double fPrice, sal_Int32 nBase ) THROWDEF_RTE_IAE 996 { 997 double fIssMat = GetYearFrac( nNullDate, nIssue, nMat, nBase ); 998 double fIssSet = GetYearFrac( nNullDate, nIssue, nSettle, nBase ); 999 double fSetMat = GetYearFrac( nNullDate, nSettle, nMat, nBase ); 1000 1001 double y = 1.0 + fIssMat * fRate; 1002 y /= fPrice / 100.0 + fIssSet * fRate; 1003 y--; 1004 y /= fSetMat; 1005 1006 return y; 1007 } 1008 1009 1010 double GetOddfprice( sal_Int32 /*nNullDate*/, sal_Int32 /*nSettle*/, sal_Int32 /*nMat*/, sal_Int32 /*nIssue*/, 1011 sal_Int32 /*nFirstCoup*/, double /*fRate*/, double /*fYield*/, double /*fRedemp*/, sal_Int32 /*nFreq*/, 1012 sal_Int32 /*nBase*/ ) THROWDEF_RTE_IAE 1013 { 1014 THROW_RTE; // #87380# 1015 /* 1016 double fN = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase ) - 1.0; 1017 double fNq = GetCoupnum( nNullDate, nSettle, nFirstCoup, nFreq, nBase ) - 1.0; 1018 double fDSC = GetCoupdaysnc( nNullDate, nSettle, nFirstCoup, nFreq, nBase ); 1019 double fDSC_E = fDSC / GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase ); 1020 double fNC = GetCoupnum( nNullDate, nIssue, nFirstCoup, nFreq, nBase ); 1021 sal_uInt32 nNC = sal_uInt32( fNC ); 1022 sal_uInt16 nMonthDelta = 12 / sal_uInt16( nFreq ); 1023 1024 sal_uInt32 i; 1025 double f1YieldFreq = 1.0 + fYield / double( nFreq ); 1026 double f100RateFreq = 100.0 * fRate / double( nFreq ); 1027 1028 double* pDC = new double[ nNC + 1 ]; 1029 double* pNL = new double[ nNC + 1 ]; 1030 double* pA = new double[ nNC + 1 ]; 1031 1032 pDC[ 0 ] = pNL[ 0 ] = pA[ 0 ] = 1.0; 1033 1034 ScaDate aStartDate( nNullDate, nSettle, nBase ); 1035 ScaDate aNextCoup( nNullDate, nFirstCoup, nBase ); 1036 if( nNC ) 1037 { 1038 pDC[ 1 ] = ScaDate::GetDiff( aStartDate, aNextCoup ); 1039 pNL[ 1 ] = GetCoupdays( nNullDate, nSettle, nFirstCoup, nFreq, nBase ); 1040 pA[ 1 ] = pDC[ 1 ]; 1041 ScaDate aPre; 1042 for( i = 1 ; i <= nNC ; i++ ) 1043 { 1044 aPre = aStartDate; 1045 aStartDate.addMonths( nMonthDelta ); 1046 aNextCoup.addMonths( nMonthDelta ); 1047 pDC[ i ] = ScaDate::GetDiff( aPre, aStartDate ); 1048 pNL[ i ] = GetCoupdays( nNullDate, aStartDate.GetDate( nNullDate ), aNextCoup.GetDate( nNullDate ), 1049 nFreq, nBase ); 1050 pA[ i ] = ScaDate::GetDiff( aStartDate, aNextCoup ); 1051 } 1052 } 1053 1054 double fT1 = fRedemp / pow( f1YieldFreq, fN + fNq + fDSC_E ); 1055 1056 double fT2 = 0.0; 1057 for( i = 1 ; i <= nNC ; i++ ) 1058 fT2 += pDC[ i ] / pNL[ i ]; 1059 fT2 *= f100RateFreq / pow( f1YieldFreq, fNq + fDSC_E ); 1060 1061 double fT3 = 0.0; 1062 for( double k = 2.0 ; k <= fN ; k++ ) 1063 fT3 += 1.0 / pow( f1YieldFreq, k - fNq + fDSC_E ); 1064 fT3 *= f100RateFreq; 1065 1066 double fT4 = 0.0; 1067 for( i = 1 ; i <= nNC ; i++ ) 1068 fT4 += pA[ i ] / pNL[ i ]; 1069 fT4 *= f100RateFreq; 1070 1071 if( nNC ) 1072 { 1073 delete pDC; 1074 delete pNL; 1075 delete pA; 1076 } 1077 1078 return fT1 + fT2 + fT3 - fT4; 1079 */ 1080 } 1081 1082 1083 double getYield_( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup, double fPrice, 1084 double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE 1085 { 1086 double fRate = fCoup; 1087 double fPriceN = 0.0; 1088 double fYield1 = 0.0; 1089 double fYield2 = 1.0; 1090 double fPrice1 = getPrice_( nNullDate, nSettle, nMat, fRate, fYield1, fRedemp, nFreq, nBase ); 1091 double fPrice2 = getPrice_( nNullDate, nSettle, nMat, fRate, fYield2, fRedemp, nFreq, nBase ); 1092 double fYieldN = ( fYield2 - fYield1 ) * 0.5; 1093 1094 for( sal_uInt32 nIter = 0 ; nIter < 100 && fPriceN != fPrice ; nIter++ ) 1095 { 1096 fPriceN = getPrice_( nNullDate, nSettle, nMat, fRate, fYieldN, fRedemp, nFreq, nBase ); 1097 1098 if( fPrice == fPrice1 ) 1099 return fYield1; 1100 else if( fPrice == fPrice2 ) 1101 return fYield2; 1102 else if( fPrice == fPriceN ) 1103 return fYieldN; 1104 else if( fPrice < fPrice2 ) 1105 { 1106 fYield2 *= 2.0; 1107 fPrice2 = getPrice_( nNullDate, nSettle, nMat, fRate, fYield2, fRedemp, nFreq, nBase ); 1108 1109 fYieldN = ( fYield2 - fYield1 ) * 0.5; 1110 } 1111 else 1112 { 1113 if( fPrice < fPriceN ) 1114 { 1115 fYield1 = fYieldN; 1116 fPrice1 = fPriceN; 1117 } 1118 else 1119 { 1120 fYield2 = fYieldN; 1121 fPrice2 = fPriceN; 1122 } 1123 1124 fYieldN = fYield2 - ( fYield2 - fYield1 ) * ( ( fPrice - fPrice2 ) / ( fPrice1 - fPrice2 ) ); 1125 } 1126 } 1127 1128 if( fabs( fPrice - fPriceN ) > fPrice / 100.0 ) 1129 THROW_IAE; // result not precise enough 1130 1131 return fYieldN; 1132 } 1133 1134 1135 double getPrice_( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fRate, double fYield, 1136 double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE 1137 { 1138 double fFreq = nFreq; 1139 1140 double fE = GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase ); 1141 double fDSC_E = GetCoupdaysnc( nNullDate, nSettle, nMat, nFreq, nBase ) / fE; 1142 double fN = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase ); 1143 double fA = GetCoupdaybs( nNullDate, nSettle, nMat, nFreq, nBase ); 1144 1145 double fRet = fRedemp / ( pow( 1.0 + fYield / fFreq, fN - 1.0 + fDSC_E ) ); 1146 fRet -= 100.0 * fRate / fFreq * fA / fE; 1147 1148 double fT1 = 100.0 * fRate / fFreq; 1149 double fT2 = 1.0 + fYield / fFreq; 1150 1151 for( double fK = 0.0 ; fK < fN ; fK++ ) 1152 fRet += fT1 / pow( fT2, fK + fDSC_E ); 1153 1154 return fRet; 1155 } 1156 1157 1158 double GetOddfyield( sal_Int32 /*nNullDate*/, sal_Int32 /*nSettle*/, sal_Int32 /*nMat*/, sal_Int32 /*nIssue*/, 1159 sal_Int32 /*nFirstCoup*/, double /*fRate*/, double /*fPrice*/, double /*fRedemp*/, sal_Int32 /*nFreq*/, 1160 sal_Int32 /*nBase*/ ) THROWDEF_RTE_IAE 1161 { 1162 THROW_RTE; // #87380# 1163 /* 1164 //GetOddfprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue, 1165 //sal_Int32 nFirstCoup, double fRate, double fYield, double fRedemp, sal_Int32 nFreq, 1166 //sal_Int32 nBase ) 1167 double fPriceN = 0.0; 1168 double fYield1 = 0.0; 1169 double fYield2 = 1.0; 1170 double fPrice1 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield1, fRedemp, nFreq, nBase ); 1171 double fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase ); 1172 double fYieldN = ( fYield2 - fYield1 ) * 0.5; 1173 1174 for( sal_uInt32 nIter = 0 ; nIter < 100 && fPriceN != fPrice ; nIter++ ) 1175 { 1176 fPriceN = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYieldN, fRedemp, nFreq, nBase ); 1177 1178 if( fPrice == fPrice1 ) 1179 return fYield1; 1180 else if( fPrice == fPrice2 ) 1181 return fYield2; 1182 else if( fPrice == fPriceN ) 1183 return fYieldN; 1184 else if( fPrice < fPrice2 ) 1185 { 1186 fYield2 *= 2.0; 1187 fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase ); 1188 1189 fYieldN = ( fYield2 - fYield1 ) * 0.5; 1190 } 1191 else 1192 { 1193 if( fPrice < fPriceN ) 1194 { 1195 fYield1 = fYieldN; 1196 fPrice1 = fPriceN; 1197 } 1198 else 1199 { 1200 fYield2 = fYieldN; 1201 fPrice2 = fPriceN; 1202 } 1203 1204 fYieldN = fYield2 - ( fYield2 - fYield1 ) * ( ( fPrice - fPrice2 ) / ( fPrice1 - fPrice2 ) ); 1205 } 1206 } 1207 1208 if( fabs( fPrice - fPriceN ) > fPrice / 100.0 ) 1209 THROW_IAE; // result not precise enough 1210 1211 return fYieldN; 1212 */ 1213 } 1214 1215 1216 double GetOddlprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastCoup, 1217 double fRate, double fYield, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE 1218 { 1219 double fFreq = double( nFreq ); 1220 double fDCi = GetYearFrac( nNullDate, nLastCoup, nMat, nBase ) * fFreq; 1221 double fDSCi = GetYearFrac( nNullDate, nSettle, nMat, nBase ) * fFreq; 1222 double fAi = GetYearFrac( nNullDate, nLastCoup, nSettle, nBase ) * fFreq; 1223 1224 double p = fRedemp + fDCi * 100.0 * fRate / fFreq; 1225 p /= fDSCi * fYield / fFreq + 1.0; 1226 p -= fAi * 100.0 * fRate / fFreq; 1227 1228 return p; 1229 } 1230 1231 1232 double GetOddlyield( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastCoup, 1233 double fRate, double fPrice, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE 1234 { 1235 double fFreq = double( nFreq ); 1236 double fDCi = GetYearFrac( nNullDate, nLastCoup, nMat, nBase ) * fFreq; 1237 double fDSCi = GetYearFrac( nNullDate, nSettle, nMat, nBase ) * fFreq; 1238 double fAi = GetYearFrac( nNullDate, nLastCoup, nSettle, nBase ) * fFreq; 1239 1240 double y = fRedemp + fDCi * 100.0 * fRate / fFreq; 1241 y /= fPrice + fAi * 100.0 * fRate / fFreq; 1242 y--; 1243 y *= fFreq / fDSCi; 1244 1245 return y; 1246 } 1247 1248 1249 double GetRmz( double fZins, double fZzr, double fBw, double fZw, sal_Int32 nF ) 1250 { 1251 double fRmz; 1252 if( fZins == 0.0 ) 1253 fRmz = ( fBw + fZw ) / fZzr; 1254 else 1255 { 1256 double fTerm = pow( 1.0 + fZins, fZzr ); 1257 if( nF > 0 ) 1258 fRmz = ( fZw * fZins / ( fTerm - 1.0 ) + fBw * fZins / ( 1.0 - 1.0 / fTerm ) ) / ( 1.0 + fZins ); 1259 else 1260 fRmz = fZw * fZins / ( fTerm - 1.0 ) + fBw * fZins / ( 1.0 - 1.0 / fTerm ); 1261 } 1262 1263 return -fRmz; 1264 } 1265 1266 1267 double GetZw( double fZins, double fZzr, double fRmz, double fBw, sal_Int32 nF ) 1268 { 1269 double fZw; 1270 if( fZins == 0.0 ) 1271 fZw = fBw + fRmz * fZzr; 1272 else 1273 { 1274 double fTerm = pow( 1.0 + fZins, fZzr ); 1275 if( nF > 0 ) 1276 fZw = fBw * fTerm + fRmz * ( 1.0 + fZins ) * ( fTerm - 1.0 ) / fZins; 1277 else 1278 fZw = fBw * fTerm + fRmz * ( fTerm - 1.0 ) / fZins; 1279 } 1280 1281 return -fZw; 1282 } 1283 1284 1285 /*double TBillYield( constREFXPS& xOpt, sal_Int32 nSettle, sal_Int32 nMat, double fPrice ) THROWDEF_RTE_IAE 1286 { 1287 sal_Int32 nDiff = GetDiffDate360( xOpt, nSettle, nMat, sal_True ); 1288 1289 if( fPrice <= 0.0 || nSettle >= nMat || nDiff > 360 ) 1290 THROW_IAE; 1291 1292 double fRet = 100.0; 1293 fRet /= fPrice; 1294 fRet--; 1295 fRet *= double( nDiff ); 1296 fRet /= 360.0; 1297 1298 return fRet; 1299 }*/ 1300 1301 1302 //----------------------------------------------------------------------------- 1303 // financial functions COUP*** 1304 1305 1306 //------- 1307 // COUPPCD: find last coupon date before settlement (can be equal to settlement) 1308 void lcl_GetCouppcd( ScaDate& rDate, const ScaDate& rSettle, const ScaDate& rMat, sal_Int32 nFreq ) 1309 throw( lang::IllegalArgumentException ) 1310 { 1311 rDate = rMat; 1312 rDate.setYear( rSettle.getYear() ); 1313 if( rDate < rSettle ) 1314 rDate.addYears( 1 ); 1315 while( rDate > rSettle ) 1316 rDate.addMonths( -12 / nFreq ); 1317 } 1318 1319 double GetCouppcd( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) 1320 THROWDEF_RTE_IAE 1321 { 1322 if( nSettle >= nMat || CHK_Freq ) 1323 THROW_IAE; 1324 1325 ScaDate aDate; 1326 lcl_GetCouppcd( aDate, ScaDate( nNullDate, nSettle, nBase ), ScaDate( nNullDate, nMat, nBase ), nFreq ); 1327 return aDate.getDate( nNullDate ); 1328 } 1329 1330 1331 //------- 1332 // COUPNCD: find first coupon date after settlement (is never equal to settlement) 1333 void lcl_GetCoupncd( ScaDate& rDate, const ScaDate& rSettle, const ScaDate& rMat, sal_Int32 nFreq ) 1334 throw( lang::IllegalArgumentException ) 1335 { 1336 rDate = rMat; 1337 rDate.setYear( rSettle.getYear() ); 1338 if( rDate > rSettle ) 1339 rDate.addYears( -1 ); 1340 while( rDate <= rSettle ) 1341 rDate.addMonths( 12 / nFreq ); 1342 } 1343 1344 double GetCoupncd( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) 1345 THROWDEF_RTE_IAE 1346 { 1347 if( nSettle >= nMat || CHK_Freq ) 1348 THROW_IAE; 1349 1350 ScaDate aDate; 1351 lcl_GetCoupncd( aDate, ScaDate( nNullDate, nSettle, nBase ), ScaDate( nNullDate, nMat, nBase ), nFreq ); 1352 return aDate.getDate( nNullDate ); 1353 } 1354 1355 1356 //------- 1357 // COUPDAYBS: get day count: coupon date before settlement <-> settlement 1358 double GetCoupdaybs( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) 1359 THROWDEF_RTE_IAE 1360 { 1361 if( nSettle >= nMat || CHK_Freq ) 1362 THROW_IAE; 1363 1364 ScaDate aSettle( nNullDate, nSettle, nBase ); 1365 ScaDate aDate; 1366 lcl_GetCouppcd( aDate, aSettle, ScaDate( nNullDate, nMat, nBase ), nFreq ); 1367 return ScaDate::getDiff( aDate, aSettle ); 1368 } 1369 1370 1371 //------- 1372 // COUPDAYSNC: get day count: settlement <-> coupon date after settlement 1373 double GetCoupdaysnc( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) 1374 THROWDEF_RTE_IAE 1375 { 1376 if( nSettle >= nMat || CHK_Freq ) 1377 THROW_IAE; 1378 1379 if( (nBase != 0) && (nBase != 4) ) 1380 { 1381 ScaDate aSettle( nNullDate, nSettle, nBase ); 1382 ScaDate aDate; 1383 lcl_GetCoupncd( aDate, aSettle, ScaDate( nNullDate, nMat, nBase ), nFreq ); 1384 return ScaDate::getDiff( aSettle, aDate ); 1385 } 1386 return GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase ) - GetCoupdaybs( nNullDate, nSettle, nMat, nFreq, nBase ); 1387 } 1388 1389 1390 //------- 1391 // COUPDAYS: get day count: coupon date before settlement <-> coupon date after settlement 1392 double GetCoupdays( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) 1393 THROWDEF_RTE_IAE 1394 { 1395 if( nSettle >= nMat || CHK_Freq ) 1396 THROW_IAE; 1397 1398 if( nBase == 1 ) 1399 { 1400 ScaDate aDate; 1401 lcl_GetCouppcd( aDate, ScaDate( nNullDate, nSettle, nBase ), ScaDate( nNullDate, nMat, nBase ), nFreq ); 1402 ScaDate aNextDate( aDate ); 1403 aNextDate.addMonths( 12 / nFreq ); 1404 return ScaDate::getDiff( aDate, aNextDate ); 1405 } 1406 return static_cast< double >( GetDaysInYear( 0, 0, nBase ) ) / nFreq; 1407 } 1408 1409 1410 //------- 1411 // COUPNUM: get count of coupon dates 1412 double GetCoupnum( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) 1413 THROWDEF_RTE_IAE 1414 { 1415 if( nSettle >= nMat || CHK_Freq ) 1416 THROW_IAE; 1417 1418 ScaDate aMat( nNullDate, nMat, nBase ); 1419 ScaDate aDate; 1420 lcl_GetCouppcd( aDate, ScaDate( nNullDate, nSettle, nBase ), aMat, nFreq ); 1421 sal_uInt16 nMonths = (aMat.getYear() - aDate.getYear()) * 12 + aMat.getMonth() - aDate.getMonth(); 1422 return static_cast< double >( nMonths * nFreq / 12 ); 1423 } 1424 1425 1426 1427 1428 1429 1430 1431 const sal_uInt32 MyList::nStartSize = 16; 1432 const sal_uInt32 MyList::nIncrSize = 16; 1433 1434 1435 void MyList::_Grow( void ) 1436 { 1437 nSize += nIncrSize; 1438 1439 void** pNewData = new void*[ nSize ]; 1440 memcpy( pNewData, pData, nNew * sizeof( void* ) ); 1441 1442 delete[] pData; 1443 pData = pNewData; 1444 } 1445 1446 1447 MyList::MyList( void ) 1448 { 1449 nSize = nStartSize; 1450 pData = new void*[ nSize ]; 1451 nNew = nAct = 0; 1452 } 1453 1454 1455 MyList::~MyList() 1456 { 1457 delete[] pData; 1458 } 1459 1460 1461 void MyList::Insert( void* p, sal_uInt32 n ) 1462 { 1463 if( n >= nNew ) 1464 Append( p ); 1465 else 1466 { 1467 Grow(); 1468 1469 void** pIns = pData + n; 1470 memmove( pIns + 1, pIns, ( nNew - n ) * sizeof( void* ) ); 1471 1472 *pIns = p; 1473 1474 nNew++; 1475 } 1476 } 1477 1478 1479 1480 1481 StringList::~StringList() 1482 { 1483 for( STRING* p = ( STRING* ) First() ; p ; p = ( STRING* ) Next() ) 1484 delete p; 1485 } 1486 1487 1488 class AnalysisRscStrArrLoader : public Resource 1489 { 1490 private: 1491 ResStringArray aStrArray; 1492 public: 1493 AnalysisRscStrArrLoader( sal_uInt16 nRsc, sal_uInt16 nArrayId, ResMgr& rResMgr ) : 1494 Resource( AnalysisResId( nRsc, rResMgr ) ), 1495 aStrArray( AnalysisResId( nArrayId, rResMgr ) ) 1496 { 1497 FreeResource(); 1498 } 1499 1500 const ResStringArray& GetStringArray() const { return aStrArray; } 1501 }; 1502 1503 1504 1505 1506 FuncData::FuncData( const FuncDataBase& r, ResMgr& rResMgr ) : 1507 aIntName( OUString::createFromAscii( r.pIntName ) ), 1508 nUINameID( r.nUINameID ), 1509 nDescrID( r.nDescrID ), 1510 bDouble( r.bDouble ), 1511 bWithOpt( r.bWithOpt ), 1512 nParam( r.nNumOfParams ), 1513 nCompID( r.nCompListID ), 1514 eCat( r.eCat ) 1515 { 1516 AnalysisRscStrArrLoader aArrLoader( RID_ANALYSIS_DEFFUNCTION_NAMES, nCompID, rResMgr ); 1517 // ResStringArray aDefFuncNameArray( AnalysisResId( nCompID, rResMgr ) ); 1518 const ResStringArray& rArr = aArrLoader.GetStringArray(); 1519 1520 sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( rArr.Count() ); 1521 sal_uInt16 n; 1522 1523 for( n = 0 ; n < nCount ; n++ ) 1524 aCompList.Append( rArr.GetString( n ) ); 1525 } 1526 1527 1528 FuncData::~FuncData() 1529 { 1530 } 1531 1532 1533 sal_uInt16 FuncData::GetStrIndex( sal_uInt16 nParamNum ) const 1534 { 1535 if( !bWithOpt ) 1536 nParamNum++; 1537 1538 if( nParamNum > nParam ) 1539 return nParam * 2; 1540 else 1541 return nParamNum * 2; 1542 } 1543 1544 1545 1546 1547 FuncDataList::FuncDataList( ResMgr& rResMgr ) 1548 { 1549 const sal_uInt32 nNum = sizeof( pFuncDatas ) / sizeof( FuncDataBase ); 1550 1551 for( sal_uInt16 n = 0 ; n < nNum ; n++ ) 1552 Append( new FuncData( pFuncDatas[ n ], rResMgr ) ); 1553 } 1554 1555 1556 FuncDataList::~FuncDataList() 1557 { 1558 for( FuncData* p = ( FuncData* ) First() ; p ; p = ( FuncData* ) Next() ) 1559 delete p; 1560 } 1561 1562 1563 const FuncData* FuncDataList::Get( const OUString& aProgrammaticName ) const 1564 { 1565 if( aLastName == aProgrammaticName ) 1566 return Get( nLast ); 1567 1568 ( ( FuncDataList* ) this )->aLastName = aProgrammaticName; 1569 1570 sal_uInt32 nE = Count(); 1571 for( sal_uInt32 n = 0 ; n < nE ; n++ ) 1572 { 1573 const FuncData* p = Get( n ); 1574 if( p->Is( aProgrammaticName ) ) 1575 { 1576 ( ( FuncDataList* ) this )->nLast = n; 1577 return p; 1578 } 1579 } 1580 1581 ( ( FuncDataList* ) this )->nLast = 0xFFFFFFFF; 1582 return NULL; 1583 } 1584 1585 1586 AnalysisResId::AnalysisResId( sal_uInt16 nId, ResMgr& rResMgr ) : ResId( nId, rResMgr ) 1587 { 1588 } 1589 1590 1591 1592 1593 SortedIndividualInt32List::SortedIndividualInt32List() 1594 { 1595 } 1596 1597 1598 SortedIndividualInt32List::~SortedIndividualInt32List() 1599 { 1600 } 1601 1602 1603 void SortedIndividualInt32List::Insert( sal_Int32 nDay ) 1604 { 1605 sal_uInt32 nIndex = Count(); 1606 while( nIndex ) 1607 { 1608 nIndex--; 1609 sal_Int32 nRef = Get( nIndex ); 1610 if( nDay == nRef ) 1611 return; 1612 else if( nDay > nRef ) 1613 { 1614 MyList::Insert( (void*) nDay, nIndex + 1 ); 1615 return; 1616 } 1617 } 1618 MyList::Insert( (void*) nDay, 0UL ); 1619 } 1620 1621 1622 void SortedIndividualInt32List::Insert( sal_Int32 nDay, sal_Int32 nNullDate, sal_Bool bInsertOnWeekend ) 1623 { 1624 if( !nDay ) 1625 return; 1626 1627 nDay += nNullDate; 1628 if( bInsertOnWeekend || (GetDayOfWeek( nDay ) < 5) ) 1629 Insert( nDay ); 1630 } 1631 1632 1633 void SortedIndividualInt32List::Insert( 1634 double fDay, sal_Int32 nNullDate, sal_Bool bInsertOnWeekend ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 1635 { 1636 if( (fDay < -2147483648.0) || (fDay > 2147483649.0) ) 1637 throw lang::IllegalArgumentException(); 1638 Insert( static_cast< sal_Int32 >( fDay ), nNullDate, bInsertOnWeekend ); 1639 } 1640 1641 1642 sal_Bool SortedIndividualInt32List::Find( sal_Int32 nVal ) const 1643 { 1644 sal_uInt32 nE = Count(); 1645 1646 if( !nE || nVal < Get( 0 ) || nVal > Get( nE - 1 ) ) 1647 return sal_False; 1648 1649 // linear search 1650 1651 for( sal_uInt32 n = 0 ; n < nE ; n++ ) 1652 { 1653 sal_Int32 nRef = Get( n ); 1654 1655 if( nRef == nVal ) 1656 return sal_True; 1657 else if( nRef > nVal ) 1658 return sal_False; 1659 } 1660 return sal_False; 1661 } 1662 1663 1664 void SortedIndividualInt32List::InsertHolidayList( 1665 const ScaAnyConverter& rAnyConv, 1666 const uno::Any& rHolAny, 1667 sal_Int32 nNullDate, 1668 sal_Bool bInsertOnWeekend ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 1669 { 1670 double fDay; 1671 if( rAnyConv.getDouble( fDay, rHolAny ) ) 1672 Insert( fDay, nNullDate, bInsertOnWeekend ); 1673 } 1674 1675 1676 void SortedIndividualInt32List::InsertHolidayList( 1677 ScaAnyConverter& rAnyConv, 1678 const uno::Reference< beans::XPropertySet >& xOptions, 1679 const uno::Any& rHolAny, 1680 sal_Int32 nNullDate, 1681 sal_Bool bInsertOnWeekend ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 1682 { 1683 rAnyConv.init( xOptions ); 1684 if( rHolAny.getValueTypeClass() == uno::TypeClass_SEQUENCE ) 1685 { 1686 uno::Sequence< uno::Sequence< uno::Any > > aAnySeq; 1687 if( rHolAny >>= aAnySeq ) 1688 { 1689 const uno::Sequence< uno::Any >* pSeqArray = aAnySeq.getConstArray(); 1690 for( sal_Int32 nIndex1 = 0; nIndex1 < aAnySeq.getLength(); nIndex1++ ) 1691 { 1692 const uno::Sequence< uno::Any >& rSubSeq = pSeqArray[ nIndex1 ]; 1693 const uno::Any* pAnyArray = rSubSeq.getConstArray(); 1694 1695 for( sal_Int32 nIndex2 = 0; nIndex2 < rSubSeq.getLength(); nIndex2++ ) 1696 InsertHolidayList( rAnyConv, pAnyArray[ nIndex2 ], nNullDate, bInsertOnWeekend ); 1697 } 1698 } 1699 else 1700 throw lang::IllegalArgumentException(); 1701 } 1702 else 1703 InsertHolidayList( rAnyConv, rHolAny, nNullDate, bInsertOnWeekend ); 1704 } 1705 1706 1707 1708 //----------------------------------------------------------------------------- 1709 1710 ScaDoubleList::~ScaDoubleList() 1711 { 1712 for( double* pDbl = const_cast< double* >( First() ); pDbl; pDbl = const_cast< double* >( Next() ) ) 1713 delete pDbl; 1714 } 1715 1716 1717 void ScaDoubleList::Append( 1718 const uno::Sequence< uno::Sequence< double > >& rValueSeq ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 1719 { 1720 const uno::Sequence< double >* pSeqArray = rValueSeq.getConstArray(); 1721 for( sal_Int32 nIndex1 = 0; nIndex1 < rValueSeq.getLength(); nIndex1++ ) 1722 { 1723 const uno::Sequence< double >& rSubSeq = pSeqArray[ nIndex1 ]; 1724 const double* pArray = rSubSeq.getConstArray(); 1725 for( sal_Int32 nIndex2 = 0; nIndex2 < rSubSeq.getLength(); nIndex2++ ) 1726 Append( pArray[ nIndex2 ] ); 1727 } 1728 } 1729 1730 1731 void ScaDoubleList::Append( 1732 const uno::Sequence< uno::Sequence< sal_Int32 > >& rValueSeq ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 1733 { 1734 const uno::Sequence< sal_Int32 >* pSeqArray = rValueSeq.getConstArray(); 1735 for( sal_Int32 nIndex1 = 0; nIndex1 < rValueSeq.getLength(); nIndex1++ ) 1736 { 1737 const uno::Sequence< sal_Int32 >& rSubSeq = pSeqArray[ nIndex1 ]; 1738 const sal_Int32* pArray = rSubSeq.getConstArray(); 1739 for( sal_Int32 nIndex2 = 0; nIndex2 < rSubSeq.getLength(); nIndex2++ ) 1740 Append( pArray[ nIndex2 ] ); 1741 } 1742 } 1743 1744 1745 1746 void ScaDoubleList::Append( 1747 const ScaAnyConverter& rAnyConv, 1748 const uno::Any& rAny, 1749 sal_Bool bIgnoreEmpty ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 1750 { 1751 if( rAny.getValueTypeClass() == uno::TypeClass_SEQUENCE ) 1752 Append( rAnyConv, *static_cast< const uno::Sequence< uno::Sequence< uno::Any > >* >( rAny.getValue() ), bIgnoreEmpty ); 1753 else 1754 { 1755 double fValue; 1756 if( rAnyConv.getDouble( fValue, rAny ) ) 1757 Append( fValue ); 1758 else if( !bIgnoreEmpty ) 1759 Append( 0.0 ); 1760 } 1761 } 1762 1763 1764 void ScaDoubleList::Append( 1765 const ScaAnyConverter& rAnyConv, 1766 const uno::Sequence< uno::Any >& rAnySeq, 1767 sal_Bool bIgnoreEmpty ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 1768 { 1769 const uno::Any* pArray = rAnySeq.getConstArray(); 1770 for( sal_Int32 nIndex = 0; nIndex < rAnySeq.getLength(); nIndex++ ) 1771 Append( rAnyConv, pArray[ nIndex ], bIgnoreEmpty ); 1772 } 1773 1774 1775 void ScaDoubleList::Append( 1776 const ScaAnyConverter& rAnyConv, 1777 const uno::Sequence< uno::Sequence< uno::Any > >& rAnySeq, 1778 sal_Bool bIgnoreEmpty ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 1779 { 1780 const uno::Sequence< uno::Any >* pArray = rAnySeq.getConstArray(); 1781 for( sal_Int32 nIndex = 0; nIndex < rAnySeq.getLength(); nIndex++ ) 1782 Append( rAnyConv, pArray[ nIndex ], bIgnoreEmpty ); 1783 } 1784 1785 1786 1787 void ScaDoubleList::Append( 1788 ScaAnyConverter& rAnyConv, 1789 const uno::Reference< beans::XPropertySet >& xOpt, 1790 const uno::Sequence< uno::Any >& rAnySeq, 1791 sal_Bool bIgnoreEmpty ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 1792 { 1793 rAnyConv.init( xOpt ); 1794 Append( rAnyConv, rAnySeq, bIgnoreEmpty ); 1795 } 1796 1797 1798 sal_Bool ScaDoubleList::CheckInsert( double ) const throw( uno::RuntimeException, lang::IllegalArgumentException ) 1799 { 1800 return sal_True; 1801 } 1802 1803 1804 1805 //----------------------------------------------------------------------------- 1806 1807 sal_Bool ScaDoubleListGT0::CheckInsert( double fValue ) const throw( uno::RuntimeException, lang::IllegalArgumentException ) 1808 { 1809 if( fValue < 0.0 ) 1810 throw lang::IllegalArgumentException(); 1811 return fValue > 0.0; 1812 } 1813 1814 1815 1816 //----------------------------------------------------------------------------- 1817 1818 sal_Bool ScaDoubleListGE0::CheckInsert( double fValue ) const throw( uno::RuntimeException, lang::IllegalArgumentException ) 1819 { 1820 if( fValue < 0.0 ) 1821 throw lang::IllegalArgumentException(); 1822 return sal_True; 1823 } 1824 1825 1826 1827 //----------------------------------------------------------------------------- 1828 1829 Complex::Complex( const STRING& rStr ) THROWDEF_RTE_IAE 1830 { 1831 if( !ParseString( rStr, *this ) ) 1832 THROW_IAE; 1833 } 1834 1835 1836 inline sal_Bool Complex::IsImagUnit( sal_Unicode c ) 1837 { 1838 return c == 'i' || c == 'j'; 1839 } 1840 1841 sal_Bool Complex::ParseString( const STRING& rStr, Complex& rCompl ) 1842 { 1843 rCompl.c = '\0'; // do not force a symbol, if only real part present 1844 1845 const sal_Unicode* pStr = ( const sal_Unicode * ) rStr; 1846 1847 if( IsImagUnit( *pStr ) && rStr.getLength() == 1) 1848 { 1849 rCompl.r = 0.0; 1850 rCompl.i = 1.0; 1851 rCompl.c = *pStr; 1852 return sal_True; 1853 } 1854 1855 double f; 1856 1857 if( !ParseDouble( pStr, f ) ) 1858 return sal_False; 1859 1860 switch( *pStr ) 1861 { 1862 case '-': // imag part follows 1863 case '+': 1864 { 1865 double r = f; 1866 if( IsImagUnit( pStr[ 1 ] ) ) 1867 { 1868 rCompl.c = pStr[ 1 ]; 1869 if( pStr[ 2 ] == 0 ) 1870 { 1871 rCompl.r = f; 1872 rCompl.i = ( *pStr == '+' )? 1.0 : -1.0; 1873 return sal_True; 1874 } 1875 } 1876 else if( ParseDouble( pStr, f ) && IsImagUnit( *pStr ) ) 1877 { 1878 rCompl.c = *pStr; 1879 pStr++; 1880 if( *pStr == 0 ) 1881 { 1882 rCompl.r = r; 1883 rCompl.i = f; 1884 return sal_True; 1885 } 1886 } 1887 } 1888 break; 1889 case 'j': 1890 case 'i': 1891 rCompl.c = *pStr; 1892 pStr++; 1893 if( *pStr == 0 ) 1894 { 1895 rCompl.i = f; 1896 rCompl.r = 0.0; 1897 return sal_True; 1898 } 1899 break; 1900 case 0: // only real-part 1901 rCompl.r = f; 1902 rCompl.i = 0.0; 1903 return sal_True; 1904 } 1905 1906 return sal_False; 1907 } 1908 1909 1910 STRING Complex::GetString() const THROWDEF_RTE_IAE 1911 { 1912 static const String aI( 'i' ); 1913 static const String aJ( 'j' ); 1914 static const String aPlus( '+' ); 1915 static const String aMinus( '-' ); 1916 1917 CHK_FINITE(r); 1918 CHK_FINITE(i); 1919 STRING aRet; 1920 1921 bool bHasImag = i != 0.0; 1922 bool bHasReal = !bHasImag || (r != 0.0); 1923 1924 if( bHasReal ) 1925 aRet = ::GetString( r ); 1926 if( bHasImag ) 1927 { 1928 if( i == 1.0 ) 1929 { 1930 if( bHasReal ) 1931 aRet += aPlus; 1932 } 1933 else if( i == -1.0 ) 1934 aRet += aMinus; 1935 else 1936 aRet += ::GetString( i, bHasReal ); 1937 aRet += (c != 'j') ? aI : aJ; 1938 } 1939 1940 return aRet; 1941 } 1942 1943 1944 double Complex::Arg( void ) const THROWDEF_RTE_IAE 1945 { 1946 if( r == 0.0 && i == 0.0 ) 1947 THROW_IAE; 1948 1949 double phi = acos( r / Abs() ); 1950 1951 if( i < 0.0 ) 1952 phi = -phi; 1953 1954 return phi; 1955 } 1956 1957 1958 void Complex::Power( double fPower ) THROWDEF_RTE_IAE 1959 { 1960 if( r == 0.0 && i == 0.0 ) 1961 { 1962 if( fPower > 0 ) 1963 { 1964 r = i = 0.0; 1965 return; 1966 } 1967 else 1968 THROW_IAE; 1969 } 1970 1971 double p, phi; 1972 1973 p = Abs(); 1974 1975 phi = acos( r / p ); 1976 if( i < 0.0 ) 1977 phi = -phi; 1978 1979 p = pow( p, fPower ); 1980 phi *= fPower; 1981 1982 r = cos( phi ) * p; 1983 i = sin( phi ) * p; 1984 } 1985 1986 1987 void Complex::Sqrt( void ) 1988 { 1989 static const double fMultConst = 0.7071067811865475; // ...2440084436210485 = 1/sqrt(2) 1990 double p = Abs(); 1991 double i_ = sqrt( p - r ) * fMultConst; 1992 1993 r = sqrt( p + r ) * fMultConst; 1994 i = ( i < 0.0 )? -i_ : i_; 1995 } 1996 1997 1998 inline sal_Bool SinOverflow( double f ) 1999 { 2000 return fabs( f ) >= 134217728; 2001 } 2002 2003 2004 void Complex::Sin( void ) THROWDEF_RTE_IAE 2005 { 2006 if( SinOverflow( r ) ) 2007 THROW_IAE; 2008 2009 if( i ) 2010 { 2011 double r_; 2012 2013 r_ = sin( r ) * cosh( i ); 2014 i = cos( r ) * sinh( i ); 2015 r = r_; 2016 } 2017 else 2018 r = sin( r ); 2019 } 2020 2021 2022 void Complex::Cos( void ) THROWDEF_RTE_IAE 2023 { 2024 if( SinOverflow( r ) ) 2025 THROW_IAE; 2026 2027 if( i ) 2028 { 2029 double r_; 2030 2031 r_ = cos( r ) * cosh( i ); 2032 i = -( sin( r ) * sinh( i ) ); 2033 r = r_; 2034 } 2035 else 2036 r = cos( r ); 2037 } 2038 2039 2040 void Complex::Div( const Complex& z ) THROWDEF_RTE_IAE 2041 { 2042 if( z.r == 0 && z.i == 0 ) 2043 THROW_IAE; 2044 2045 double a1 = r; 2046 double a2 = z.r; 2047 double b1 = i; 2048 double b2 = z.i; 2049 2050 double f = 1.0 / ( a2 * a2 + b2 * b2 ); 2051 2052 r = ( a1 * a2 + b1 * b2 ) * f; 2053 i = ( a2 * b1 - a1 * b2 ) * f; 2054 2055 if( !c ) c = z.c; 2056 } 2057 2058 2059 void Complex::Exp( void ) 2060 { 2061 double fE = exp( r ); 2062 r = fE * cos( i ); 2063 i = fE * sin( i ); 2064 } 2065 2066 2067 void Complex::Ln( void ) THROWDEF_RTE_IAE 2068 { 2069 if( r == 0.0 && i == 0.0 ) 2070 THROW_IAE; 2071 2072 double fAbs = Abs(); 2073 sal_Bool bNegi = i < 0.0; 2074 2075 i = acos( r / fAbs ); 2076 2077 if( bNegi ) 2078 i = -i; 2079 2080 r = log( fAbs ); 2081 } 2082 2083 2084 void Complex::Log10( void ) THROWDEF_RTE_IAE 2085 { 2086 Ln(); 2087 Mult( 0.434294481903251828 ); // * log10( e ) 2088 } 2089 2090 2091 void Complex::Log2( void ) THROWDEF_RTE_IAE 2092 { 2093 Ln(); 2094 Mult( 1.442695040888963407 ); // * log2( e ) 2095 } 2096 2097 2098 2099 2100 ComplexList::~ComplexList() 2101 { 2102 for( Complex* p = ( Complex* ) First() ; p ; p = ( Complex* ) Next() ) 2103 delete p; 2104 } 2105 2106 2107 void ComplexList::Append( const SEQSEQ( STRING )& r, ComplListAppendHandl eAH ) THROWDEF_RTE_IAE 2108 { 2109 sal_Int32 n1, n2; 2110 sal_Int32 nE1 = r.getLength(); 2111 sal_Int32 nE2; 2112 sal_Bool bEmpty0 = eAH == AH_EmpyAs0; 2113 sal_Bool bErrOnEmpty = eAH == AH_EmptyAsErr; 2114 2115 for( n1 = 0 ; n1 < nE1 ; n1++ ) 2116 { 2117 const SEQ( STRING )& rList = r[ n1 ]; 2118 nE2 = rList.getLength(); 2119 2120 for( n2 = 0 ; n2 < nE2 ; n2++ ) 2121 { 2122 const STRING& rStr = rList[ n2 ]; 2123 2124 if( rStr.getLength() ) 2125 Append( new Complex( rStr ) ); 2126 else if( bEmpty0 ) 2127 Append( new Complex( 0.0 ) ); 2128 else if( bErrOnEmpty ) 2129 THROW_IAE; 2130 } 2131 } 2132 } 2133 2134 2135 void ComplexList::Append( const SEQ( ANY )& aMultPars, ComplListAppendHandl eAH ) THROWDEF_RTE_IAE 2136 { 2137 sal_Int32 nEle = aMultPars.getLength(); 2138 sal_Bool bEmpty0 = eAH == AH_EmpyAs0; 2139 sal_Bool bErrOnEmpty = eAH == AH_EmptyAsErr; 2140 2141 for( sal_Int32 i = 0 ; i < nEle ; i++ ) 2142 { 2143 const ANY& r = aMultPars[ i ]; 2144 switch( r.getValueTypeClass() ) 2145 { 2146 case uno::TypeClass_VOID: break; 2147 case uno::TypeClass_STRING: 2148 { 2149 const STRING* pStr = ( const STRING* ) r.getValue(); 2150 2151 if( pStr->getLength() ) 2152 Append( new Complex( *( STRING* ) r.getValue() ) ); 2153 else if( bEmpty0 ) 2154 Append( new Complex( 0.0 ) ); 2155 else if( bErrOnEmpty ) 2156 THROW_IAE; 2157 } 2158 break; 2159 case uno::TypeClass_DOUBLE: 2160 Append( new Complex( *( double* ) r.getValue(), 0.0 ) ); 2161 break; 2162 case uno::TypeClass_SEQUENCE: 2163 { 2164 SEQSEQ( ANY ) aValArr; 2165 if( r >>= aValArr ) 2166 { 2167 sal_Int32 nE = aValArr.getLength(); 2168 const SEQ( ANY )* pArr = aValArr.getConstArray(); 2169 for( sal_Int32 n = 0 ; n < nE ; n++ ) 2170 Append( pArr[ n ], eAH ); 2171 } 2172 else 2173 THROW_IAE; 2174 } 2175 break; 2176 default: 2177 THROW_IAE; 2178 } 2179 } 2180 } 2181 2182 2183 2184 2185 ConvertData::ConvertData( const sal_Char p[], double fC, ConvertDataClass e, sal_Bool bPrefSupport ) : aName( p, strlen( p ), RTL_TEXTENCODING_MS_1252 ) 2186 { 2187 fConst = fC; 2188 eClass = e; 2189 bPrefixSupport = bPrefSupport; 2190 } 2191 2192 ConvertData::~ConvertData() 2193 { 2194 } 2195 2196 2197 sal_Int16 ConvertData::GetMatchingLevel( const STRING& rRef ) const 2198 { 2199 STRING aStr = rRef; 2200 sal_Int32 nLen = rRef.getLength(); 2201 sal_Int32 nIndex = rRef.lastIndexOf( '^' ); 2202 if( nIndex > 0 && nIndex == ( nLen - 2 ) ) 2203 { 2204 const sal_Unicode* p = aStr.getStr(); 2205 aStr = STRING( p, nLen - 2 ); 2206 aStr += STRING( p[ nLen - 1 ] ); 2207 } 2208 if( aName.equals( aStr ) ) 2209 return 0; 2210 else 2211 { 2212 const sal_Unicode* p = aStr.getStr(); 2213 2214 nLen = aStr.getLength(); 2215 bool bPref = IsPrefixSupport(); 2216 bool bOneChar = (bPref && nLen > 1 && (aName == p + 1)); 2217 if (bOneChar || (bPref && nLen > 2 && (aName == p + 2) && 2218 *p == 'd' && *(p+1) == 'a')) 2219 { 2220 sal_Int16 n; 2221 switch( *p ) 2222 { 2223 case 'y': n = -24; break; // yocto 2224 case 'z': n = -21; break; // zepto 2225 case 'a': n = -18; break; 2226 case 'f': n = -15; break; 2227 case 'p': n = -12; break; 2228 case 'n': n = -9; break; 2229 case 'u': n = -6; break; 2230 case 'm': n = -3; break; 2231 case 'c': n = -2; break; 2232 case 'd': 2233 { 2234 if ( bOneChar ) 2235 n = -1; // deci 2236 else 2237 n = 1; // deca 2238 } 2239 break; 2240 case 'e': n = 1; break; 2241 case 'h': n = 2; break; 2242 case 'k': n = 3; break; 2243 case 'M': n = 6; break; 2244 case 'G': n = 9; break; 2245 case 'T': n = 12; break; 2246 case 'P': n = 15; break; 2247 case 'E': n = 18; break; 2248 case 'Z': n = 21; break; // zetta 2249 case 'Y': n = 24; break; // yotta 2250 default: 2251 n = INV_MATCHLEV; 2252 } 2253 2254 // We could weed some nonsense out, ODFF doesn't say so though. 2255 #if 0 2256 if (n < 0 && Class() == CDC_Information) 2257 n = INV_MATCHLEV; // milli-bits doesn't make sense 2258 #endif 2259 2260 //! <HACK> #100616# "cm3" is not 10^-2 m^3 but 10^-6 m^3 !!! ------------------ 2261 if( n != INV_MATCHLEV ) 2262 { 2263 sal_Unicode cLast = p[ aStr.getLength() - 1 ]; 2264 if( cLast == '2' ) 2265 n *= 2; 2266 else if( cLast == '3' ) 2267 n *= 3; 2268 } 2269 //! </HACK> ------------------------------------------------------------------- 2270 2271 return n; 2272 } 2273 else if ( nLen > 2 && ( aName == p + 2 ) && ( Class() == CDC_Information ) ) 2274 { 2275 const sal_Unicode* pStr = aStr.getStr(); 2276 if ( *(pStr + 1) != 'i') 2277 return INV_MATCHLEV; 2278 sal_Int16 n; 2279 switch( *pStr ) 2280 { 2281 case 'k': n = 10; break; 2282 case 'M': n = 20; break; 2283 case 'G': n = 30; break; 2284 case 'T': n = 40; break; 2285 case 'P': n = 50; break; 2286 case 'E': n = 60; break; 2287 case 'Z': n = 70; break; 2288 case 'Y': n = 80; break; 2289 default: 2290 n = INV_MATCHLEV; 2291 } 2292 return n; 2293 } 2294 else 2295 return INV_MATCHLEV; 2296 } 2297 } 2298 2299 2300 double ConvertData::Convert( 2301 double f, const ConvertData& r, sal_Int16 nLevFrom, sal_Int16 nLevTo ) const THROWDEF_RTE_IAE 2302 { 2303 if( Class() != r.Class() ) 2304 THROW_IAE; 2305 2306 sal_Bool bBinFromLev = ( nLevFrom > 0 && ( nLevFrom % 10 ) == 0 ); 2307 sal_Bool bBinToLev = ( nLevTo > 0 && ( nLevTo % 10 ) == 0 ); 2308 2309 if ( Class() == CDC_Information && ( bBinFromLev || bBinToLev ) ) 2310 { 2311 if ( bBinFromLev && bBinToLev ) 2312 { 2313 nLevFrom = sal::static_int_cast<sal_Int16>( nLevFrom - nLevTo ); 2314 f *= r.fConst / fConst; 2315 if( nLevFrom ) 2316 f *= pow( 2.0, nLevFrom ); 2317 } 2318 else if ( bBinFromLev ) 2319 f *= ( r.fConst / fConst ) * ( pow( 2.0, nLevFrom ) / pow( 10.0, nLevTo ) ); 2320 else 2321 f *= ( r.fConst / fConst ) * ( pow( 10.0, nLevFrom ) / pow( 2.0, nLevTo ) ); 2322 return f; 2323 } 2324 2325 nLevFrom = sal::static_int_cast<sal_Int16>( nLevFrom - nLevTo ); // effective level 2326 2327 f *= r.fConst / fConst; 2328 2329 if( nLevFrom ) 2330 f = ::rtl::math::pow10Exp( f, nLevFrom ); 2331 2332 return f; 2333 } 2334 2335 2336 double ConvertData::ConvertToBase( double f, sal_Int16 n ) const 2337 { 2338 return ::rtl::math::pow10Exp( f / fConst, n ); 2339 } 2340 2341 2342 double ConvertData::ConvertFromBase( double f, sal_Int16 n ) const 2343 { 2344 return ::rtl::math::pow10Exp( f * fConst, -n ); 2345 } 2346 2347 2348 2349 ConvertDataLinear::~ConvertDataLinear() 2350 { 2351 } 2352 2353 double ConvertDataLinear::Convert( 2354 double f, const ConvertData& r, sal_Int16 nLevFrom, sal_Int16 nLevTo ) const THROWDEF_RTE_IAE 2355 { 2356 if( Class() != r.Class() ) 2357 THROW_IAE; 2358 2359 // return ::rtl::math::round( r.ConvertFromBase( ConvertToBase( f, nLevFrom ), nLevTo ), 13 ); 2360 return r.ConvertFromBase( ConvertToBase( f, nLevFrom ), nLevTo ); 2361 } 2362 2363 2364 double ConvertDataLinear::ConvertToBase( double f, sal_Int16 n ) const 2365 { 2366 if( n ) 2367 f = ::rtl::math::pow10Exp( f, n ); 2368 2369 f /= fConst; 2370 f -= fOffs; 2371 2372 return f; 2373 } 2374 2375 2376 double ConvertDataLinear::ConvertFromBase( double f, sal_Int16 n ) const 2377 { 2378 f += fOffs; 2379 f *= fConst; 2380 2381 if( n ) 2382 f = ::rtl::math::pow10Exp( f, -n ); 2383 2384 return f; 2385 } 2386 2387 2388 2389 2390 ConvertDataList::ConvertDataList( void ) 2391 { 2392 #define NEWD(str,unit,cl) Append(new ConvertData(str,unit,cl)) 2393 #define NEWDP(str,unit,cl) Append(new ConvertData(str,unit,cl,sal_True)) 2394 #define NEWL(str,unit,offs,cl) Append(new ConvertDataLinear(str,unit,offs,cl)) 2395 #define NEWLP(str,unit,offs,cl) Append(new ConvertDataLinear(str,unit,offs,cl,sal_True)) 2396 2397 // *** are extra and not standard Excel Analysis Addin! 2398 2399 // MASS: 1 Gram is... 2400 NEWDP( "g", 1.0000000000000000E00, CDC_Mass ); // Gram 2401 NEWD( "sg", 6.8522050005347800E-05, CDC_Mass ); // Pieces 2402 NEWD( "lbm", 2.2046229146913400E-03, CDC_Mass ); // Pound (commercial weight) 2403 NEWDP( "u", 6.0221370000000000E23, CDC_Mass ); // U (atomic mass) 2404 NEWD( "ozm", 3.5273971800362700E-02, CDC_Mass ); // Ounce (commercial weight) 2405 NEWD( "stone", 1.574730e-04, CDC_Mass ); // *** Stone 2406 NEWD( "ton", 1.102311e-06, CDC_Mass ); // *** Ton 2407 NEWD( "grain", 1.543236E01, CDC_Mass ); // *** Grain 2408 NEWD( "pweight", 7.054792E-01, CDC_Mass ); // *** Pennyweight 2409 NEWD( "hweight", 1.968413E-05, CDC_Mass ); // *** Hundredweight 2410 NEWD( "shweight", 2.204623E-05, CDC_Mass ); // *** Shorthundredweight 2411 NEWD( "brton", 9.842065E-07, CDC_Mass ); // *** Gross Registered Ton 2412 NEWD( "cwt", 2.2046226218487758E-05, CDC_Mass ); // U.S. (short) hundredweight 2413 NEWD( "shweight", 2.2046226218487758E-05, CDC_Mass ); // U.S. (short) hundredweight also 2414 NEWD( "uk_cwt", 1.9684130552221213E-05, CDC_Mass ); // Imperial hundredweight 2415 NEWD( "lcwt", 1.9684130552221213E-05, CDC_Mass ); // Imperial hundredweight also 2416 NEWD( "hweight", 1.9684130552221213E-05, CDC_Mass ); // Imperial hundredweight also 2417 NEWD( "uk_ton", 9.8420652761106063E-07, CDC_Mass ); // Imperial ton 2418 NEWD( "LTON", 9.8420652761106063E-07, CDC_Mass ); // Imperial ton also 2419 2420 // LENGTH: 1 Meter is... 2421 NEWDP( "m", 1.0000000000000000E00, CDC_Length ); // Meter 2422 NEWD( "mi", 6.2137119223733397E-04, CDC_Length ); // Britsh Mile 6,21371192237333969617434184363e-4 2423 NEWD( "Nmi", 5.3995680345572354E-04, CDC_Length ); // Nautical Mile 5,39956803455723542116630669546e-4 2424 NEWD( "in", 3.9370078740157480E01, CDC_Length ); // Inch 39,37007874015748031496062992126 2425 NEWD( "ft", 3.2808398950131234E00, CDC_Length ); // Foot 3,2808398950131233595800524934383 2426 NEWD( "yd", 1.0936132983377078E00, CDC_Length ); // Yard 1,0936132983377077865266841644794 2427 NEWDP( "ang", 1.0000000000000000E10, CDC_Length ); // Angstroem 2428 NEWD( "Pica", 2.8346456692913386E03, CDC_Length ); // Pica (1/72 Inch) 2834,6456692913385826771653543307 2429 NEWD( "ell", 8.748906E-01, CDC_Length ); // *** Ell 2430 NEWDP( "parsec", 3.240779E-17, CDC_Length ); // *** Parsec 2431 NEWDP( "pc", 3.240779E-17, CDC_Length ); // *** Parsec also 2432 NEWDP( "lightyear", 1.0570234557732930E-16, CDC_Length ); // *** Light Year 2433 NEWDP( "ly", 1.0570234557732930E-16, CDC_Length ); // *** Light Year also 2434 NEWD( "survey_mi", 6.2136994949494949E-04, CDC_Length ); // U.S. survey mile 2435 2436 // TIME: 1 Second is... 2437 NEWD( "yr", 3.1688087814028950E-08, CDC_Time ); // Year 2438 NEWD( "day", 1.1574074074074074E-05, CDC_Time ); // Day 2439 NEWD( "d", 1.1574074074074074E-05, CDC_Time ); // Day also 2440 NEWD( "hr", 2.7777777777777778E-04, CDC_Time ); // Hour 2441 NEWD( "mn", 1.6666666666666667E-02, CDC_Time ); // Minute 2442 NEWD( "min", 1.6666666666666667E-02, CDC_Time ); // Minute also 2443 NEWDP( "sec", 1.0000000000000000E00, CDC_Time ); // Second 2444 NEWDP( "s", 1.0000000000000000E00, CDC_Time ); // Second also 2445 2446 // PRESSURE: 1 Pascal is... 2447 NEWDP( "Pa", 1.0000000000000000E00, CDC_Pressure ); // Pascal 2448 NEWDP( "atm", 9.8692329999819300E-06, CDC_Pressure ); // Atmosphere 2449 NEWDP( "at", 9.8692329999819300E-06, CDC_Pressure ); // Atmosphere also 2450 NEWDP( "mmHg", 7.5006170799862700E-03, CDC_Pressure ); // mm Hg (Mercury) 2451 NEWD( "Torr", 7.5006380000000000E-03, CDC_Pressure ); // *** Torr 2452 NEWD( "psi", 1.4503770000000000E-04, CDC_Pressure ); // *** Psi 2453 2454 // FORCE: 1 Newton is... 2455 NEWDP( "N", 1.0000000000000000E00, CDC_Force ); // Newton 2456 NEWDP( "dyn", 1.0000000000000000E05, CDC_Force ); // Dyn 2457 NEWDP( "dy", 1.0000000000000000E05, CDC_Force ); // Dyn also 2458 NEWD( "lbf", 2.24808923655339E-01, CDC_Force ); // Pound-Force 2459 NEWDP( "pond", 1.019716E02, CDC_Force ); // *** Pond 2460 2461 // ENERGY: 1 Joule is... 2462 NEWDP( "J", 1.0000000000000000E00, CDC_Energy ); // Joule 2463 NEWDP( "e", 1.0000000000000000E07, CDC_Energy ); // Erg -> http://www.chemie.fu-berlin.de/chemistry/general/si.html 2464 // NEWD( "e", 9.99999519343231E06, CDC_Energy ); // Erg 2465 NEWDP( "c", 2.3900624947346700E-01, CDC_Energy ); // Thermodynamical Calorie 2466 NEWDP( "cal", 2.3884619064201700E-01, CDC_Energy ); // Calorie 2467 NEWDP( "eV", 6.2414570000000000E18, CDC_Energy ); // Electronvolt 2468 NEWDP( "ev", 6.2414570000000000E18, CDC_Energy ); // Electronvolt also 2469 NEWD( "HPh", 3.7250611111111111E-07, CDC_Energy ); // Horsepower Hours 2470 NEWD( "hh", 3.7250611111111111E-07, CDC_Energy ); // Horsepower Hours also 2471 // NEWD( "HPh", 3.72506430801000E-07, CDC_Energy ); // Horsepower Hours 2472 NEWDP( "Wh", 2.7777777777777778E-04, CDC_Energy ); // Watt Hours 2473 NEWDP( "wh", 2.7777777777777778E-04, CDC_Energy ); // Watt Hours also 2474 NEWD( "flb", 2.37304222192651E01, CDC_Energy ); // Foot Pound 2475 NEWD( "BTU", 9.4781506734901500E-04, CDC_Energy ); // British Thermal Unit 2476 NEWD( "btu", 9.4781506734901500E-04, CDC_Energy ); // British Thermal Unit also 2477 2478 // POWER: 1 Watt is... 2479 NEWDP( "W", 1.0000000000000000E00, CDC_Power ); // Watt 2480 NEWDP( "w", 1.0000000000000000E00, CDC_Power ); // Watt also 2481 NEWD( "HP", 1.341022E-03, CDC_Power ); // Horsepower 2482 NEWD( "h", 1.341022E-03, CDC_Power ); // Horsepower also 2483 NEWD( "PS", 1.359622E-03, CDC_Power ); // *** German Pferdestaerke 2484 // NEWD( "HP", 1.4102006031908E-03, CDC_Power ); // Excel seams to be a little bit wrong... either this doesn't fit to J -> HPh 2485 2486 // MAGNETISM: 1 Tesla is... 2487 NEWDP( "T", 1.0000000000000000E00, CDC_Magnetism ); // Tesla 2488 NEWDP( "ga", 1.0000000000000000E04, CDC_Magnetism ); // Gauss 2489 2490 // TEMERATURE: 1 Kelvin is... 2491 NEWL( "C", 1.0000000000000000E00, -2.7315000000000000E02, CDC_Temperature ); // Celsius 2492 NEWL( "cel", 1.0000000000000000E00, -2.7315000000000000E02, CDC_Temperature ); // Celsius also 2493 NEWL( "F", 1.8000000000000000E00, -2.5537222222222222E02, CDC_Temperature ); // Fahrenheit 2494 NEWL( "fah", 1.8000000000000000E00, -2.5537222222222222E02, CDC_Temperature ); // Fahrenheit also 2495 NEWLP( "K", 1.0000000000000000E00, +0.0000000000000000E00, CDC_Temperature ); // Kelvin 2496 NEWLP( "kel", 1.0000000000000000E00, +0.0000000000000000E00, CDC_Temperature ); // Kelvin also 2497 NEWL( "Reau", 8.0000000000000000E-01, -2.7315000000000000E02, CDC_Temperature ); // *** Reaumur 2498 NEWL( "Rank", 1.8000000000000000E00, +0.0000000000000000E00, CDC_Temperature ); // *** Rankine 2499 2500 // VOLUMNE: 1 Liter is... 2501 NEWD( "tsp", 2.0284000000000000E02, CDC_Volume ); // Teaspoon 2502 NEWD( "tbs", 6.7613333333333333E01, CDC_Volume ); // Tablespoon 2503 NEWD( "oz", 3.3806666666666667E01, CDC_Volume ); // Ounce Liquid 2504 NEWD( "cup", 4.2258333333333333E00, CDC_Volume ); // Cup 2505 NEWD( "pt", 2.1129166666666667E00, CDC_Volume ); // US Pint 2506 NEWD( "us_pt", 2.1129166666666667E00, CDC_Volume ); // US Pint also 2507 NEWD( "uk_pt", 1.75975569552166E00, CDC_Volume ); // UK Pint 2508 NEWD( "qt", 1.0564583333333333E00, CDC_Volume ); // Quart 2509 NEWD( "gal", 2.6411458333333333E-01, CDC_Volume ); // Gallone 2510 NEWDP( "l", 1.0000000000000000E00, CDC_Volume ); // Liter 2511 NEWDP( "L", 1.0000000000000000E00, CDC_Volume ); // Liter also 2512 NEWDP( "lt", 1.0000000000000000E00, CDC_Volume ); // Liter also 2513 NEWDP( "m3", 1.0000000000000000E-03, CDC_Volume ); // *** Cubic Meter 2514 NEWD( "mi3", 2.3991275857892772E-13, CDC_Volume ); // *** Cubic Britsh Mile 2515 NEWD( "Nmi3", 1.5742621468581148E-13, CDC_Volume ); // *** Cubic Nautical Mile 2516 NEWD( "in3", 6.1023744094732284E01, CDC_Volume ); // *** Cubic Inch 2517 NEWD( "ft3", 3.5314666721488590E-02, CDC_Volume ); // *** Cubic Foot 2518 NEWD( "yd3", 1.3079506193143922E-03, CDC_Volume ); // *** Cubic Yard 2519 NEWDP( "ang3", 1.0000000000000000E27, CDC_Volume ); // *** Cubic Angstroem 2520 NEWD( "Pica3", 2.2776990435870636E07, CDC_Volume ); // *** Cubic Pica 2521 NEWD( "barrel", 6.289811E-03, CDC_Volume ); // *** Barrel (=42gal?) 2522 NEWD( "bushel", 2.837759E-02, CDC_Volume ); // *** Bushel 2523 NEWD( "regton", 3.531467E-04, CDC_Volume ); // *** Register ton 2524 NEWD( "GRT", 3.531467E-04, CDC_Volume ); // *** Register ton also 2525 NEWD( "Schooner", 2.3529411764705882E00, CDC_Volume ); // *** austr. Schooner 2526 NEWD( "Middy", 3.5087719298245614E00, CDC_Volume ); // *** austr. Middy 2527 NEWD( "Glass", 5.0000000000000000E00, CDC_Volume ); // *** austr. Glass 2528 NEWD( "Sixpack", 0.5, CDC_Volume ); // *** 2529 NEWD( "Humpen", 2.0, CDC_Volume ); // *** 2530 NEWD( "ly3", 1.1810108125623799E-51, CDC_Volume ); // *** Cubic light-year 2531 NEWD( "MTON", 1.4125866688595436E00, CDC_Volume ); // *** Measurement ton 2532 NEWD( "tspm", 5.0000000000000000E02, CDC_Volume ); // *** Modern teaspoon 2533 NEWD( "uk_gal", 2.199694619402070E-01, CDC_Volume ); // U.K. / Imperial gallon 2534 NEWD( "uk_qt", 8.798778477608300E-01, CDC_Volume ); // U.K. / Imperial quart 2535 2536 // 1 Square Meter is... 2537 NEWDP( "m2", 1.0000000000000000E00, CDC_Area ); // *** Square Meter 2538 NEWD( "mi2", 3.8610215854244585E-07, CDC_Area ); // *** Square Britsh Mile 2539 NEWD( "Nmi2", 2.9155334959812286E-07, CDC_Area ); // *** Square Nautical Mile 2540 NEWD( "in2", 1.5500031000062000E03, CDC_Area ); // *** Square Inch 2541 NEWD( "ft2", 1.0763910416709722E01, CDC_Area ); // *** Square Foot 2542 NEWD( "yd2", 1.1959900463010803E00, CDC_Area ); // *** Square Yard 2543 NEWDP( "ang2", 1.0000000000000000E20, CDC_Area ); // *** Square Angstroem 2544 NEWD( "Pica2", 8.0352160704321409E06, CDC_Area ); // *** Square Pica 2545 NEWD( "Morgen", 4.0000000000000000E-04, CDC_Area ); // *** Morgen 2546 NEWDP( "ar", 1.000000E-02, CDC_Area ); // *** Ar 2547 NEWD( "acre", 2.471053815E-04, CDC_Area ); // *** Acre 2548 NEWD( "uk_acre", 2.4710538146716534E-04, CDC_Area ); // *** International acre 2549 NEWD( "us_acre", 2.4710439304662790E-04, CDC_Area ); // *** U.S. survey/statute acre 2550 NEWD( "ly2", 1.1172985860549147E-32, CDC_Area ); // *** Square Light-year 2551 NEWD( "ha", 1.000000E-04, CDC_Area ); // *** Hectare 2552 NEWD( "Quadratlatschen",5.6689342403628117914,CDC_Area ); // *** 2553 2554 // SPEED: 1 Meter per Second is... 2555 NEWDP( "m/s", 1.0000000000000000E00, CDC_Speed ); // *** Meters per Second 2556 NEWDP( "m/sec", 1.0000000000000000E00, CDC_Speed ); // *** Meters per Second also 2557 NEWDP( "m/h", 3.6000000000000000E03, CDC_Speed ); // *** Meters per Hour 2558 NEWDP( "m/hr", 3.6000000000000000E03, CDC_Speed ); // *** Meters per Hour also 2559 NEWD( "mph", 2.2369362920544023E00, CDC_Speed ); // *** Britsh Miles per Hour 2560 NEWD( "kn", 1.9438444924406048E00, CDC_Speed ); // *** Knot = Nautical Miles per Hour 2561 NEWD( "admkn", 1.9438446603753486E00, CDC_Speed ); // *** Admiralty Knot 2562 NEWD( "wahnsinnige Geschwindigkeit", 2.0494886343432328E-14, CDC_Speed ); // *** 2563 NEWD( "ludicrous speed", 2.0494886343432328E-14, CDC_Speed ); // *** 2564 NEWD( "laecherliche Geschwindigkeit", 4.0156958471424288E-06, CDC_Speed); // *** 2565 NEWD( "ridiculous speed", 4.0156958471424288E-06, CDC_Speed); // *** 2566 2567 // INFORMATION: 1 Bit is... 2568 NEWDP( "bit", 1.00E00, CDC_Information); // *** Bit 2569 NEWDP( "byte", 1.25E-01, CDC_Information); // *** Byte 2570 } 2571 2572 2573 ConvertDataList::~ConvertDataList() 2574 { 2575 for( ConvertData* p = First() ; p ; p = Next() ) 2576 delete p; 2577 } 2578 2579 2580 double ConvertDataList::Convert( double fVal, const STRING& rFrom, const STRING& rTo ) THROWDEF_RTE_IAE 2581 { 2582 // This will not catch illegal units 2583 // if( rFrom == rTo ) 2584 // return fVal; 2585 2586 ConvertData* pFrom = NULL; 2587 ConvertData* pTo = NULL; 2588 sal_Bool bSearchFrom = sal_True; 2589 sal_Bool bSearchTo = sal_True; 2590 sal_Int16 nLevelFrom = 0; 2591 sal_Int16 nLevelTo = 0; 2592 2593 ConvertData* p = First(); 2594 while( p && ( bSearchFrom || bSearchTo ) ) 2595 { 2596 if( bSearchFrom ) 2597 { 2598 sal_Int16 n = p->GetMatchingLevel( rFrom ); 2599 if( n != INV_MATCHLEV ) 2600 { 2601 if( n ) 2602 { // only first match for partial equality rulz a little bit more 2603 pFrom = p; 2604 nLevelFrom = n; 2605 } 2606 else 2607 { // ... but exact match rulz most 2608 pFrom = p; 2609 bSearchFrom = sal_False; 2610 nLevelFrom = n; 2611 } 2612 } 2613 } 2614 2615 if( bSearchTo ) 2616 { 2617 sal_Int16 n = p->GetMatchingLevel( rTo ); 2618 if( n != INV_MATCHLEV ) 2619 { 2620 if( n ) 2621 { // only first match for partial equality rulz a little bit more 2622 pTo = p; 2623 nLevelTo = n; 2624 } 2625 else 2626 { // ... but exact match rulz most 2627 pTo = p; 2628 bSearchTo = sal_False; 2629 nLevelTo = n; 2630 } 2631 } 2632 } 2633 2634 p = Next(); 2635 } 2636 2637 if( pFrom && pTo ) 2638 return pFrom->Convert( fVal, *pTo, nLevelFrom, nLevelTo ); 2639 else 2640 THROW_IAE; 2641 } 2642 2643 2644 2645 //----------------------------------------------------------------------------- 2646 2647 ScaDate::ScaDate() : 2648 nOrigDay( 1 ), 2649 nDay( 1 ), 2650 nMonth( 1 ), 2651 nYear( 1900 ), 2652 bLastDayMode( sal_True ), 2653 bLastDay( sal_False ), 2654 b30Days( sal_False ), 2655 bUSMode( sal_False ) 2656 { 2657 } 2658 2659 ScaDate::ScaDate( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nBase ) 2660 { 2661 DaysToDate( nNullDate + nDate, nOrigDay, nMonth, nYear ); 2662 bLastDayMode = (nBase != 5); 2663 bLastDay = (nOrigDay >= ::DaysInMonth( nMonth, nYear )); 2664 b30Days = (nBase == 0) || (nBase == 4); 2665 bUSMode = (nBase == 0); 2666 setDay(); 2667 } 2668 2669 ScaDate::ScaDate( const ScaDate& rCopy ) : 2670 nOrigDay( rCopy.nOrigDay ), 2671 nDay( rCopy.nDay ), 2672 nMonth( rCopy.nMonth ), 2673 nYear( rCopy.nYear ), 2674 bLastDayMode( rCopy.bLastDayMode ), 2675 bLastDay( rCopy.bLastDay ), 2676 b30Days( rCopy.b30Days ), 2677 bUSMode( rCopy.bUSMode ) 2678 { 2679 } 2680 2681 ScaDate& ScaDate::operator=( const ScaDate& rCopy ) 2682 { 2683 if( this != &rCopy ) 2684 { 2685 nOrigDay = rCopy.nOrigDay; 2686 nDay = rCopy.nDay; 2687 nMonth = rCopy.nMonth; 2688 nYear = rCopy.nYear; 2689 bLastDayMode = rCopy.bLastDayMode; 2690 bLastDay = rCopy.bLastDay; 2691 b30Days = rCopy.b30Days; 2692 bUSMode = rCopy.bUSMode; 2693 } 2694 return *this; 2695 } 2696 2697 void ScaDate::setDay() 2698 { 2699 if( b30Days ) 2700 { 2701 // 30-days-mode: set nDay to 30 if original was last day in month 2702 nDay = Min( nOrigDay, static_cast< sal_uInt16 >( 30 ) ); 2703 if( bLastDay || (nDay >= ::DaysInMonth( nMonth, nYear )) ) 2704 nDay = 30; 2705 } 2706 else 2707 { 2708 // set nDay to last day in this month if original was last day 2709 sal_uInt16 nLastDay = ::DaysInMonth( nMonth, nYear ); 2710 nDay = bLastDay ? nLastDay : Min( nOrigDay, nLastDay ); 2711 } 2712 } 2713 2714 sal_Int32 ScaDate::getDaysInMonthRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const 2715 { 2716 if( nFrom > nTo ) 2717 return 0; 2718 2719 sal_Int32 nRet = 0; 2720 if( b30Days ) 2721 nRet = (nTo - nFrom + 1) * 30; 2722 else 2723 { 2724 for( sal_uInt16 nMonthIx = nFrom; nMonthIx <= nTo; ++nMonthIx ) 2725 nRet += getDaysInMonth( nMonthIx ); 2726 } 2727 return nRet; 2728 } 2729 2730 sal_Int32 ScaDate::getDaysInYearRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const 2731 { 2732 if( nFrom > nTo ) 2733 return 0; 2734 2735 return b30Days ? ((nTo - nFrom + 1) * 360) : ::GetDaysInYears( nFrom, nTo ); 2736 } 2737 2738 void ScaDate::doAddYears( sal_Int32 nYearCount ) throw( lang::IllegalArgumentException ) 2739 { 2740 sal_Int32 nNewYear = nYearCount + nYear; 2741 if( (nNewYear < 0) || (nNewYear > 0x7FFF) ) 2742 throw lang::IllegalArgumentException(); 2743 nYear = static_cast< sal_uInt16 >( nNewYear ); 2744 } 2745 2746 void ScaDate::addMonths( sal_Int32 nMonthCount ) throw( lang::IllegalArgumentException ) 2747 { 2748 sal_Int32 nNewMonth = nMonthCount + nMonth; 2749 if( nNewMonth > 12 ) 2750 { 2751 --nNewMonth; 2752 doAddYears( nNewMonth / 12 ); 2753 nMonth = static_cast< sal_uInt16 >( nNewMonth % 12 ) + 1; 2754 } 2755 else if( nNewMonth < 1 ) 2756 { 2757 doAddYears( nNewMonth / 12 - 1 ); 2758 nMonth = static_cast< sal_uInt16 >( nNewMonth % 12 + 12 ); 2759 } 2760 else 2761 nMonth = static_cast< sal_uInt16 >( nNewMonth ); 2762 setDay(); 2763 } 2764 2765 sal_Int32 ScaDate::getDate( sal_Int32 nNullDate ) const 2766 { 2767 sal_uInt16 nLastDay = ::DaysInMonth( nMonth, nYear ); 2768 sal_uInt16 nRealDay = (bLastDayMode && bLastDay) ? nLastDay : Min( nLastDay, nOrigDay ); 2769 return ::DateToDays( nRealDay, nMonth, nYear ) - nNullDate; 2770 } 2771 2772 sal_Int32 ScaDate::getDiff( const ScaDate& rFrom, const ScaDate& rTo ) throw( lang::IllegalArgumentException ) 2773 { 2774 if( rFrom > rTo ) 2775 return getDiff( rTo, rFrom ); 2776 2777 sal_Int32 nDiff = 0; 2778 ScaDate aFrom( rFrom ); 2779 ScaDate aTo( rTo ); 2780 2781 if( rTo.b30Days ) 2782 { 2783 // corrections for base 0 (US NASD) 2784 if( rTo.bUSMode ) 2785 { 2786 if( ((rFrom.nMonth == 2) || (rFrom.nDay < 30)) && (aTo.nOrigDay == 31) ) 2787 aTo.nDay = 31; 2788 else if( (aTo.nMonth == 2) && aTo.bLastDay ) 2789 aTo.nDay = ::DaysInMonth( 2, aTo.nYear ); 2790 } 2791 // corrections for base 4 (Europe) 2792 else 2793 { 2794 if( (aFrom.nMonth == 2) && (aFrom.nDay == 30) ) 2795 aFrom.nDay = ::DaysInMonth( 2, aFrom.nYear ); 2796 if( (aTo.nMonth == 2) && (aTo.nDay == 30) ) 2797 aTo.nDay = ::DaysInMonth( 2, aTo.nYear ); 2798 } 2799 } 2800 2801 if( (aFrom.nYear < aTo.nYear) || ((aFrom.nYear == aTo.nYear) && (aFrom.nMonth < aTo.nMonth)) ) 2802 { 2803 // move aFrom to 1st day of next month 2804 nDiff = aFrom.getDaysInMonth() - aFrom.nDay + 1; 2805 aFrom.nOrigDay = aFrom.nDay = 1; 2806 aFrom.bLastDay = sal_False; 2807 aFrom.addMonths( 1 ); 2808 2809 if( aFrom.nYear < aTo.nYear ) 2810 { 2811 // move aFrom to 1st day of next year 2812 nDiff += aFrom.getDaysInMonthRange( aFrom.nMonth, 12 ); 2813 aFrom.addMonths( 13 - aFrom.nMonth ); 2814 2815 // move aFrom to 1st day of this year 2816 nDiff += aFrom.getDaysInYearRange( aFrom.nYear, aTo.nYear - 1 ); 2817 aFrom.addYears( aTo.nYear - aFrom.nYear ); 2818 } 2819 2820 // move aFrom to 1st day of this month 2821 nDiff += aFrom.getDaysInMonthRange( aFrom.nMonth, aTo.nMonth - 1 ); 2822 aFrom.addMonths( aTo.nMonth - aFrom.nMonth ); 2823 } 2824 // finally add remaining days in this month 2825 nDiff += aTo.nDay - aFrom.nDay; 2826 return nDiff > 0 ? nDiff : 0; 2827 } 2828 2829 sal_Bool ScaDate::operator<( const ScaDate& rCmp ) const 2830 { 2831 if( nYear != rCmp.nYear ) 2832 return nYear < rCmp.nYear; 2833 if( nMonth != rCmp.nMonth ) 2834 return nMonth < rCmp.nMonth; 2835 if( nDay != rCmp.nDay ) 2836 return nDay < rCmp.nDay; 2837 if( bLastDay || rCmp.bLastDay ) 2838 return !bLastDay && rCmp.bLastDay; 2839 return nOrigDay < rCmp.nOrigDay; 2840 } 2841 2842 2843 2844 //----------------------------------------------------------------------------- 2845 2846 ScaAnyConverter::ScaAnyConverter( const uno::Reference< lang::XMultiServiceFactory >& xServiceFact ) : 2847 bHasValidFormat( sal_False ) 2848 { 2849 if( xServiceFact.is() ) 2850 { 2851 uno::Reference< uno::XInterface > xInstance = xServiceFact->createInstance( 2852 OUString::createFromAscii( "com.sun.star.util.NumberFormatter" ) ); 2853 xFormatter = uno::Reference< util::XNumberFormatter >( xInstance, uno::UNO_QUERY ); 2854 } 2855 } 2856 2857 ScaAnyConverter::~ScaAnyConverter() 2858 { 2859 } 2860 2861 void ScaAnyConverter::init( const uno::Reference< beans::XPropertySet >& xPropSet ) throw( uno::RuntimeException ) 2862 { 2863 // try to get default number format 2864 bHasValidFormat = sal_False; 2865 if( xFormatter.is() ) 2866 { 2867 // get XFormatsSupplier from outer XPropertySet 2868 uno::Reference< util::XNumberFormatsSupplier > xFormatsSupp( xPropSet, uno::UNO_QUERY ); 2869 if( xFormatsSupp.is() ) 2870 { 2871 // get XNumberFormatTypes from XNumberFormatsSupplier to get standard index 2872 uno::Reference< util::XNumberFormats > xFormats( xFormatsSupp->getNumberFormats() ); 2873 uno::Reference< util::XNumberFormatTypes > xFormatTypes( xFormats, uno::UNO_QUERY ); 2874 if( xFormatTypes.is() ) 2875 { 2876 lang::Locale eLocale; 2877 nDefaultFormat = xFormatTypes->getStandardIndex( eLocale ); 2878 xFormatter->attachNumberFormatsSupplier( xFormatsSupp ); 2879 bHasValidFormat = sal_True; 2880 } 2881 } 2882 } 2883 } 2884 2885 double ScaAnyConverter::convertToDouble( const OUString& rString ) const throw( lang::IllegalArgumentException ) 2886 { 2887 double fValue = 0.0; 2888 if( bHasValidFormat ) 2889 { 2890 try 2891 { 2892 fValue = xFormatter->convertStringToNumber( nDefaultFormat, rString ); 2893 } 2894 catch( uno::Exception& ) 2895 { 2896 throw lang::IllegalArgumentException(); 2897 } 2898 } 2899 else 2900 { 2901 rtl_math_ConversionStatus eStatus; 2902 sal_Int32 nEnd; 2903 fValue = ::rtl::math::stringToDouble( rString, '.', ',', &eStatus, &nEnd ); 2904 if( (eStatus != rtl_math_ConversionStatus_Ok) || (nEnd < rString.getLength()) ) 2905 throw lang::IllegalArgumentException(); 2906 } 2907 return fValue; 2908 } 2909 2910 sal_Bool ScaAnyConverter::getDouble( 2911 double& rfResult, 2912 const uno::Any& rAny ) const throw( lang::IllegalArgumentException ) 2913 { 2914 rfResult = 0.0; 2915 sal_Bool bContainsVal = sal_True; 2916 switch( rAny.getValueTypeClass() ) 2917 { 2918 case uno::TypeClass_VOID: 2919 bContainsVal = sal_False; 2920 break; 2921 case uno::TypeClass_DOUBLE: 2922 rAny >>= rfResult; 2923 break; 2924 case uno::TypeClass_STRING: 2925 { 2926 const OUString* pString = static_cast< const OUString* >( rAny.getValue() ); 2927 if( pString->getLength() ) 2928 rfResult = convertToDouble( *pString ); 2929 else 2930 bContainsVal = sal_False; 2931 } 2932 break; 2933 default: 2934 throw lang::IllegalArgumentException(); 2935 } 2936 return bContainsVal; 2937 } 2938 2939 sal_Bool ScaAnyConverter::getDouble( 2940 double& rfResult, 2941 const uno::Reference< beans::XPropertySet >& xPropSet, 2942 const uno::Any& rAny ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 2943 { 2944 init( xPropSet ); 2945 return getDouble( rfResult, rAny ); 2946 } 2947 2948 double ScaAnyConverter::getDouble( 2949 const uno::Reference< beans::XPropertySet >& xPropSet, 2950 const uno::Any& rAny, 2951 double fDefault ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 2952 { 2953 double fResult; 2954 if( !getDouble( fResult, xPropSet, rAny ) ) 2955 fResult = fDefault; 2956 return fResult; 2957 } 2958 2959 sal_Bool ScaAnyConverter::getInt32( 2960 sal_Int32& rnResult, 2961 const uno::Reference< beans::XPropertySet >& xPropSet, 2962 const uno::Any& rAny ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 2963 { 2964 double fResult; 2965 sal_Bool bContainsVal = getDouble( fResult, xPropSet, rAny ); 2966 if( (fResult <= -2147483649.0) || (fResult >= 2147483648.0) ) 2967 throw lang::IllegalArgumentException(); 2968 2969 rnResult = static_cast< sal_Int32 >( fResult ); 2970 return bContainsVal; 2971 } 2972 2973 sal_Int32 ScaAnyConverter::getInt32( 2974 const uno::Reference< beans::XPropertySet >& xPropSet, 2975 const uno::Any& rAny, 2976 sal_Int32 nDefault ) throw( uno::RuntimeException, lang::IllegalArgumentException ) 2977 { 2978 sal_Int32 nResult; 2979 if( !getInt32( nResult, xPropSet, rAny ) ) 2980 nResult = nDefault; 2981 return nResult; 2982 } 2983 2984 2985 2986 //----------------------------------------------------------------------------- 2987 2988 2989