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