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