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