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