| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include <com/sun/star/util/XNumberFormatTypes.hpp> |
| |
| #include <string.h> |
| #include <stdio.h> |
| #include <tools/resary.hxx> |
| #include <rtl/math.hxx> |
| #include "analysishelper.hxx" |
| #include "analysis.hrc" |
| |
| using namespace ::rtl; |
| using namespace ::com::sun::star; |
| |
| #define UNIQUE sal_False // function name does not exist in Calc |
| #define DOUBLE sal_True // function name exists in Calc |
| |
| #define STDPAR sal_False // all parameters are described |
| #define INTPAR sal_True // first parameter is internal |
| |
| #define FUNCDATA( FUNCNAME, DBL, OPT, NUMOFPAR, CAT ) \ |
| { "get" #FUNCNAME, ANALYSIS_FUNCNAME_##FUNCNAME, ANALYSIS_##FUNCNAME, DBL, OPT, ANALYSIS_DEFFUNCNAME_##FUNCNAME, NUMOFPAR, CAT } |
| |
| const FuncDataBase pFuncDatas[] = |
| { |
| // UNIQUE or INTPAR or |
| // function name DOUBLE STDPAR # of param category |
| FUNCDATA( Workday, UNIQUE, INTPAR, 3, FDCat_DateTime ), |
| FUNCDATA( Yearfrac, UNIQUE, INTPAR, 3, FDCat_DateTime ), |
| FUNCDATA( Edate, UNIQUE, INTPAR, 2, FDCat_DateTime ), |
| FUNCDATA( Weeknum, DOUBLE, INTPAR, 2, FDCat_DateTime ), |
| FUNCDATA( Eomonth, UNIQUE, INTPAR, 2, FDCat_DateTime ), |
| FUNCDATA( Networkdays, UNIQUE, INTPAR, 3, FDCat_DateTime ), |
| FUNCDATA( Iseven, DOUBLE, STDPAR, 1, FDCat_Inf ), |
| FUNCDATA( Isodd, DOUBLE, STDPAR, 1, FDCat_Inf ), |
| FUNCDATA( Multinomial, UNIQUE, STDPAR, 1, FDCat_Math ), |
| FUNCDATA( Seriessum, UNIQUE, STDPAR, 4, FDCat_Math ), |
| FUNCDATA( Quotient, UNIQUE, STDPAR, 2, FDCat_Math ), |
| FUNCDATA( Mround, UNIQUE, STDPAR, 2, FDCat_Math ), |
| FUNCDATA( Sqrtpi, UNIQUE, STDPAR, 1, FDCat_Math ), |
| FUNCDATA( Randbetween, UNIQUE, STDPAR, 2, FDCat_Math ), |
| FUNCDATA( Gcd, DOUBLE, INTPAR, 1, FDCat_Math ), |
| FUNCDATA( Lcm, DOUBLE, INTPAR, 1, FDCat_Math ), |
| FUNCDATA( Besseli, UNIQUE, STDPAR, 2, FDCat_Tech ), |
| FUNCDATA( Besselj, UNIQUE, STDPAR, 2, FDCat_Tech ), |
| FUNCDATA( Besselk, UNIQUE, STDPAR, 2, FDCat_Tech ), |
| FUNCDATA( Bessely, UNIQUE, STDPAR, 2, FDCat_Tech ), |
| FUNCDATA( Bin2Oct, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Bin2Dec, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Bin2Hex, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Oct2Bin, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Oct2Dec, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Oct2Hex, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Dec2Bin, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Dec2Hex, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Dec2Oct, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Hex2Bin, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Hex2Dec, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Hex2Oct, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Delta, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Erf, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Erfc, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Gestep, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Factdouble, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imabs, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imaginary, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Impower, UNIQUE, STDPAR, 2, FDCat_Tech ), |
| FUNCDATA( Imargument, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imcos, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imdiv, UNIQUE, STDPAR, 2, FDCat_Tech ), |
| FUNCDATA( Imexp, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imconjugate, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imln, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imlog10, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imlog2, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Improduct, UNIQUE, INTPAR, 2, FDCat_Tech ), |
| FUNCDATA( Imreal, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imsin, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imsub, UNIQUE, STDPAR, 2, FDCat_Tech ), |
| FUNCDATA( Imsqrt, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imsum, UNIQUE, INTPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imtan, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imsec, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imcsc, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imcot, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imsinh, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imcosh, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imsech, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Imcsch, UNIQUE, STDPAR, 1, FDCat_Tech ), |
| FUNCDATA( Complex, UNIQUE, STDPAR, 3, FDCat_Tech ), |
| FUNCDATA( Convert, DOUBLE, STDPAR, 3, FDCat_Tech ), |
| FUNCDATA( Amordegrc, UNIQUE, INTPAR, 7, FDCat_Finance ), |
| FUNCDATA( Amorlinc, UNIQUE, INTPAR, 7, FDCat_Finance ), |
| FUNCDATA( Accrint, UNIQUE, INTPAR, 7, FDCat_Finance ), |
| FUNCDATA( Accrintm, UNIQUE, INTPAR, 5, FDCat_Finance ), |
| FUNCDATA( Received, UNIQUE, INTPAR, 5, FDCat_Finance ), |
| FUNCDATA( Disc, UNIQUE, INTPAR, 5, FDCat_Finance ), |
| FUNCDATA( Duration, DOUBLE, INTPAR, 6, FDCat_Finance ), |
| FUNCDATA( Effect, DOUBLE, STDPAR, 2, FDCat_Finance ), |
| FUNCDATA( Cumprinc, DOUBLE, STDPAR, 6, FDCat_Finance ), |
| FUNCDATA( Cumipmt, DOUBLE, STDPAR, 6, FDCat_Finance ), |
| FUNCDATA( Price, UNIQUE, INTPAR, 7, FDCat_Finance ), |
| FUNCDATA( Pricedisc, UNIQUE, INTPAR, 5, FDCat_Finance ), |
| FUNCDATA( Pricemat, UNIQUE, INTPAR, 6, FDCat_Finance ), |
| FUNCDATA( Mduration, UNIQUE, INTPAR, 6, FDCat_Finance ), |
| FUNCDATA( Nominal, DOUBLE, STDPAR, 2, FDCat_Finance ), |
| FUNCDATA( Dollarfr, UNIQUE, STDPAR, 2, FDCat_Finance ), |
| FUNCDATA( Dollarde, UNIQUE, STDPAR, 2, FDCat_Finance ), |
| FUNCDATA( Yield, UNIQUE, INTPAR, 7, FDCat_Finance ), |
| FUNCDATA( Yielddisc, UNIQUE, INTPAR, 5, FDCat_Finance ), |
| FUNCDATA( Yieldmat, UNIQUE, INTPAR, 6, FDCat_Finance ), |
| FUNCDATA( Tbilleq, UNIQUE, INTPAR, 3, FDCat_Finance ), |
| FUNCDATA( Tbillprice, UNIQUE, INTPAR, 3, FDCat_Finance ), |
| FUNCDATA( Tbillyield, UNIQUE, INTPAR, 3, FDCat_Finance ), |
| FUNCDATA( Oddfprice, UNIQUE, INTPAR, 9, FDCat_Finance ), |
| FUNCDATA( Oddfyield, UNIQUE, INTPAR, 9, FDCat_Finance ), |
| FUNCDATA( Oddlprice, UNIQUE, INTPAR, 8, FDCat_Finance ), |
| FUNCDATA( Oddlyield, UNIQUE, INTPAR, 8, FDCat_Finance ), |
| FUNCDATA( Xirr, UNIQUE, INTPAR, 3, FDCat_Finance ), |
| FUNCDATA( Xnpv, UNIQUE, STDPAR, 3, FDCat_Finance ), |
| FUNCDATA( Intrate, UNIQUE, INTPAR, 5, FDCat_Finance ), |
| FUNCDATA( Coupncd, UNIQUE, INTPAR, 4, FDCat_Finance ), |
| FUNCDATA( Coupdays, UNIQUE, INTPAR, 4, FDCat_Finance ), |
| FUNCDATA( Coupdaysnc, UNIQUE, INTPAR, 4, FDCat_Finance ), |
| FUNCDATA( Coupdaybs, UNIQUE, INTPAR, 4, FDCat_Finance ), |
| FUNCDATA( Couppcd, UNIQUE, INTPAR, 4, FDCat_Finance ), |
| FUNCDATA( Coupnum, UNIQUE, INTPAR, 4, FDCat_Finance ), |
| FUNCDATA( Fvschedule, UNIQUE, STDPAR, 2, FDCat_Finance ) |
| }; |
| #undef FUNCDATA |
| |
| |
| sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ) |
| { |
| if( (nMonth == 2) && IsLeapYear( nYear ) ) |
| return 29; |
| static const sal_uInt16 aDaysInMonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| return aDaysInMonth[ nMonth ]; |
| } |
| |
| |
| /** |
| * Convert a date to a count of days starting from 01/01/0001 |
| * |
| * The internal representation of a Date used in this Addin |
| * is the number of days between 01/01/0001 and the date |
| * this function converts a Day , Month, Year representation |
| * to this internal Date value. |
| * |
| */ |
| |
| sal_Int32 DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) |
| { |
| sal_Int32 nDays = ((sal_Int32)nYear-1) * 365; |
| nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400); |
| |
| for( sal_uInt16 i = 1; i < nMonth; i++ ) |
| nDays += DaysInMonth(i,nYear); |
| nDays += nDay; |
| |
| return nDays; |
| } |
| |
| |
| /** |
| * Convert a count of days starting from 01/01/0001 to a date |
| * |
| * The internal representation of a Date used in this Addin |
| * is the number of days between 01/01/0001 and the date |
| * this function converts this internal Date value |
| * to a Day , Month, Year representation of a Date. |
| * |
| */ |
| |
| void DaysToDate( sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear ) |
| throw( lang::IllegalArgumentException ) |
| { |
| if( nDays < 0 ) |
| throw lang::IllegalArgumentException(); |
| |
| sal_Int32 nTempDays; |
| sal_Int32 i = 0; |
| sal_Bool bCalc; |
| |
| do |
| { |
| nTempDays = nDays; |
| rYear = (sal_uInt16)((nTempDays / 365) - i); |
| nTempDays -= ((sal_Int32) rYear -1) * 365; |
| nTempDays -= (( rYear -1) / 4) - (( rYear -1) / 100) + ((rYear -1) / 400); |
| bCalc = sal_False; |
| if ( nTempDays < 1 ) |
| { |
| i++; |
| bCalc = sal_True; |
| } |
| else |
| { |
| if ( nTempDays > 365 ) |
| { |
| if ( (nTempDays != 366) || !IsLeapYear( rYear ) ) |
| { |
| i--; |
| bCalc = sal_True; |
| } |
| } |
| } |
| } |
| while ( bCalc ); |
| |
| rMonth = 1; |
| while ( (sal_Int32)nTempDays > DaysInMonth( rMonth, rYear ) ) |
| { |
| nTempDays -= DaysInMonth( rMonth, rYear ); |
| rMonth++; |
| } |
| rDay = (sal_uInt16)nTempDays; |
| } |
| |
| |
| /** |
| * Get the null date used by the spreadsheet document |
| * |
| * The internal representation of a Date used in this Addin |
| * is the number of days between 01/01/0001 and the date |
| * this function returns this internal Date value for the document null date |
| * |
| */ |
| |
| sal_Int32 GetNullDate( constREFXPS& xOpt ) THROWDEF_RTE |
| { |
| if( xOpt.is() ) |
| { |
| try |
| { |
| ANY aAny = xOpt->getPropertyValue( STRFROMASCII( "NullDate" ) ); |
| util::Date aDate; |
| if( aAny >>= aDate ) |
| return DateToDays( aDate.Day, aDate.Month, aDate.Year ); |
| } |
| catch( uno::Exception& ) |
| { |
| } |
| } |
| |
| // no null date available -> no calculations possible |
| throw uno::RuntimeException(); |
| } |
| |
| |
| sal_Int32 GetDiffDate360( |
| sal_uInt16 nDay1, sal_uInt16 nMonth1, sal_uInt16 nYear1, sal_Bool bLeapYear1, |
| sal_uInt16 nDay2, sal_uInt16 nMonth2, sal_uInt16 nYear2, |
| sal_Bool bUSAMethod ) |
| { |
| if( nDay1 == 31 ) |
| nDay1--; |
| else if( bUSAMethod && ( nMonth1 == 2 && ( nDay1 == 29 || ( nDay1 == 28 && !bLeapYear1 ) ) ) ) |
| nDay1 = 30; |
| |
| if( nDay2 == 31 ) |
| { |
| if( bUSAMethod && nDay1 != 30 ) |
| { |
| //aDate2 += 1; -> 1.xx.yyyy |
| nDay2 = 1; |
| if( nMonth2 == 12 ) |
| { |
| nYear2++; |
| nMonth2 = 1; |
| } |
| else |
| nMonth2++; |
| } |
| else |
| nDay2 = 30; |
| } |
| |
| return nDay2 + nMonth2 * 30 + nYear2 * 360 - nDay1 - nMonth1 * 30 - nYear1 * 360; |
| } |
| |
| |
| sal_Int32 GetDiffDate360( sal_Int32 nNullDate, sal_Int32 nDate1, sal_Int32 nDate2, sal_Bool bUSAMethod ) |
| { |
| nDate1 += nNullDate; |
| nDate2 += nNullDate; |
| |
| sal_uInt16 nDay1, nMonth1, nYear1, nDay2, nMonth2, nYear2; |
| |
| DaysToDate( nDate1, nDay1, nMonth1, nYear1 ); |
| DaysToDate( nDate2, nDay2, nMonth2, nYear2 ); |
| |
| return GetDiffDate360( nDay1, nMonth1, nYear1, IsLeapYear( nYear1 ), nDay2, nMonth2, nYear2, bUSAMethod ); |
| } |
| |
| |
| sal_Int32 GetDaysInYears( sal_uInt16 nYear1, sal_uInt16 nYear2 ) |
| { |
| sal_uInt16 nLeaps = 0; |
| for( sal_uInt16 n = nYear1 ; n <= nYear2 ; n++ ) |
| { |
| if( IsLeapYear( n ) ) |
| nLeaps++; |
| } |
| |
| sal_uInt32 nSum = 1; |
| nSum += nYear2; |
| nSum -= nYear1; |
| nSum *= 365; |
| nSum += nLeaps; |
| |
| return nSum; |
| } |
| |
| |
| void GetDiffParam( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode, |
| sal_uInt16& rYears, sal_Int32& rDayDiffPart, sal_Int32& rDaysInYear ) THROWDEF_RTE_IAE |
| { |
| if( nStartDate > nEndDate ) |
| { |
| sal_Int32 n = nEndDate; |
| nEndDate = nStartDate; |
| nStartDate = n; |
| } |
| |
| sal_Int32 nDate1 = nStartDate + nNullDate; |
| sal_Int32 nDate2 = nEndDate + nNullDate; |
| |
| sal_uInt16 nDay1, nDay2; |
| sal_uInt16 nMonth1, nMonth2; |
| sal_uInt16 nYear1, nYear2; |
| |
| DaysToDate( nDate1, nDay1, nMonth1, nYear1 ); |
| DaysToDate( nDate2, nDay2, nMonth2, nYear2 ); |
| |
| sal_uInt16 nYears; |
| |
| sal_Int32 nDayDiff, nDaysInYear; |
| |
| switch( nMode ) |
| { |
| case 0: // 0=USA (NASD) 30/360 |
| case 4: // 4=Europe 30/360 |
| nDaysInYear = 360; |
| nYears = nYear2 - nYear1; |
| nDayDiff = GetDiffDate360( nDay1, nMonth1, nYear1, IsLeapYear( nYear1 ), |
| nDay2, nMonth2, nYear2, nMode == 0 ) - nYears * nDaysInYear; |
| break; |
| case 1: // 1=exact/exact |
| nYears = nYear2 - nYear1; |
| |
| nDaysInYear = IsLeapYear( nYear1 )? 366 : 365; |
| |
| if( nYears && ( nMonth1 > nMonth2 || ( nMonth1 == nMonth2 && nDay1 > nDay2 ) ) ) |
| nYears--; |
| |
| if( nYears ) |
| nDayDiff = nDate2 - DateToDays( nDay1, nMonth1, nYear2 ); |
| else |
| nDayDiff = nDate2 - nDate1; |
| |
| if( nDayDiff < 0 ) |
| nDayDiff += nDaysInYear; |
| |
| break; |
| case 2: // 2=exact/360 |
| nDaysInYear = 360; |
| nYears = sal_uInt16( ( nDate2 - nDate1 ) / nDaysInYear ); |
| nDayDiff = nDate2 - nDate1; |
| nDayDiff %= nDaysInYear; |
| break; |
| case 3: //3=exact/365 |
| nDaysInYear = 365; |
| nYears = sal_uInt16( ( nDate2 - nDate1 ) / nDaysInYear ); |
| nDayDiff = nDate2 - nDate1; |
| nDayDiff %= nDaysInYear; |
| break; |
| default: |
| THROW_IAE; |
| } |
| |
| rYears = nYears; |
| rDayDiffPart = nDayDiff; |
| rDaysInYear = nDaysInYear; |
| } |
| |
| |
| sal_Int32 GetDiffDate( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode, |
| sal_Int32* pOptDaysIn1stYear ) THROWDEF_RTE_IAE |
| { |
| sal_Bool bNeg = nStartDate > nEndDate; |
| |
| if( bNeg ) |
| { |
| sal_Int32 n = nEndDate; |
| nEndDate = nStartDate; |
| nStartDate = n; |
| } |
| |
| sal_Int32 nRet; |
| |
| switch( nMode ) |
| { |
| case 0: // 0=USA (NASD) 30/360 |
| case 4: // 4=Europe 30/360 |
| { |
| sal_uInt16 nD1, nM1, nY1, nD2, nM2, nY2; |
| |
| nStartDate += nNullDate; |
| nEndDate += nNullDate; |
| |
| DaysToDate( nStartDate, nD1, nM1, nY1 ); |
| DaysToDate( nEndDate, nD2, nM2, nY2 ); |
| |
| sal_Bool bLeap = IsLeapYear( nY1 ); |
| sal_Int32 nDays, nMonths/*, nYears*/; |
| |
| nMonths = nM2 - nM1; |
| nDays = nD2 - nD1; |
| |
| nMonths += ( nY2 - nY1 ) * 12; |
| |
| nRet = nMonths * 30 + nDays; |
| if( nMode == 0 && nM1 == 2 && nM2 != 2 && nY1 == nY2 ) |
| nRet -= bLeap? 1 : 2; |
| |
| if( pOptDaysIn1stYear ) |
| *pOptDaysIn1stYear = 360; |
| } |
| break; |
| case 1: // 1=exact/exact |
| if( pOptDaysIn1stYear ) |
| { |
| sal_uInt16 nD, nM, nY; |
| |
| DaysToDate( nStartDate + nNullDate, nD, nM, nY ); |
| |
| *pOptDaysIn1stYear = IsLeapYear( nY )? 366 : 365; |
| } |
| nRet = nEndDate - nStartDate; |
| break; |
| case 2: // 2=exact/360 |
| nRet = nEndDate - nStartDate; |
| if( pOptDaysIn1stYear ) |
| *pOptDaysIn1stYear = 360; |
| break; |
| case 3: //3=exact/365 |
| nRet = nEndDate - nStartDate; |
| if( pOptDaysIn1stYear ) |
| *pOptDaysIn1stYear = 365; |
| break; |
| default: |
| THROW_IAE; |
| } |
| |
| return bNeg? -nRet : nRet; |
| } |
| |
| |
| double GetYearDiff( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode ) THROWDEF_RTE_IAE |
| { |
| sal_Int32 nDays1stYear; |
| sal_Int32 nTotalDays = GetDiffDate( nNullDate, nStartDate, nEndDate, nMode, &nDays1stYear ); |
| |
| return double( nTotalDays ) / double( nDays1stYear ); |
| } |
| |
| |
| sal_Int32 GetDaysInYear( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nMode ) THROWDEF_RTE_IAE |
| { |
| switch( nMode ) |
| { |
| case 0: // 0=USA (NASD) 30/360 |
| case 2: // 2=exact/360 |
| case 4: // 4=Europe 30/360 |
| return 360; |
| case 1: // 1=exact/exact |
| { |
| sal_uInt16 nD, nM, nY; |
| nDate += nNullDate; |
| DaysToDate( nDate, nD, nM, nY ); |
| return IsLeapYear( nY )? 366 : 365; |
| } |
| case 3: //3=exact/365 |
| return 365; |
| default: |
| THROW_IAE; |
| } |
| } |
| |
| |
| double GetYearFrac( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode ) THROWDEF_RTE_IAE |
| { |
| if( nStartDate == nEndDate ) |
| return 0.0; // nothing to do... |
| |
| sal_uInt16 nYears; |
| sal_Int32 nDayDiff, nDaysInYear; |
| |
| GetDiffParam( nNullDate, nStartDate, nEndDate, nMode, nYears, nDayDiff, nDaysInYear ); |
| |
| return double( nYears ) + double( nDayDiff ) / double( nDaysInYear ); |
| } |
| |
| |
| double Fak( sal_Int32 n ) |
| { |
| if( n > 0 ) |
| { |
| double fRet = n; |
| double f = n - 1; |
| |
| while( f >= 2.0 ) |
| { |
| fRet *= f; |
| f--; |
| } |
| |
| return fRet; |
| } |
| else if( !n ) |
| return 1.0; |
| else |
| return 0.0; |
| } |
| |
| |
| double GetGcd( double f1, double f2 ) |
| { |
| double f = fmod( f1, f2 ); |
| while( f > 0.0 ) |
| { |
| f1 = f2; |
| f2 = f; |
| f = fmod( f1, f2 ); |
| } |
| |
| return f2; |
| } |
| |
| |
| double ConvertToDec( const STRING& aStr, sal_uInt16 nBase, sal_uInt16 nCharLim ) THROWDEF_RTE_IAE |
| { |
| if ( nBase < 2 || nBase > 36 ) |
| THROW_IAE; |
| |
| sal_uInt32 nStrLen = aStr.getLength(); |
| if( nStrLen > nCharLim ) |
| THROW_IAE; |
| else if( !nStrLen ) |
| return 0.0; |
| |
| double fVal = 0.0; |
| |
| register const sal_Unicode* p = aStr.getStr(); |
| |
| sal_uInt16 nFirstDig = 0; |
| sal_Bool bFirstDig = sal_True; |
| double fBase = nBase; |
| |
| while ( *p ) |
| { |
| sal_uInt16 n; |
| |
| if( '0' <= *p && *p <= '9' ) |
| n = *p - '0'; |
| else if( 'A' <= *p && *p <= 'Z' ) |
| n = 10 + ( *p - 'A' ); |
| else if ( 'a' <= *p && *p <= 'z' ) |
| n = 10 + ( *p - 'a' ); |
| else |
| n = nBase; |
| |
| if( n < nBase ) |
| { |
| if( bFirstDig ) |
| { |
| bFirstDig = sal_False; |
| nFirstDig = n; |
| } |
| fVal = fVal * fBase + double( n ); |
| } |
| else |
| // illegal char! |
| THROW_IAE; |
| |
| p++; |
| |
| } |
| |
| if( nStrLen == nCharLim && !bFirstDig && (nFirstDig >= nBase / 2) ) |
| { // handling negativ values |
| fVal = ( pow( double( nBase ), double( nCharLim ) ) - fVal ); // complement |
| fVal *= -1.0; |
| } |
| |
| return fVal; |
| } |
| |
| |
| static inline sal_Char GetMaxChar( sal_uInt16 nBase ) |
| { |
| const sal_Char* c = "--123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
| return c[ nBase ]; |
| } |
| |
| |
| STRING ConvertFromDec( double fNum, double fMin, double fMax, sal_uInt16 nBase, |
| sal_Int32 nPlaces, sal_Int32 nMaxPlaces, sal_Bool bUsePlaces ) THROWDEF_RTE_IAE |
| { |
| fNum = ::rtl::math::approxFloor( fNum ); |
| fMin = ::rtl::math::approxFloor( fMin ); |
| fMax = ::rtl::math::approxFloor( fMax ); |
| |
| if( fNum < fMin || fNum > fMax || ( bUsePlaces && ( nPlaces <= 0 || nPlaces > nMaxPlaces ) ) ) |
| THROW_IAE; |
| |
| sal_Int64 nNum = static_cast< sal_Int64 >( fNum ); |
| sal_Bool bNeg = nNum < 0; |
| if( bNeg ) |
| nNum = sal_Int64( pow( double( nBase ), double( nMaxPlaces ) ) ) + nNum; |
| |
| STRING aRet( STRING::valueOf( nNum, nBase ).toAsciiUpperCase() ); |
| |
| |
| if( bUsePlaces ) |
| { |
| sal_Int32 nLen = aRet.getLength(); |
| if( !bNeg && nLen > nPlaces ) |
| { |
| THROW_IAE; |
| } |
| else if( ( bNeg && nLen < nMaxPlaces ) || ( !bNeg && nLen < nPlaces ) ) |
| { |
| sal_Int32 nLeft = nPlaces - nLen; |
| sal_Char* p = new sal_Char[ nLeft + 1 ]; |
| memset( p, bNeg? GetMaxChar( nBase ) : '0', nLeft ); |
| p[ nLeft ] = 0x00; |
| STRING aTmp( p, nLeft, RTL_TEXTENCODING_MS_1252 ); |
| aTmp += aRet; |
| aRet = aTmp; |
| |
| delete[] p; |
| } |
| } |
| |
| return aRet; |
| } |
| |
| // implementation moved to module sal, see #i97091# |
| double Erf( double x ) |
| { |
| return ::rtl::math::erf(x); |
| } |
| |
| // implementation moved to module sal, see #i97091# |
| double Erfc( double x ) |
| { |
| return ::rtl::math::erfc(x); |
| } |
| |
| inline sal_Bool IsNum( sal_Unicode c ) |
| { |
| return c >= '0' && c <= '9'; |
| } |
| |
| |
| inline sal_Bool IsComma( sal_Unicode c ) |
| { |
| return c == '.' || c == ','; |
| } |
| |
| |
| inline sal_Bool IsExpStart( sal_Unicode c ) |
| { |
| return c == 'e' || c == 'E'; |
| } |
| |
| |
| inline sal_Bool IsImagUnit( sal_Unicode c ) |
| { |
| return c == 'i' || c == 'j'; |
| } |
| |
| |
| inline sal_uInt16 GetVal( sal_Unicode c ) |
| { |
| return sal_uInt16( c - '0' ); |
| } |
| |
| |
| sal_Bool ParseDouble( const sal_Unicode*& rp, double& rRet ) |
| { |
| double fInt = 0.0; |
| double fFrac = 0.0; |
| double fMult = 0.1; // multiplier to multiply digits with, when adding fractional ones |
| sal_Int32 nExp = 0; |
| sal_Int32 nMaxExp = 307; |
| sal_uInt16 nDigCnt = 18; // max. number of digits to read in, rest doesn't matter |
| |
| enum State { S_End = 0, S_Sign, S_IntStart, S_Int, S_IgnoreIntDigs, S_Frac, S_IgnoreFracDigs, S_ExpSign, S_Exp }; |
| |
| State eS = S_Sign; |
| |
| sal_Bool bNegNum = sal_False; |
| sal_Bool bNegExp = sal_False; |
| |
| const sal_Unicode* p = rp; |
| sal_Unicode c; |
| |
| while( eS ) |
| { |
| c = *p; |
| switch( eS ) |
| { |
| case S_Sign: |
| if( IsNum( c ) ) |
| { |
| fInt = GetVal( c ); |
| nDigCnt--; |
| eS = S_Int; |
| } |
| else if( c == '-' ) |
| { |
| bNegNum = sal_True; |
| eS = S_IntStart; |
| } |
| else if( c == '+' ) |
| eS = S_IntStart; |
| else if( IsComma( c ) ) |
| eS = S_Frac; |
| else |
| return sal_False; |
| break; |
| case S_IntStart: |
| if( IsNum( c ) ) |
| { |
| fInt = GetVal( c ); |
| nDigCnt--; |
| eS = S_Int; |
| } |
| else if( IsComma( c ) ) |
| eS = S_Frac; |
| else if( IsImagUnit( c ) ) |
| { |
| rRet = 0.0; |
| return sal_True; |
| } |
| else |
| return sal_False; |
| break; |
| case S_Int: |
| if( IsNum( c ) ) |
| { |
| fInt *= 10.0; |
| fInt += double( GetVal( c ) ); |
| nDigCnt--; |
| if( !nDigCnt ) |
| eS = S_IgnoreIntDigs; |
| } |
| else if( IsComma( c ) ) |
| eS = S_Frac; |
| else if( IsExpStart( c ) ) |
| eS = S_ExpSign; |
| else |
| eS = S_End; |
| break; |
| case S_IgnoreIntDigs: |
| if( IsNum( c ) ) |
| nExp++; // just multiply num with 10... ;-) |
| else if( IsComma( c ) ) |
| eS = S_Frac; |
| else if( IsExpStart( c ) ) |
| eS = S_ExpSign; |
| else |
| eS = S_End; |
| break; |
| case S_Frac: |
| if( IsNum( c ) ) |
| { |
| fFrac += double( GetVal( c ) ) * fMult; |
| nDigCnt--; |
| if( nDigCnt ) |
| fMult *= 0.1; |
| else |
| eS = S_IgnoreFracDigs; |
| } |
| else if( IsExpStart( c ) ) |
| eS = S_ExpSign; |
| else |
| eS = S_End; |
| break; |
| case S_IgnoreFracDigs: |
| if( IsExpStart( c ) ) |
| eS = S_ExpSign; |
| else if( !IsNum( c ) ) |
| eS = S_End; |
| break; |
| case S_ExpSign: |
| if( IsNum( c ) ) |
| { |
| nExp = GetVal( c ); |
| eS = S_Exp; |
| } |
| else if( c == '-' ) |
| { |
| bNegExp = sal_True; |
| eS = S_Exp; |
| } |
| else if( c != '+' ) |
| eS = S_End; |
| break; |
| case S_Exp: |
| if( IsNum( c ) ) |
| { |
| nExp *= 10; |
| nExp += GetVal( c ); |
| if( nExp > nMaxExp ) |
| return sal_False; |
| } |
| else |
| eS = S_End; |
| break; |
| case S_End: // to avoid compiler warning |
| break; // loop exits anyway |
| } |
| |
| p++; |
| } |
| |
| p--; // set pointer back to last |
| rp = p; |
| |
| fInt += fFrac; |
| sal_Int32 nLog10 = sal_Int32( log10( fInt ) ); |
| |
| if( bNegExp ) |
| nExp = -nExp; |
| |
| if( nLog10 + nExp > nMaxExp ) |
| return sal_False; |
| |
| fInt = ::rtl::math::pow10Exp( fInt, nExp ); |
| |
| if( bNegNum ) |
| fInt = -fInt; |
| |
| rRet = fInt; |
| |
| return sal_True; |
| } |
| |
| |
| STRING GetString( double f, sal_Bool bLeadingSign, sal_uInt16 nMaxDig ) |
| { |
| const int nBuff = 256; |
| sal_Char aBuff[ nBuff + 1 ]; |
| const char* pFormStr = bLeadingSign? "%+.*g" : "%.*g"; |
| int nLen = snprintf( aBuff, nBuff, pFormStr, int( nMaxDig ), f ); |
| // you never know which underlying implementation you get ... |
| aBuff[nBuff] = 0; |
| if ( nLen < 0 || nLen > nBuff ) |
| nLen = strlen( aBuff ); |
| |
| STRING aRet( aBuff, nLen, RTL_TEXTENCODING_MS_1252 ); |
| |
| return aRet; |
| } |
| |
| |
| double GetAmordegrc( sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer, |
| double fRestVal, double fPer, double fRate, sal_Int32 nBase ) THROWDEF_RTE_IAE |
| { |
| if( nBase == 2 ) |
| THROW_IAE; |
| |
| sal_uInt32 nPer = sal_uInt32( fPer ); |
| double fUsePer = 1.0 / fRate; |
| double fAmorCoeff; |
| |
| if( fUsePer < 3.0 ) |
| fAmorCoeff = 1.0; |
| else if( fUsePer < 5.0 ) |
| fAmorCoeff = 1.5; |
| else if( fUsePer <= 6.0 ) |
| fAmorCoeff = 2.0; |
| else |
| fAmorCoeff = 2.5; |
| |
| fRate *= fAmorCoeff; |
| double fNRate = ::rtl::math::round( GetYearFrac( nNullDate, nDate, nFirstPer, nBase ) * fRate * fCost, 0 ); |
| fCost -= fNRate; |
| double fRest = fCost - fRestVal; // Anschaffungskosten - Restwert - Summe aller Abschreibungen |
| |
| for( sal_uInt32 n = 0 ; n < nPer ; n++ ) |
| { |
| fNRate = ::rtl::math::round( fRate * fCost, 0 ); |
| fRest -= fNRate; |
| |
| if( fRest < 0.0 ) |
| { |
| switch( nPer - n ) |
| { |
| case 0: |
| case 1: |
| return ::rtl::math::round( fCost * 0.5, 0 ); |
| default: |
| return 0.0; |
| } |
| } |
| |
| fCost -= fNRate; |
| } |
| |
| return fNRate; |
| } |
| |
| |
| double GetAmorlinc( sal_Int32 nNullDate, double fCost, sal_Int32 nDate, sal_Int32 nFirstPer, |
| double fRestVal, double fPer, double fRate, sal_Int32 nBase ) THROWDEF_RTE_IAE |
| { |
| if( nBase == 2 ) |
| THROW_IAE; |
| |
| sal_uInt32 nPer = sal_uInt32( fPer ); |
| double fOneRate = fCost * fRate; |
| double fCostDelta = fCost - fRestVal; |
| double f0Rate = GetYearFrac( nNullDate, nDate, nFirstPer, nBase ) * fRate * fCost; |
| sal_uInt32 nNumOfFullPeriods = sal_uInt32( ( fCost - fRestVal - f0Rate) / fOneRate ); |
| |
| if( nPer == 0 ) |
| return f0Rate; |
| else if( nPer <= nNumOfFullPeriods ) |
| return fOneRate; |
| else if( nPer == nNumOfFullPeriods + 1 ) |
| return fCostDelta - fOneRate * nNumOfFullPeriods - f0Rate; |
| else |
| return 0.0; |
| } |
| |
| |
| double GetDuration( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup, |
| double fYield, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE |
| { |
| double fYearfrac = GetYearFrac( nNullDate, nSettle, nMat, nBase ); |
| double fNumOfCoups = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase ); |
| double fDur = 0.0; |
| const double f100 = 100.0; |
| fCoup *= f100 / double( nFreq ); // fCoup is used as cash flow |
| fYield /= nFreq; |
| fYield += 1.0; |
| |
| double nDiff = fYearfrac * nFreq - fNumOfCoups; |
| |
| double t; |
| |
| for( t = 1.0 ; t < fNumOfCoups ; t++ ) |
| fDur += ( t + nDiff ) * ( fCoup ) / pow( fYield, t + nDiff ); |
| |
| fDur += ( fNumOfCoups + nDiff ) * ( fCoup + f100 ) / pow( fYield, fNumOfCoups + nDiff ); |
| |
| double p = 0.0; |
| for( t = 1.0 ; t < fNumOfCoups ; t++ ) |
| p += fCoup / pow( fYield, t + nDiff ); |
| |
| p += ( fCoup + f100 ) / pow( fYield, fNumOfCoups + nDiff ); |
| |
| fDur /= p; |
| fDur /= double( nFreq ); |
| |
| return fDur; |
| } |
| |
| |
| double GetYieldmat( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue, |
| double fRate, double fPrice, sal_Int32 nBase ) THROWDEF_RTE_IAE |
| { |
| double fIssMat = GetYearFrac( nNullDate, nIssue, nMat, nBase ); |
| double fIssSet = GetYearFrac( nNullDate, nIssue, nSettle, nBase ); |
| double fSetMat = GetYearFrac( nNullDate, nSettle, nMat, nBase ); |
| |
| double y = 1.0 + fIssMat * fRate; |
| y /= fPrice / 100.0 + fIssSet * fRate; |
| y--; |
| y /= fSetMat; |
| |
| return y; |
| } |
| |
| |
| double GetOddfprice( sal_Int32 /*nNullDate*/, sal_Int32 /*nSettle*/, sal_Int32 /*nMat*/, sal_Int32 /*nIssue*/, |
| sal_Int32 /*nFirstCoup*/, double /*fRate*/, double /*fYield*/, double /*fRedemp*/, sal_Int32 /*nFreq*/, |
| sal_Int32 /*nBase*/ ) THROWDEF_RTE_IAE |
| { |
| THROW_RTE; // #87380# |
| /* |
| double fN = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase ) - 1.0; |
| double fNq = GetCoupnum( nNullDate, nSettle, nFirstCoup, nFreq, nBase ) - 1.0; |
| double fDSC = GetCoupdaysnc( nNullDate, nSettle, nFirstCoup, nFreq, nBase ); |
| double fDSC_E = fDSC / GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase ); |
| double fNC = GetCoupnum( nNullDate, nIssue, nFirstCoup, nFreq, nBase ); |
| sal_uInt32 nNC = sal_uInt32( fNC ); |
| sal_uInt16 nMonthDelta = 12 / sal_uInt16( nFreq ); |
| |
| sal_uInt32 i; |
| double f1YieldFreq = 1.0 + fYield / double( nFreq ); |
| double f100RateFreq = 100.0 * fRate / double( nFreq ); |
| |
| double* pDC = new double[ nNC + 1 ]; |
| double* pNL = new double[ nNC + 1 ]; |
| double* pA = new double[ nNC + 1 ]; |
| |
| pDC[ 0 ] = pNL[ 0 ] = pA[ 0 ] = 1.0; |
| |
| ScaDate aStartDate( nNullDate, nSettle, nBase ); |
| ScaDate aNextCoup( nNullDate, nFirstCoup, nBase ); |
| if( nNC ) |
| { |
| pDC[ 1 ] = ScaDate::GetDiff( aStartDate, aNextCoup ); |
| pNL[ 1 ] = GetCoupdays( nNullDate, nSettle, nFirstCoup, nFreq, nBase ); |
| pA[ 1 ] = pDC[ 1 ]; |
| ScaDate aPre; |
| for( i = 1 ; i <= nNC ; i++ ) |
| { |
| aPre = aStartDate; |
| aStartDate.addMonths( nMonthDelta ); |
| aNextCoup.addMonths( nMonthDelta ); |
| pDC[ i ] = ScaDate::GetDiff( aPre, aStartDate ); |
| pNL[ i ] = GetCoupdays( nNullDate, aStartDate.GetDate( nNullDate ), aNextCoup.GetDate( nNullDate ), |
| nFreq, nBase ); |
| pA[ i ] = ScaDate::GetDiff( aStartDate, aNextCoup ); |
| } |
| } |
| |
| double fT1 = fRedemp / pow( f1YieldFreq, fN + fNq + fDSC_E ); |
| |
| double fT2 = 0.0; |
| for( i = 1 ; i <= nNC ; i++ ) |
| fT2 += pDC[ i ] / pNL[ i ]; |
| fT2 *= f100RateFreq / pow( f1YieldFreq, fNq + fDSC_E ); |
| |
| double fT3 = 0.0; |
| for( double k = 2.0 ; k <= fN ; k++ ) |
| fT3 += 1.0 / pow( f1YieldFreq, k - fNq + fDSC_E ); |
| fT3 *= f100RateFreq; |
| |
| double fT4 = 0.0; |
| for( i = 1 ; i <= nNC ; i++ ) |
| fT4 += pA[ i ] / pNL[ i ]; |
| fT4 *= f100RateFreq; |
| |
| if( nNC ) |
| { |
| delete pDC; |
| delete pNL; |
| delete pA; |
| } |
| |
| return fT1 + fT2 + fT3 - fT4; |
| */ |
| } |
| |
| |
| double getYield_( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup, double fPrice, |
| double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE |
| { |
| double fRate = fCoup; |
| double fPriceN = 0.0; |
| double fYield1 = 0.0; |
| double fYield2 = 1.0; |
| double fPrice1 = getPrice_( nNullDate, nSettle, nMat, fRate, fYield1, fRedemp, nFreq, nBase ); |
| double fPrice2 = getPrice_( nNullDate, nSettle, nMat, fRate, fYield2, fRedemp, nFreq, nBase ); |
| double fYieldN = ( fYield2 - fYield1 ) * 0.5; |
| |
| for( sal_uInt32 nIter = 0 ; nIter < 100 && fPriceN != fPrice ; nIter++ ) |
| { |
| fPriceN = getPrice_( nNullDate, nSettle, nMat, fRate, fYieldN, fRedemp, nFreq, nBase ); |
| |
| if( fPrice == fPrice1 ) |
| return fYield1; |
| else if( fPrice == fPrice2 ) |
| return fYield2; |
| else if( fPrice == fPriceN ) |
| return fYieldN; |
| else if( fPrice < fPrice2 ) |
| { |
| fYield2 *= 2.0; |
| fPrice2 = getPrice_( nNullDate, nSettle, nMat, fRate, fYield2, fRedemp, nFreq, nBase ); |
| |
| fYieldN = ( fYield2 - fYield1 ) * 0.5; |
| } |
| else |
| { |
| if( fPrice < fPriceN ) |
| { |
| fYield1 = fYieldN; |
| fPrice1 = fPriceN; |
| } |
| else |
| { |
| fYield2 = fYieldN; |
| fPrice2 = fPriceN; |
| } |
| |
| fYieldN = fYield2 - ( fYield2 - fYield1 ) * ( ( fPrice - fPrice2 ) / ( fPrice1 - fPrice2 ) ); |
| } |
| } |
| |
| if( fabs( fPrice - fPriceN ) > fPrice / 100.0 ) |
| THROW_IAE; // result not precise enough |
| |
| return fYieldN; |
| } |
| |
| |
| double getPrice_( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fRate, double fYield, |
| double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE |
| { |
| double fFreq = nFreq; |
| |
| double fE = GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase ); |
| double fDSC_E = GetCoupdaysnc( nNullDate, nSettle, nMat, nFreq, nBase ) / fE; |
| double fN = GetCoupnum( nNullDate, nSettle, nMat, nFreq, nBase ); |
| double fA = GetCoupdaybs( nNullDate, nSettle, nMat, nFreq, nBase ); |
| |
| double fRet = fRedemp / ( pow( 1.0 + fYield / fFreq, fN - 1.0 + fDSC_E ) ); |
| fRet -= 100.0 * fRate / fFreq * fA / fE; |
| |
| double fT1 = 100.0 * fRate / fFreq; |
| double fT2 = 1.0 + fYield / fFreq; |
| |
| for( double fK = 0.0 ; fK < fN ; fK++ ) |
| fRet += fT1 / pow( fT2, fK + fDSC_E ); |
| |
| return fRet; |
| } |
| |
| |
| double GetOddfyield( sal_Int32 /*nNullDate*/, sal_Int32 /*nSettle*/, sal_Int32 /*nMat*/, sal_Int32 /*nIssue*/, |
| sal_Int32 /*nFirstCoup*/, double /*fRate*/, double /*fPrice*/, double /*fRedemp*/, sal_Int32 /*nFreq*/, |
| sal_Int32 /*nBase*/ ) THROWDEF_RTE_IAE |
| { |
| THROW_RTE; // #87380# |
| /* |
| //GetOddfprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nIssue, |
| //sal_Int32 nFirstCoup, double fRate, double fYield, double fRedemp, sal_Int32 nFreq, |
| //sal_Int32 nBase ) |
| double fPriceN = 0.0; |
| double fYield1 = 0.0; |
| double fYield2 = 1.0; |
| double fPrice1 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield1, fRedemp, nFreq, nBase ); |
| double fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase ); |
| double fYieldN = ( fYield2 - fYield1 ) * 0.5; |
| |
| for( sal_uInt32 nIter = 0 ; nIter < 100 && fPriceN != fPrice ; nIter++ ) |
| { |
| fPriceN = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYieldN, fRedemp, nFreq, nBase ); |
| |
| if( fPrice == fPrice1 ) |
| return fYield1; |
| else if( fPrice == fPrice2 ) |
| return fYield2; |
| else if( fPrice == fPriceN ) |
| return fYieldN; |
| else if( fPrice < fPrice2 ) |
| { |
| fYield2 *= 2.0; |
| fPrice2 = GetOddfprice( nNullDate, nSettle, nMat, nIssue, nFirstCoup, fRate, fYield2, fRedemp, nFreq, nBase ); |
| |
| fYieldN = ( fYield2 - fYield1 ) * 0.5; |
| } |
| else |
| { |
| if( fPrice < fPriceN ) |
| { |
| fYield1 = fYieldN; |
| fPrice1 = fPriceN; |
| } |
| else |
| { |
| fYield2 = fYieldN; |
| fPrice2 = fPriceN; |
| } |
| |
| fYieldN = fYield2 - ( fYield2 - fYield1 ) * ( ( fPrice - fPrice2 ) / ( fPrice1 - fPrice2 ) ); |
| } |
| } |
| |
| if( fabs( fPrice - fPriceN ) > fPrice / 100.0 ) |
| THROW_IAE; // result not precise enough |
| |
| return fYieldN; |
| */ |
| } |
| |
| |
| double GetOddlprice( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastCoup, |
| double fRate, double fYield, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE |
| { |
| double fFreq = double( nFreq ); |
| double fDCi = GetYearFrac( nNullDate, nLastCoup, nMat, nBase ) * fFreq; |
| double fDSCi = GetYearFrac( nNullDate, nSettle, nMat, nBase ) * fFreq; |
| double fAi = GetYearFrac( nNullDate, nLastCoup, nSettle, nBase ) * fFreq; |
| |
| double p = fRedemp + fDCi * 100.0 * fRate / fFreq; |
| p /= fDSCi * fYield / fFreq + 1.0; |
| p -= fAi * 100.0 * fRate / fFreq; |
| |
| return p; |
| } |
| |
| |
| double GetOddlyield( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nLastCoup, |
| double fRate, double fPrice, double fRedemp, sal_Int32 nFreq, sal_Int32 nBase ) THROWDEF_RTE_IAE |
| { |
| double fFreq = double( nFreq ); |
| double fDCi = GetYearFrac( nNullDate, nLastCoup, nMat, nBase ) * fFreq; |
| double fDSCi = GetYearFrac( nNullDate, nSettle, nMat, nBase ) * fFreq; |
| double fAi = GetYearFrac( nNullDate, nLastCoup, nSettle, nBase ) * fFreq; |
| |
| double y = fRedemp + fDCi * 100.0 * fRate / fFreq; |
| y /= fPrice + fAi * 100.0 * fRate / fFreq; |
| y--; |
| y *= fFreq / fDSCi; |
| |
| return y; |
| } |
| |
| |
| double GetRmz( double fZins, double fZzr, double fBw, double fZw, sal_Int32 nF ) |
| { |
| double fRmz; |
| if( fZins == 0.0 ) |
| fRmz = ( fBw + fZw ) / fZzr; |
| else |
| { |
| double fTerm = pow( 1.0 + fZins, fZzr ); |
| if( nF > 0 ) |
| fRmz = ( fZw * fZins / ( fTerm - 1.0 ) + fBw * fZins / ( 1.0 - 1.0 / fTerm ) ) / ( 1.0 + fZins ); |
| else |
| fRmz = fZw * fZins / ( fTerm - 1.0 ) + fBw * fZins / ( 1.0 - 1.0 / fTerm ); |
| } |
| |
| return -fRmz; |
| } |
| |
| |
| double GetZw( double fZins, double fZzr, double fRmz, double fBw, sal_Int32 nF ) |
| { |
| double fZw; |
| if( fZins == 0.0 ) |
| fZw = fBw + fRmz * fZzr; |
| else |
| { |
| double fTerm = pow( 1.0 + fZins, fZzr ); |
| if( nF > 0 ) |
| fZw = fBw * fTerm + fRmz * ( 1.0 + fZins ) * ( fTerm - 1.0 ) / fZins; |
| else |
| fZw = fBw * fTerm + fRmz * ( fTerm - 1.0 ) / fZins; |
| } |
| |
| return -fZw; |
| } |
| |
| |
| /*double TBillYield( constREFXPS& xOpt, sal_Int32 nSettle, sal_Int32 nMat, double fPrice ) THROWDEF_RTE_IAE |
| { |
| sal_Int32 nDiff = GetDiffDate360( xOpt, nSettle, nMat, sal_True ); |
| |
| if( fPrice <= 0.0 || nSettle >= nMat || nDiff > 360 ) |
| THROW_IAE; |
| |
| double fRet = 100.0; |
| fRet /= fPrice; |
| fRet--; |
| fRet *= double( nDiff ); |
| fRet /= 360.0; |
| |
| return fRet; |
| }*/ |
| |
| |
| //----------------------------------------------------------------------------- |
| // financial functions COUP*** |
| |
| |
| //------- |
| // COUPPCD: find last coupon date before settlement (can be equal to settlement) |
| void lcl_GetCouppcd( ScaDate& rDate, const ScaDate& rSettle, const ScaDate& rMat, sal_Int32 nFreq ) |
| throw( lang::IllegalArgumentException ) |
| { |
| rDate = rMat; |
| rDate.setYear( rSettle.getYear() ); |
| if( rDate < rSettle ) |
| rDate.addYears( 1 ); |
| while( rDate > rSettle ) |
| rDate.addMonths( -12 / nFreq ); |
| } |
| |
| double GetCouppcd( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) |
| THROWDEF_RTE_IAE |
| { |
| if( nSettle >= nMat || CHK_Freq ) |
| THROW_IAE; |
| |
| ScaDate aDate; |
| lcl_GetCouppcd( aDate, ScaDate( nNullDate, nSettle, nBase ), ScaDate( nNullDate, nMat, nBase ), nFreq ); |
| return aDate.getDate( nNullDate ); |
| } |
| |
| |
| //------- |
| // COUPNCD: find first coupon date after settlement (is never equal to settlement) |
| void lcl_GetCoupncd( ScaDate& rDate, const ScaDate& rSettle, const ScaDate& rMat, sal_Int32 nFreq ) |
| throw( lang::IllegalArgumentException ) |
| { |
| rDate = rMat; |
| rDate.setYear( rSettle.getYear() ); |
| if( rDate > rSettle ) |
| rDate.addYears( -1 ); |
| while( rDate <= rSettle ) |
| rDate.addMonths( 12 / nFreq ); |
| } |
| |
| double GetCoupncd( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) |
| THROWDEF_RTE_IAE |
| { |
| if( nSettle >= nMat || CHK_Freq ) |
| THROW_IAE; |
| |
| ScaDate aDate; |
| lcl_GetCoupncd( aDate, ScaDate( nNullDate, nSettle, nBase ), ScaDate( nNullDate, nMat, nBase ), nFreq ); |
| return aDate.getDate( nNullDate ); |
| } |
| |
| |
| //------- |
| // COUPDAYBS: get day count: coupon date before settlement <-> settlement |
| double GetCoupdaybs( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) |
| THROWDEF_RTE_IAE |
| { |
| if( nSettle >= nMat || CHK_Freq ) |
| THROW_IAE; |
| |
| ScaDate aSettle( nNullDate, nSettle, nBase ); |
| ScaDate aDate; |
| lcl_GetCouppcd( aDate, aSettle, ScaDate( nNullDate, nMat, nBase ), nFreq ); |
| return ScaDate::getDiff( aDate, aSettle ); |
| } |
| |
| |
| //------- |
| // COUPDAYSNC: get day count: settlement <-> coupon date after settlement |
| double GetCoupdaysnc( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) |
| THROWDEF_RTE_IAE |
| { |
| if( nSettle >= nMat || CHK_Freq ) |
| THROW_IAE; |
| |
| if( (nBase != 0) && (nBase != 4) ) |
| { |
| ScaDate aSettle( nNullDate, nSettle, nBase ); |
| ScaDate aDate; |
| lcl_GetCoupncd( aDate, aSettle, ScaDate( nNullDate, nMat, nBase ), nFreq ); |
| return ScaDate::getDiff( aSettle, aDate ); |
| } |
| return GetCoupdays( nNullDate, nSettle, nMat, nFreq, nBase ) - GetCoupdaybs( nNullDate, nSettle, nMat, nFreq, nBase ); |
| } |
| |
| |
| //------- |
| // COUPDAYS: get day count: coupon date before settlement <-> coupon date after settlement |
| double GetCoupdays( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) |
| THROWDEF_RTE_IAE |
| { |
| if( nSettle >= nMat || CHK_Freq ) |
| THROW_IAE; |
| |
| if( nBase == 1 ) |
| { |
| ScaDate aDate; |
| lcl_GetCouppcd( aDate, ScaDate( nNullDate, nSettle, nBase ), ScaDate( nNullDate, nMat, nBase ), nFreq ); |
| ScaDate aNextDate( aDate ); |
| aNextDate.addMonths( 12 / nFreq ); |
| return ScaDate::getDiff( aDate, aNextDate ); |
| } |
| return static_cast< double >( GetDaysInYear( 0, 0, nBase ) ) / nFreq; |
| } |
| |
| |
| //------- |
| // COUPNUM: get count of coupon dates |
| double GetCoupnum( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, sal_Int32 nFreq, sal_Int32 nBase ) |
| THROWDEF_RTE_IAE |
| { |
| if( nSettle >= nMat || CHK_Freq ) |
| THROW_IAE; |
| |
| ScaDate aMat( nNullDate, nMat, nBase ); |
| ScaDate aDate; |
| lcl_GetCouppcd( aDate, ScaDate( nNullDate, nSettle, nBase ), aMat, nFreq ); |
| sal_uInt16 nMonths = (aMat.getYear() - aDate.getYear()) * 12 + aMat.getMonth() - aDate.getMonth(); |
| return static_cast< double >( nMonths * nFreq / 12 ); |
| } |
| |
| |
| |
| |
| |
| |
| |
| const sal_uInt32 MyList::nStartSize = 16; |
| const sal_uInt32 MyList::nIncrSize = 16; |
| |
| |
| void MyList::_Grow( void ) |
| { |
| nSize += nIncrSize; |
| |
| void** pNewData = new void*[ nSize ]; |
| memcpy( pNewData, pData, nNew * sizeof( void* ) ); |
| |
| delete[] pData; |
| pData = pNewData; |
| } |
| |
| |
| MyList::MyList( void ) |
| { |
| nSize = nStartSize; |
| pData = new void*[ nSize ]; |
| nNew = nAct = 0; |
| } |
| |
| |
| MyList::~MyList() |
| { |
| delete[] pData; |
| } |
| |
| |
| void MyList::Insert( void* p, sal_uInt32 n ) |
| { |
| if( n >= nNew ) |
| Append( p ); |
| else |
| { |
| Grow(); |
| |
| void** pIns = pData + n; |
| memmove( pIns + 1, pIns, ( nNew - n ) * sizeof( void* ) ); |
| |
| *pIns = p; |
| |
| nNew++; |
| } |
| } |
| |
| |
| |
| |
| StringList::~StringList() |
| { |
| for( STRING* p = ( STRING* ) First() ; p ; p = ( STRING* ) Next() ) |
| delete p; |
| } |
| |
| |
| class AnalysisRscStrArrLoader : public Resource |
| { |
| private: |
| ResStringArray aStrArray; |
| public: |
| AnalysisRscStrArrLoader( sal_uInt16 nRsc, sal_uInt16 nArrayId, ResMgr& rResMgr ) : |
| Resource( AnalysisResId( nRsc, rResMgr ) ), |
| aStrArray( AnalysisResId( nArrayId, rResMgr ) ) |
| { |
| FreeResource(); |
| } |
| |
| const ResStringArray& GetStringArray() const { return aStrArray; } |
| }; |
| |
| |
| |
| |
| FuncData::FuncData( const FuncDataBase& r, ResMgr& rResMgr ) : |
| aIntName( OUString::createFromAscii( r.pIntName ) ), |
| nUINameID( r.nUINameID ), |
| nDescrID( r.nDescrID ), |
| bDouble( r.bDouble ), |
| bWithOpt( r.bWithOpt ), |
| nParam( r.nNumOfParams ), |
| nCompID( r.nCompListID ), |
| eCat( r.eCat ) |
| { |
| AnalysisRscStrArrLoader aArrLoader( RID_ANALYSIS_DEFFUNCTION_NAMES, nCompID, rResMgr ); |
| // ResStringArray aDefFuncNameArray( AnalysisResId( nCompID, rResMgr ) ); |
| const ResStringArray& rArr = aArrLoader.GetStringArray(); |
| |
| sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( rArr.Count() ); |
| sal_uInt16 n; |
| |
| for( n = 0 ; n < nCount ; n++ ) |
| aCompList.Append( rArr.GetString( n ) ); |
| } |
| |
| |
| FuncData::~FuncData() |
| { |
| } |
| |
| |
| sal_uInt16 FuncData::GetStrIndex( sal_uInt16 nParamNum ) const |
| { |
| if( !bWithOpt ) |
| nParamNum++; |
| |
| if( nParamNum > nParam ) |
| return nParam * 2; |
| else |
| return nParamNum * 2; |
| } |
| |
| |
| |
| |
| FuncDataList::FuncDataList( ResMgr& rResMgr ) |
| { |
| const sal_uInt32 nNum = sizeof( pFuncDatas ) / sizeof( FuncDataBase ); |
| |
| for( sal_uInt16 n = 0 ; n < nNum ; n++ ) |
| Append( new FuncData( pFuncDatas[ n ], rResMgr ) ); |
| } |
| |
| |
| FuncDataList::~FuncDataList() |
| { |
| for( FuncData* p = ( FuncData* ) First() ; p ; p = ( FuncData* ) Next() ) |
| delete p; |
| } |
| |
| |
| const FuncData* FuncDataList::Get( const OUString& aProgrammaticName ) const |
| { |
| if( aLastName == aProgrammaticName ) |
| return Get( nLast ); |
| |
| ( ( FuncDataList* ) this )->aLastName = aProgrammaticName; |
| |
| sal_uInt32 nE = Count(); |
| for( sal_uInt32 n = 0 ; n < nE ; n++ ) |
| { |
| const FuncData* p = Get( n ); |
| if( p->Is( aProgrammaticName ) ) |
| { |
| ( ( FuncDataList* ) this )->nLast = n; |
| return p; |
| } |
| } |
| |
| ( ( FuncDataList* ) this )->nLast = 0xFFFFFFFF; |
| return NULL; |
| } |
| |
| |
| AnalysisResId::AnalysisResId( sal_uInt16 nId, ResMgr& rResMgr ) : ResId( nId, rResMgr ) |
| { |
| } |
| |
| |
| |
| |
| SortedIndividualInt32List::SortedIndividualInt32List() |
| { |
| } |
| |
| |
| SortedIndividualInt32List::~SortedIndividualInt32List() |
| { |
| } |
| |
| |
| void SortedIndividualInt32List::Insert( sal_Int32 nDay ) |
| { |
| sal_uInt32 nIndex = Count(); |
| while( nIndex ) |
| { |
| nIndex--; |
| sal_Int32 nRef = Get( nIndex ); |
| if( nDay == nRef ) |
| return; |
| else if( nDay > nRef ) |
| { |
| MyList::Insert( (void*) nDay, nIndex + 1 ); |
| return; |
| } |
| } |
| MyList::Insert( (void*) nDay, 0UL ); |
| } |
| |
| |
| void SortedIndividualInt32List::Insert( sal_Int32 nDay, sal_Int32 nNullDate, sal_Bool bInsertOnWeekend ) |
| { |
| if( !nDay ) |
| return; |
| |
| nDay += nNullDate; |
| if( bInsertOnWeekend || (GetDayOfWeek( nDay ) < 5) ) |
| Insert( nDay ); |
| } |
| |
| |
| void SortedIndividualInt32List::Insert( |
| double fDay, sal_Int32 nNullDate, sal_Bool bInsertOnWeekend ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| if( (fDay < -2147483648.0) || (fDay > 2147483649.0) ) |
| throw lang::IllegalArgumentException(); |
| Insert( static_cast< sal_Int32 >( fDay ), nNullDate, bInsertOnWeekend ); |
| } |
| |
| |
| sal_Bool SortedIndividualInt32List::Find( sal_Int32 nVal ) const |
| { |
| sal_uInt32 nE = Count(); |
| |
| if( !nE || nVal < Get( 0 ) || nVal > Get( nE - 1 ) ) |
| return sal_False; |
| |
| // linear search |
| |
| for( sal_uInt32 n = 0 ; n < nE ; n++ ) |
| { |
| sal_Int32 nRef = Get( n ); |
| |
| if( nRef == nVal ) |
| return sal_True; |
| else if( nRef > nVal ) |
| return sal_False; |
| } |
| return sal_False; |
| } |
| |
| |
| void SortedIndividualInt32List::InsertHolidayList( |
| const ScaAnyConverter& rAnyConv, |
| const uno::Any& rHolAny, |
| sal_Int32 nNullDate, |
| sal_Bool bInsertOnWeekend ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| double fDay; |
| if( rAnyConv.getDouble( fDay, rHolAny ) ) |
| Insert( fDay, nNullDate, bInsertOnWeekend ); |
| } |
| |
| |
| void SortedIndividualInt32List::InsertHolidayList( |
| ScaAnyConverter& rAnyConv, |
| const uno::Reference< beans::XPropertySet >& xOptions, |
| const uno::Any& rHolAny, |
| sal_Int32 nNullDate, |
| sal_Bool bInsertOnWeekend ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| rAnyConv.init( xOptions ); |
| if( rHolAny.getValueTypeClass() == uno::TypeClass_SEQUENCE ) |
| { |
| uno::Sequence< uno::Sequence< uno::Any > > aAnySeq; |
| if( rHolAny >>= aAnySeq ) |
| { |
| const uno::Sequence< uno::Any >* pSeqArray = aAnySeq.getConstArray(); |
| for( sal_Int32 nIndex1 = 0; nIndex1 < aAnySeq.getLength(); nIndex1++ ) |
| { |
| const uno::Sequence< uno::Any >& rSubSeq = pSeqArray[ nIndex1 ]; |
| const uno::Any* pAnyArray = rSubSeq.getConstArray(); |
| |
| for( sal_Int32 nIndex2 = 0; nIndex2 < rSubSeq.getLength(); nIndex2++ ) |
| InsertHolidayList( rAnyConv, pAnyArray[ nIndex2 ], nNullDate, bInsertOnWeekend ); |
| } |
| } |
| else |
| throw lang::IllegalArgumentException(); |
| } |
| else |
| InsertHolidayList( rAnyConv, rHolAny, nNullDate, bInsertOnWeekend ); |
| } |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| |
| ScaDoubleList::~ScaDoubleList() |
| { |
| for( double* pDbl = const_cast< double* >( First() ); pDbl; pDbl = const_cast< double* >( Next() ) ) |
| delete pDbl; |
| } |
| |
| |
| void ScaDoubleList::Append( |
| const uno::Sequence< uno::Sequence< double > >& rValueSeq ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| const uno::Sequence< double >* pSeqArray = rValueSeq.getConstArray(); |
| for( sal_Int32 nIndex1 = 0; nIndex1 < rValueSeq.getLength(); nIndex1++ ) |
| { |
| const uno::Sequence< double >& rSubSeq = pSeqArray[ nIndex1 ]; |
| const double* pArray = rSubSeq.getConstArray(); |
| for( sal_Int32 nIndex2 = 0; nIndex2 < rSubSeq.getLength(); nIndex2++ ) |
| Append( pArray[ nIndex2 ] ); |
| } |
| } |
| |
| |
| void ScaDoubleList::Append( |
| const uno::Sequence< uno::Sequence< sal_Int32 > >& rValueSeq ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| const uno::Sequence< sal_Int32 >* pSeqArray = rValueSeq.getConstArray(); |
| for( sal_Int32 nIndex1 = 0; nIndex1 < rValueSeq.getLength(); nIndex1++ ) |
| { |
| const uno::Sequence< sal_Int32 >& rSubSeq = pSeqArray[ nIndex1 ]; |
| const sal_Int32* pArray = rSubSeq.getConstArray(); |
| for( sal_Int32 nIndex2 = 0; nIndex2 < rSubSeq.getLength(); nIndex2++ ) |
| Append( pArray[ nIndex2 ] ); |
| } |
| } |
| |
| |
| |
| void ScaDoubleList::Append( |
| const ScaAnyConverter& rAnyConv, |
| const uno::Any& rAny, |
| sal_Bool bIgnoreEmpty ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| if( rAny.getValueTypeClass() == uno::TypeClass_SEQUENCE ) |
| Append( rAnyConv, *static_cast< const uno::Sequence< uno::Sequence< uno::Any > >* >( rAny.getValue() ), bIgnoreEmpty ); |
| else |
| { |
| double fValue; |
| if( rAnyConv.getDouble( fValue, rAny ) ) |
| Append( fValue ); |
| else if( !bIgnoreEmpty ) |
| Append( 0.0 ); |
| } |
| } |
| |
| |
| void ScaDoubleList::Append( |
| const ScaAnyConverter& rAnyConv, |
| const uno::Sequence< uno::Any >& rAnySeq, |
| sal_Bool bIgnoreEmpty ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| const uno::Any* pArray = rAnySeq.getConstArray(); |
| for( sal_Int32 nIndex = 0; nIndex < rAnySeq.getLength(); nIndex++ ) |
| Append( rAnyConv, pArray[ nIndex ], bIgnoreEmpty ); |
| } |
| |
| |
| void ScaDoubleList::Append( |
| const ScaAnyConverter& rAnyConv, |
| const uno::Sequence< uno::Sequence< uno::Any > >& rAnySeq, |
| sal_Bool bIgnoreEmpty ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| const uno::Sequence< uno::Any >* pArray = rAnySeq.getConstArray(); |
| for( sal_Int32 nIndex = 0; nIndex < rAnySeq.getLength(); nIndex++ ) |
| Append( rAnyConv, pArray[ nIndex ], bIgnoreEmpty ); |
| } |
| |
| |
| |
| void ScaDoubleList::Append( |
| ScaAnyConverter& rAnyConv, |
| const uno::Reference< beans::XPropertySet >& xOpt, |
| const uno::Sequence< uno::Any >& rAnySeq, |
| sal_Bool bIgnoreEmpty ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| rAnyConv.init( xOpt ); |
| Append( rAnyConv, rAnySeq, bIgnoreEmpty ); |
| } |
| |
| |
| sal_Bool ScaDoubleList::CheckInsert( double ) const throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| return sal_True; |
| } |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| |
| sal_Bool ScaDoubleListGT0::CheckInsert( double fValue ) const throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| if( fValue < 0.0 ) |
| throw lang::IllegalArgumentException(); |
| return fValue > 0.0; |
| } |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| |
| sal_Bool ScaDoubleListGE0::CheckInsert( double fValue ) const throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| if( fValue < 0.0 ) |
| throw lang::IllegalArgumentException(); |
| return sal_True; |
| } |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| |
| Complex::Complex( const STRING& rStr ) THROWDEF_RTE_IAE |
| { |
| if( !ParseString( rStr, *this ) ) |
| THROW_IAE; |
| } |
| |
| |
| inline sal_Bool Complex::IsImagUnit( sal_Unicode c ) |
| { |
| return c == 'i' || c == 'j'; |
| } |
| |
| sal_Bool Complex::ParseString( const STRING& rStr, Complex& rCompl ) |
| { |
| rCompl.c = '\0'; // do not force a symbol, if only real part present |
| |
| const sal_Unicode* pStr = rStr.getStr(); |
| |
| if( IsImagUnit( *pStr ) && rStr.getLength() == 1) |
| { |
| rCompl.Num= double_complex ( 0.0, 1.0 ); |
| rCompl.c = *pStr; |
| return sal_True; |
| } |
| |
| double f; |
| |
| if( !ParseDouble( pStr, f ) ) |
| return sal_False; |
| |
| switch( *pStr ) |
| { |
| case '-': // imag part follows |
| case '+': |
| { |
| double r = f; |
| if( IsImagUnit( pStr[ 1 ] ) ) |
| { |
| rCompl.c = pStr[ 1 ]; |
| if( pStr[ 2 ] == 0 ) |
| { |
| rCompl.Num = double_complex (f, ( *pStr == '+' )? 1.0 : -1.0 ); |
| return sal_True; |
| } |
| } |
| else if( ParseDouble( pStr, f ) && IsImagUnit( *pStr ) ) |
| { |
| rCompl.c = *pStr; |
| pStr++; |
| if( *pStr == 0 ) |
| { |
| rCompl.Num = double_complex (r, f); |
| return sal_True; |
| } |
| } |
| } |
| break; |
| case 'j': |
| case 'i': |
| rCompl.c = *pStr; |
| pStr++; |
| if( *pStr == 0 ) |
| { |
| rCompl.Num = double_complex (0.0, f); |
| return sal_True; |
| } |
| break; |
| case 0: // only real-part |
| rCompl.Num = double_complex (f, 0.0); |
| return sal_True; |
| } |
| |
| return sal_False; |
| } |
| |
| |
| STRING Complex::GetString() const THROWDEF_RTE_IAE |
| { |
| static const String aI( 'i' ); |
| static const String aJ( 'j' ); |
| static const String aPlus( '+' ); |
| static const String aMinus( '-' ); |
| |
| CHK_FINITE(Num.real()); |
| CHK_FINITE(Num.imag()); |
| STRING aRet; |
| |
| bool bHasImag = Num.imag() != 0.0; |
| bool bHasReal = !bHasImag || (Num.real() != 0.0); |
| |
| if( bHasReal ) |
| aRet = ::GetString( Num.real() ); |
| if( bHasImag ) |
| { |
| if( Num.imag() == 1.0 ) |
| { |
| if( bHasReal ) |
| aRet += aPlus; |
| } |
| else if( Num.imag() == -1.0 ) |
| aRet += aMinus; |
| else |
| aRet += ::GetString( Num.imag(), bHasReal ); |
| aRet += (c != 'j') ? aI : aJ; |
| } |
| |
| return aRet; |
| } |
| |
| |
| double Complex::Arg( void ) const THROWDEF_RTE_IAE |
| { |
| if( Num.real() == 0.0 && Num.imag() == 0.0 ) |
| THROW_IAE; |
| |
| double phi = acos( Num.real() / Abs() ); |
| |
| if( Num.imag() < 0.0 ) |
| phi = -phi; |
| |
| return phi; |
| } |
| |
| |
| void Complex::Power( double fPower ) THROWDEF_RTE_IAE |
| { |
| if( Num.real() == 0.0 && Num.imag() == 0.0 ) |
| { |
| if( fPower > 0 ) |
| { |
| Num = double_complex ( 0.0, 0.0 ); |
| return; |
| } |
| else |
| THROW_IAE; |
| } |
| |
| double p, phi; |
| |
| p = Abs(); |
| |
| phi = acos( Num.real() / p ); |
| if( Num.imag() < 0.0 ) |
| phi = -phi; |
| |
| p = pow( p, fPower ); |
| phi *= fPower; |
| |
| Num = double_complex (cos( phi ) * p, sin( phi ) * p); |
| } |
| |
| |
| void Complex::Sqrt( void ) |
| { |
| static const double fMultConst = 0.7071067811865475; // ...2440084436210485 = 1/sqrt(2) |
| double p = Abs(); |
| double i_ = sqrt( p - Num.real() ) * fMultConst; |
| |
| Num = double_complex (sqrt( p + Num.real() ) * fMultConst, ( Num.imag() < 0.0 )? -i_ : i_); |
| } |
| |
| |
| void Complex::Sin( void ) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| |
| if( i ) |
| { |
| double r_; |
| |
| r_ = sin( r ) * cosh( i ); |
| i = cos( r ) * sinh( i ); |
| r = r_; |
| } |
| else |
| r = sin( r ); |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| void Complex::Cos( void ) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| |
| if( i ) |
| { |
| double r_; |
| |
| r_ = cos( r ) * cosh( i ); |
| i = -( sin( r ) * sinh( i ) ); |
| r = r_; |
| } |
| else |
| r = cos( r ); |
| Num = double_complex ( r, i ); |
| |
| } |
| |
| void Complex::Div( const Complex& z ) THROWDEF_RTE_IAE |
| { |
| if( z.Num.real() == 0 && z.Num.imag() == 0 ) |
| THROW_IAE; |
| |
| double a1 = Num.real(); |
| double a2 = z.Num.real(); |
| double b1 = Num.imag(); |
| double b2 = z.Num.imag(); |
| |
| double f = 1.0 / ( a2 * a2 + b2 * b2 ); |
| |
| Num = f * double_complex ( a1 * a2 + b1 * b2 , a2 * b1 - a1 * b2 ); |
| |
| if( !c ) c = z.c; |
| } |
| |
| |
| void Complex::Exp( void ) |
| { |
| double fE = exp( Num.real() ); |
| Num = fE * double_complex ( cos( Num.imag() ), sin( Num.imag() ) ); |
| } |
| |
| |
| void Complex::Ln( void ) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if( r == 0.0 && i == 0.0 ) |
| THROW_IAE; |
| |
| double fAbs = Abs(); |
| sal_Bool bNegi = i < 0.0; |
| |
| i = acos( r / fAbs ); |
| |
| if( bNegi ) |
| i = -i; |
| |
| r = log( fAbs ); |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| void Complex::Log10( void ) THROWDEF_RTE_IAE |
| { |
| Ln(); |
| Mult( 0.434294481903251828 ); // * log10( e ) |
| } |
| |
| |
| void Complex::Log2( void ) THROWDEF_RTE_IAE |
| { |
| Ln(); |
| Mult( 1.442695040888963407 ); // * log2( e ) |
| } |
| |
| |
| void Complex::Tan(void) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if ( i ) |
| { |
| if( !::rtl::math::isValidArcArg( 2.0 * r ) ) |
| THROW_IAE; |
| double fScale =1.0 / ( cos( 2.0 * r ) + cosh( 2.0 * i )); |
| r = sin( 2.0 * r ) * fScale; |
| i = sinh( 2.0 * i ) * fScale; |
| } |
| else |
| { |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| r = tan( r ); |
| } |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| void Complex::Sec( void ) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if( i ) |
| { |
| if( !::rtl::math::isValidArcArg( 2 * r ) ) |
| THROW_IAE; |
| double fScale = 1.0 / (cosh( 2.0 * i) + cos ( 2.0 * r)); |
| double r_; |
| r_ = 2.0 * cos( r ) * cosh( i ) * fScale; |
| i = 2.0 * sin( r ) * sinh( i ) * fScale; |
| r = r_; |
| } |
| else |
| { |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| r = 1.0 / cos( r ); |
| } |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| void Complex::Csc( void ) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if( i ) |
| { |
| if( !::rtl::math::isValidArcArg( 2 * r ) ) |
| THROW_IAE; |
| double fScale = 1.0 / (cosh( 2.0 * i) - cos ( 2.0 * r)); |
| double r_; |
| r_ = 2.0 * sin( r ) * cosh( i ) * fScale; |
| i = -2.0 * cos( r ) * sinh( i ) * fScale; |
| r = r_; |
| } |
| else |
| { |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| r = 1.0 / sin( r ); |
| } |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| void Complex::Cot(void) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if ( i ) |
| { |
| if( !::rtl::math::isValidArcArg( 2.0 * r ) ) |
| THROW_IAE; |
| double fScale =1.0 / ( cosh( 2.0 * i ) - cos( 2.0 * r ) ); |
| r = sin( 2.0 * r ) * fScale; |
| i = - ( sinh( 2.0 * i ) * fScale ); |
| } |
| else |
| { |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| r = 1.0 / tan( r ); |
| } |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| void Complex::Sinh( void ) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| |
| if( i ) |
| { |
| double r_; |
| r_ = sinh( r ) * cos( i ); |
| i = cosh( r ) * sin( i ); |
| r = r_; |
| } |
| else |
| r = sinh( r ); |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| void Complex::Cosh( void ) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| |
| if( i ) |
| { |
| double r_; |
| r_ = cosh( r ) * cos( i ); |
| i = sinh( r ) * sin( i ); |
| r = r_; |
| } |
| else |
| r = cosh( r ); |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| void Complex::Sech(void) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if ( i ) |
| { |
| if( !::rtl::math::isValidArcArg( 2.0 * r ) ) |
| THROW_IAE; |
| double fScale =1.0 / ( cosh( 2.0 * r ) + cos( 2.0 * i )); |
| double r_; |
| r_ = 2.0 * cosh( r ) * cos( i ) * fScale; |
| i = - (2.0 * sinh( r ) * sin( i ) * fScale ); |
| r = r_ ; |
| } |
| else |
| { |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| r = 1.0 / cosh( r ); |
| } |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| void Complex::Csch(void) THROWDEF_RTE_IAE |
| { |
| double r = Num.real(), i = Num.imag() ; |
| if ( i ) |
| { |
| if( !::rtl::math::isValidArcArg( 2.0 * r ) ) |
| THROW_IAE; |
| double fScale =1.0 / ( cosh( 2.0 * r ) - cos( 2.0 * i )); |
| double r_; |
| r_ = 2.0 * sinh( r ) * cos( i ) * fScale; |
| i = - ( 2.0 * cosh( r ) * sin( i ) * fScale ); |
| r = r_ ; |
| } |
| else |
| { |
| if( !::rtl::math::isValidArcArg( r ) ) |
| THROW_IAE; |
| r = 1.0 / sinh( r ); |
| } |
| Num = double_complex ( r, i ); |
| } |
| |
| |
| ComplexList::~ComplexList() |
| { |
| for( Complex* p = ( Complex* ) First() ; p ; p = ( Complex* ) Next() ) |
| delete p; |
| } |
| |
| |
| void ComplexList::Append( const SEQSEQ( STRING )& r, ComplListAppendHandl eAH ) THROWDEF_RTE_IAE |
| { |
| sal_Int32 n1, n2; |
| sal_Int32 nE1 = r.getLength(); |
| sal_Int32 nE2; |
| sal_Bool bEmpty0 = eAH == AH_EmpyAs0; |
| sal_Bool bErrOnEmpty = eAH == AH_EmptyAsErr; |
| |
| for( n1 = 0 ; n1 < nE1 ; n1++ ) |
| { |
| const SEQ( STRING )& rList = r[ n1 ]; |
| nE2 = rList.getLength(); |
| |
| for( n2 = 0 ; n2 < nE2 ; n2++ ) |
| { |
| const STRING& rStr = rList[ n2 ]; |
| |
| if( rStr.getLength() ) |
| Append( new Complex( rStr ) ); |
| else if( bEmpty0 ) |
| Append( new Complex( 0.0 ) ); |
| else if( bErrOnEmpty ) |
| THROW_IAE; |
| } |
| } |
| } |
| |
| |
| void ComplexList::Append( const SEQ( ANY )& aMultPars, ComplListAppendHandl eAH ) THROWDEF_RTE_IAE |
| { |
| sal_Int32 nEle = aMultPars.getLength(); |
| sal_Bool bEmpty0 = eAH == AH_EmpyAs0; |
| sal_Bool bErrOnEmpty = eAH == AH_EmptyAsErr; |
| |
| for( sal_Int32 i = 0 ; i < nEle ; i++ ) |
| { |
| const ANY& r = aMultPars[ i ]; |
| switch( r.getValueTypeClass() ) |
| { |
| case uno::TypeClass_VOID: break; |
| case uno::TypeClass_STRING: |
| { |
| const STRING* pStr = ( const STRING* ) r.getValue(); |
| |
| if( pStr->getLength() ) |
| Append( new Complex( *( STRING* ) r.getValue() ) ); |
| else if( bEmpty0 ) |
| Append( new Complex( 0.0 ) ); |
| else if( bErrOnEmpty ) |
| THROW_IAE; |
| } |
| break; |
| case uno::TypeClass_DOUBLE: |
| Append( new Complex( *( double* ) r.getValue(), 0.0 ) ); |
| break; |
| case uno::TypeClass_SEQUENCE: |
| { |
| SEQSEQ( ANY ) aValArr; |
| if( r >>= aValArr ) |
| { |
| sal_Int32 nE = aValArr.getLength(); |
| const SEQ( ANY )* pArr = aValArr.getConstArray(); |
| for( sal_Int32 n = 0 ; n < nE ; n++ ) |
| Append( pArr[ n ], eAH ); |
| } |
| else |
| THROW_IAE; |
| } |
| break; |
| default: |
| THROW_IAE; |
| } |
| } |
| } |
| |
| |
| |
| |
| ConvertData::ConvertData( const sal_Char p[], double fC, ConvertDataClass e, sal_Bool bPrefSupport ) : aName( p, strlen( p ), RTL_TEXTENCODING_MS_1252 ) |
| { |
| fConst = fC; |
| eClass = e; |
| bPrefixSupport = bPrefSupport; |
| } |
| |
| ConvertData::~ConvertData() |
| { |
| } |
| |
| |
| sal_Int16 ConvertData::GetMatchingLevel( const STRING& rRef ) const |
| { |
| STRING aStr = rRef; |
| sal_Int32 nLen = rRef.getLength(); |
| sal_Int32 nIndex = rRef.lastIndexOf( '^' ); |
| if( nIndex > 0 && nIndex == ( nLen - 2 ) ) |
| { |
| const sal_Unicode* p = aStr.getStr(); |
| aStr = STRING( p, nLen - 2 ); |
| aStr += STRING( p[ nLen - 1 ] ); |
| } |
| if( aName.equals( aStr ) ) |
| return 0; |
| else |
| { |
| const sal_Unicode* p = aStr.getStr(); |
| |
| nLen = aStr.getLength(); |
| bool bPref = IsPrefixSupport(); |
| bool bOneChar = (bPref && nLen > 1 && (aName == p + 1)); |
| if (bOneChar || (bPref && nLen > 2 && (aName == p + 2) && |
| *p == 'd' && *(p+1) == 'a')) |
| { |
| sal_Int16 n; |
| switch( *p ) |
| { |
| case 'y': n = -24; break; // yocto |
| case 'z': n = -21; break; // zepto |
| case 'a': n = -18; break; |
| case 'f': n = -15; break; |
| case 'p': n = -12; break; |
| case 'n': n = -9; break; |
| case 'u': n = -6; break; |
| case 'm': n = -3; break; |
| case 'c': n = -2; break; |
| case 'd': |
| { |
| if ( bOneChar ) |
| n = -1; // deci |
| else |
| n = 1; // deca |
| } |
| break; |
| case 'e': n = 1; break; |
| case 'h': n = 2; break; |
| case 'k': n = 3; break; |
| case 'M': n = 6; break; |
| case 'G': n = 9; break; |
| case 'T': n = 12; break; |
| case 'P': n = 15; break; |
| case 'E': n = 18; break; |
| case 'Z': n = 21; break; // zetta |
| case 'Y': n = 24; break; // yotta |
| default: |
| n = INV_MATCHLEV; |
| } |
| |
| // We could weed some nonsense out, ODFF doesn't say so though. |
| #if 0 |
| if (n < 0 && Class() == CDC_Information) |
| n = INV_MATCHLEV; // milli-bits doesn't make sense |
| #endif |
| |
| //! <HACK> #100616# "cm3" is not 10^-2 m^3 but 10^-6 m^3 !!! ------------------ |
| if( n != INV_MATCHLEV ) |
| { |
| sal_Unicode cLast = p[ aStr.getLength() - 1 ]; |
| if( cLast == '2' ) |
| n *= 2; |
| else if( cLast == '3' ) |
| n *= 3; |
| } |
| //! </HACK> ------------------------------------------------------------------- |
| |
| return n; |
| } |
| else if ( nLen > 2 && ( aName == p + 2 ) && ( Class() == CDC_Information ) ) |
| { |
| const sal_Unicode* pStr = aStr.getStr(); |
| if ( *(pStr + 1) != 'i') |
| return INV_MATCHLEV; |
| sal_Int16 n; |
| switch( *pStr ) |
| { |
| case 'k': n = 10; break; |
| case 'M': n = 20; break; |
| case 'G': n = 30; break; |
| case 'T': n = 40; break; |
| case 'P': n = 50; break; |
| case 'E': n = 60; break; |
| case 'Z': n = 70; break; |
| case 'Y': n = 80; break; |
| default: |
| n = INV_MATCHLEV; |
| } |
| return n; |
| } |
| else |
| return INV_MATCHLEV; |
| } |
| } |
| |
| |
| double ConvertData::Convert( |
| double f, const ConvertData& r, sal_Int16 nLevFrom, sal_Int16 nLevTo ) const THROWDEF_RTE_IAE |
| { |
| if( Class() != r.Class() ) |
| THROW_IAE; |
| |
| sal_Bool bBinFromLev = ( nLevFrom > 0 && ( nLevFrom % 10 ) == 0 ); |
| sal_Bool bBinToLev = ( nLevTo > 0 && ( nLevTo % 10 ) == 0 ); |
| |
| if ( Class() == CDC_Information && ( bBinFromLev || bBinToLev ) ) |
| { |
| if ( bBinFromLev && bBinToLev ) |
| { |
| nLevFrom = sal::static_int_cast<sal_Int16>( nLevFrom - nLevTo ); |
| f *= r.fConst / fConst; |
| if( nLevFrom ) |
| f *= pow( 2.0, nLevFrom ); |
| } |
| else if ( bBinFromLev ) |
| f *= ( r.fConst / fConst ) * ( pow( 2.0, nLevFrom ) / pow( 10.0, nLevTo ) ); |
| else |
| f *= ( r.fConst / fConst ) * ( pow( 10.0, nLevFrom ) / pow( 2.0, nLevTo ) ); |
| return f; |
| } |
| |
| nLevFrom = sal::static_int_cast<sal_Int16>( nLevFrom - nLevTo ); // effective level |
| |
| f *= r.fConst / fConst; |
| |
| if( nLevFrom ) |
| f = ::rtl::math::pow10Exp( f, nLevFrom ); |
| |
| return f; |
| } |
| |
| |
| double ConvertData::ConvertToBase( double f, sal_Int16 n ) const |
| { |
| return ::rtl::math::pow10Exp( f / fConst, n ); |
| } |
| |
| |
| double ConvertData::ConvertFromBase( double f, sal_Int16 n ) const |
| { |
| return ::rtl::math::pow10Exp( f * fConst, -n ); |
| } |
| |
| |
| |
| ConvertDataLinear::~ConvertDataLinear() |
| { |
| } |
| |
| double ConvertDataLinear::Convert( |
| double f, const ConvertData& r, sal_Int16 nLevFrom, sal_Int16 nLevTo ) const THROWDEF_RTE_IAE |
| { |
| if( Class() != r.Class() ) |
| THROW_IAE; |
| |
| // return ::rtl::math::round( r.ConvertFromBase( ConvertToBase( f, nLevFrom ), nLevTo ), 13 ); |
| return r.ConvertFromBase( ConvertToBase( f, nLevFrom ), nLevTo ); |
| } |
| |
| |
| double ConvertDataLinear::ConvertToBase( double f, sal_Int16 n ) const |
| { |
| if( n ) |
| f = ::rtl::math::pow10Exp( f, n ); |
| |
| f /= fConst; |
| f -= fOffs; |
| |
| return f; |
| } |
| |
| |
| double ConvertDataLinear::ConvertFromBase( double f, sal_Int16 n ) const |
| { |
| f += fOffs; |
| f *= fConst; |
| |
| if( n ) |
| f = ::rtl::math::pow10Exp( f, -n ); |
| |
| return f; |
| } |
| |
| |
| |
| |
| ConvertDataList::ConvertDataList( void ) |
| { |
| #define NEWD(str,unit,cl) Append(new ConvertData(str,unit,cl)) |
| #define NEWDP(str,unit,cl) Append(new ConvertData(str,unit,cl,sal_True)) |
| #define NEWL(str,unit,offs,cl) Append(new ConvertDataLinear(str,unit,offs,cl)) |
| #define NEWLP(str,unit,offs,cl) Append(new ConvertDataLinear(str,unit,offs,cl,sal_True)) |
| |
| // *** are extra and not standard Excel Analysis Addin! |
| |
| // MASS: 1 Gram is... |
| NEWDP( "g", 1.0000000000000000E00, CDC_Mass ); // Gram |
| NEWD( "sg", 6.8522050005347800E-05, CDC_Mass ); // Pieces |
| NEWD( "lbm", 2.2046229146913400E-03, CDC_Mass ); // Pound (commercial weight) |
| NEWDP( "u", 6.0221370000000000E23, CDC_Mass ); // U (atomic mass) |
| NEWD( "ozm", 3.5273971800362700E-02, CDC_Mass ); // Ounce (commercial weight) |
| NEWD( "stone", 1.574730e-04, CDC_Mass ); // *** Stone |
| NEWD( "ton", 1.102311e-06, CDC_Mass ); // *** Ton |
| NEWD( "grain", 1.543236E01, CDC_Mass ); // *** Grain |
| NEWD( "pweight", 7.054792E-01, CDC_Mass ); // *** Pennyweight |
| NEWD( "hweight", 1.968413E-05, CDC_Mass ); // *** Hundredweight |
| NEWD( "shweight", 2.204623E-05, CDC_Mass ); // *** Shorthundredweight |
| NEWD( "brton", 9.842065E-07, CDC_Mass ); // *** Gross Registered Ton |
| NEWD( "cwt", 2.2046226218487758E-05, CDC_Mass ); // U.S. (short) hundredweight |
| NEWD( "shweight", 2.2046226218487758E-05, CDC_Mass ); // U.S. (short) hundredweight also |
| NEWD( "uk_cwt", 1.9684130552221213E-05, CDC_Mass ); // Imperial hundredweight |
| NEWD( "lcwt", 1.9684130552221213E-05, CDC_Mass ); // Imperial hundredweight also |
| NEWD( "hweight", 1.9684130552221213E-05, CDC_Mass ); // Imperial hundredweight also |
| NEWD( "uk_ton", 9.8420652761106063E-07, CDC_Mass ); // Imperial ton |
| NEWD( "LTON", 9.8420652761106063E-07, CDC_Mass ); // Imperial ton also |
| |
| // LENGTH: 1 Meter is... |
| NEWDP( "m", 1.0000000000000000E00, CDC_Length ); // Meter |
| NEWD( "mi", 6.2137119223733397E-04, CDC_Length ); // Britsh Mile 6,21371192237333969617434184363e-4 |
| NEWD( "Nmi", 5.3995680345572354E-04, CDC_Length ); // Nautical Mile 5,39956803455723542116630669546e-4 |
| NEWD( "in", 3.9370078740157480E01, CDC_Length ); // Inch 39,37007874015748031496062992126 |
| NEWD( "ft", 3.2808398950131234E00, CDC_Length ); // Foot 3,2808398950131233595800524934383 |
| NEWD( "yd", 1.0936132983377078E00, CDC_Length ); // Yard 1,0936132983377077865266841644794 |
| NEWDP( "ang", 1.0000000000000000E10, CDC_Length ); // Angstroem |
| NEWD( "Pica", 2.8346456692913386E03, CDC_Length ); // Pica (1/72 Inch) 2834,6456692913385826771653543307 |
| NEWD( "ell", 8.748906E-01, CDC_Length ); // *** Ell |
| NEWDP( "parsec", 3.240779E-17, CDC_Length ); // *** Parsec |
| NEWDP( "pc", 3.240779E-17, CDC_Length ); // *** Parsec also |
| NEWDP( "lightyear", 1.0570234557732930E-16, CDC_Length ); // *** Light Year |
| NEWDP( "ly", 1.0570234557732930E-16, CDC_Length ); // *** Light Year also |
| NEWD( "survey_mi", 6.2136994949494949E-04, CDC_Length ); // U.S. survey mile |
| |
| // TIME: 1 Second is... |
| NEWD( "yr", 3.1688087814028950E-08, CDC_Time ); // Year |
| NEWD( "day", 1.1574074074074074E-05, CDC_Time ); // Day |
| NEWD( "d", 1.1574074074074074E-05, CDC_Time ); // Day also |
| NEWD( "hr", 2.7777777777777778E-04, CDC_Time ); // Hour |
| NEWD( "mn", 1.6666666666666667E-02, CDC_Time ); // Minute |
| NEWD( "min", 1.6666666666666667E-02, CDC_Time ); // Minute also |
| NEWDP( "sec", 1.0000000000000000E00, CDC_Time ); // Second |
| NEWDP( "s", 1.0000000000000000E00, CDC_Time ); // Second also |
| |
| // PRESSURE: 1 Pascal is... |
| NEWDP( "Pa", 1.0000000000000000E00, CDC_Pressure ); // Pascal |
| NEWDP( "atm", 9.8692329999819300E-06, CDC_Pressure ); // Atmosphere |
| NEWDP( "at", 9.8692329999819300E-06, CDC_Pressure ); // Atmosphere also |
| NEWDP( "mmHg", 7.5006170799862700E-03, CDC_Pressure ); // mm Hg (Mercury) |
| NEWD( "Torr", 7.5006380000000000E-03, CDC_Pressure ); // *** Torr |
| NEWD( "psi", 1.4503770000000000E-04, CDC_Pressure ); // *** Psi |
| |
| // FORCE: 1 Newton is... |
| NEWDP( "N", 1.0000000000000000E00, CDC_Force ); // Newton |
| NEWDP( "dyn", 1.0000000000000000E05, CDC_Force ); // Dyn |
| NEWDP( "dy", 1.0000000000000000E05, CDC_Force ); // Dyn also |
| NEWD( "lbf", 2.24808923655339E-01, CDC_Force ); // Pound-Force |
| NEWDP( "pond", 1.019716E02, CDC_Force ); // *** Pond |
| |
| // ENERGY: 1 Joule is... |
| NEWDP( "J", 1.0000000000000000E00, CDC_Energy ); // Joule |
| NEWDP( "e", 1.0000000000000000E07, CDC_Energy ); // Erg -> http://www.chemie.fu-berlin.de/chemistry/general/si.html |
| // NEWD( "e", 9.99999519343231E06, CDC_Energy ); // Erg |
| NEWDP( "c", 2.3900624947346700E-01, CDC_Energy ); // Thermodynamical Calorie |
| NEWDP( "cal", 2.3884619064201700E-01, CDC_Energy ); // Calorie |
| NEWDP( "eV", 6.2414570000000000E18, CDC_Energy ); // Electronvolt |
| NEWDP( "ev", 6.2414570000000000E18, CDC_Energy ); // Electronvolt also |
| NEWD( "HPh", 3.7250611111111111E-07, CDC_Energy ); // Horsepower Hours |
| NEWD( "hh", 3.7250611111111111E-07, CDC_Energy ); // Horsepower Hours also |
| // NEWD( "HPh", 3.72506430801000E-07, CDC_Energy ); // Horsepower Hours |
| NEWDP( "Wh", 2.7777777777777778E-04, CDC_Energy ); // Watt Hours |
| NEWDP( "wh", 2.7777777777777778E-04, CDC_Energy ); // Watt Hours also |
| NEWD( "flb", 2.37304222192651E01, CDC_Energy ); // Foot Pound |
| NEWD( "BTU", 9.4781506734901500E-04, CDC_Energy ); // British Thermal Unit |
| NEWD( "btu", 9.4781506734901500E-04, CDC_Energy ); // British Thermal Unit also |
| |
| // POWER: 1 Watt is... |
| NEWDP( "W", 1.0000000000000000E00, CDC_Power ); // Watt |
| NEWDP( "w", 1.0000000000000000E00, CDC_Power ); // Watt also |
| NEWD( "HP", 1.341022E-03, CDC_Power ); // Horsepower |
| NEWD( "h", 1.341022E-03, CDC_Power ); // Horsepower also |
| NEWD( "PS", 1.359622E-03, CDC_Power ); // *** German Pferdestaerke |
| // NEWD( "HP", 1.4102006031908E-03, CDC_Power ); // Excel seems to be a little bit wrong... either this doesn't fit to J -> HPh |
| |
| // MAGNETISM: 1 Tesla is... |
| NEWDP( "T", 1.0000000000000000E00, CDC_Magnetism ); // Tesla |
| NEWDP( "ga", 1.0000000000000000E04, CDC_Magnetism ); // Gauss |
| |
| // TEMPERATURE: 1 Kelvin is... |
| NEWL( "C", 1.0000000000000000E00, -2.7315000000000000E02, CDC_Temperature ); // Celsius |
| NEWL( "cel", 1.0000000000000000E00, -2.7315000000000000E02, CDC_Temperature ); // Celsius also |
| NEWL( "F", 1.8000000000000000E00, -2.5537222222222222E02, CDC_Temperature ); // Fahrenheit |
| NEWL( "fah", 1.8000000000000000E00, -2.5537222222222222E02, CDC_Temperature ); // Fahrenheit also |
| NEWLP( "K", 1.0000000000000000E00, +0.0000000000000000E00, CDC_Temperature ); // Kelvin |
| NEWLP( "kel", 1.0000000000000000E00, +0.0000000000000000E00, CDC_Temperature ); // Kelvin also |
| NEWL( "Reau", 8.0000000000000000E-01, -2.7315000000000000E02, CDC_Temperature ); // *** Reaumur |
| NEWL( "Rank", 1.8000000000000000E00, +0.0000000000000000E00, CDC_Temperature ); // *** Rankine |
| |
| // VOLUME: 1 Liter is... |
| NEWD( "tsp", 2.0284000000000000E02, CDC_Volume ); // Teaspoon |
| NEWD( "tbs", 6.7613333333333333E01, CDC_Volume ); // Tablespoon |
| NEWD( "oz", 3.3806666666666667E01, CDC_Volume ); // Ounce Liquid |
| NEWD( "cup", 4.2258333333333333E00, CDC_Volume ); // Cup |
| NEWD( "pt", 2.1129166666666667E00, CDC_Volume ); // US Pint |
| NEWD( "us_pt", 2.1129166666666667E00, CDC_Volume ); // US Pint also |
| NEWD( "uk_pt", 1.75975569552166E00, CDC_Volume ); // UK Pint |
| NEWD( "qt", 1.0564583333333333E00, CDC_Volume ); // Quart |
| NEWD( "gal", 2.6411458333333333E-01, CDC_Volume ); // Gallone |
| NEWDP( "l", 1.0000000000000000E00, CDC_Volume ); // Liter |
| NEWDP( "L", 1.0000000000000000E00, CDC_Volume ); // Liter also |
| NEWDP( "lt", 1.0000000000000000E00, CDC_Volume ); // Liter also |
| NEWDP( "m3", 1.0000000000000000E-03, CDC_Volume ); // *** Cubic Meter |
| NEWD( "mi3", 2.3991275857892772E-13, CDC_Volume ); // *** Cubic Britsh Mile |
| NEWD( "Nmi3", 1.5742621468581148E-13, CDC_Volume ); // *** Cubic Nautical Mile |
| NEWD( "in3", 6.1023744094732284E01, CDC_Volume ); // *** Cubic Inch |
| NEWD( "ft3", 3.5314666721488590E-02, CDC_Volume ); // *** Cubic Foot |
| NEWD( "yd3", 1.3079506193143922E-03, CDC_Volume ); // *** Cubic Yard |
| NEWDP( "ang3", 1.0000000000000000E27, CDC_Volume ); // *** Cubic Angstroem |
| NEWD( "Pica3", 2.2776990435870636E07, CDC_Volume ); // *** Cubic Pica |
| NEWD( "barrel", 6.289811E-03, CDC_Volume ); // *** Barrel (=42gal?) |
| NEWD( "bushel", 2.837759E-02, CDC_Volume ); // *** Bushel |
| NEWD( "regton", 3.531467E-04, CDC_Volume ); // *** Register ton |
| NEWD( "GRT", 3.531467E-04, CDC_Volume ); // *** Register ton also |
| NEWD( "Schooner", 2.3529411764705882E00, CDC_Volume ); // *** austr. Schooner |
| NEWD( "Middy", 3.5087719298245614E00, CDC_Volume ); // *** austr. Middy |
| NEWD( "Glass", 5.0000000000000000E00, CDC_Volume ); // *** austr. Glass |
| NEWD( "Sixpack", 0.5, CDC_Volume ); // *** |
| NEWD( "Humpen", 2.0, CDC_Volume ); // *** |
| NEWD( "ly3", 1.1810108125623799E-51, CDC_Volume ); // *** Cubic light-year |
| NEWD( "MTON", 1.4125866688595436E00, CDC_Volume ); // *** Measurement ton |
| NEWD( "tspm", 5.0000000000000000E02, CDC_Volume ); // *** Modern teaspoon |
| NEWD( "uk_gal", 2.199694619402070E-01, CDC_Volume ); // U.K. / Imperial gallon |
| NEWD( "uk_qt", 8.798778477608300E-01, CDC_Volume ); // U.K. / Imperial quart |
| |
| // 1 Square Meter is... |
| NEWDP( "m2", 1.0000000000000000E00, CDC_Area ); // *** Square Meter |
| NEWD( "mi2", 3.8610215854244585E-07, CDC_Area ); // *** Square Britsh Mile |
| NEWD( "Nmi2", 2.9155334959812286E-07, CDC_Area ); // *** Square Nautical Mile |
| NEWD( "in2", 1.5500031000062000E03, CDC_Area ); // *** Square Inch |
| NEWD( "ft2", 1.0763910416709722E01, CDC_Area ); // *** Square Foot |
| NEWD( "yd2", 1.1959900463010803E00, CDC_Area ); // *** Square Yard |
| NEWDP( "ang2", 1.0000000000000000E20, CDC_Area ); // *** Square Angstroem |
| NEWD( "Pica2", 8.0352160704321409E06, CDC_Area ); // *** Square Pica |
| NEWD( "Morgen", 4.0000000000000000E-04, CDC_Area ); // *** Morgen |
| NEWDP( "ar", 1.000000E-02, CDC_Area ); // *** Ar |
| NEWD( "acre", 2.471053815E-04, CDC_Area ); // *** Acre |
| NEWD( "uk_acre", 2.4710538146716534E-04, CDC_Area ); // *** International acre |
| NEWD( "us_acre", 2.4710439304662790E-04, CDC_Area ); // *** U.S. survey/statute acre |
| NEWD( "ly2", 1.1172985860549147E-32, CDC_Area ); // *** Square Light-year |
| NEWD( "ha", 1.000000E-04, CDC_Area ); // *** Hectare |
| NEWD( "Quadratlatschen",5.6689342403628117914,CDC_Area ); // *** |
| |
| // SPEED: 1 Meter per Second is... |
| NEWDP( "m/s", 1.0000000000000000E00, CDC_Speed ); // *** Meters per Second |
| NEWDP( "m/sec", 1.0000000000000000E00, CDC_Speed ); // *** Meters per Second also |
| NEWDP( "m/h", 3.6000000000000000E03, CDC_Speed ); // *** Meters per Hour |
| NEWDP( "m/hr", 3.6000000000000000E03, CDC_Speed ); // *** Meters per Hour also |
| NEWD( "mph", 2.2369362920544023E00, CDC_Speed ); // *** Britsh Miles per Hour |
| NEWD( "kn", 1.9438444924406048E00, CDC_Speed ); // *** Knot = Nautical Miles per Hour |
| NEWD( "admkn", 1.9438446603753486E00, CDC_Speed ); // *** Admiralty Knot |
| NEWD( "wahnsinnige Geschwindigkeit", 2.0494886343432328E-14, CDC_Speed ); // *** |
| NEWD( "ludicrous speed", 2.0494886343432328E-14, CDC_Speed ); // *** |
| NEWD( "laecherliche Geschwindigkeit", 4.0156958471424288E-06, CDC_Speed); // *** |
| NEWD( "ridiculous speed", 4.0156958471424288E-06, CDC_Speed); // *** |
| |
| // INFORMATION: 1 Bit is... |
| NEWDP( "bit", 1.00E00, CDC_Information); // *** Bit |
| NEWDP( "byte", 1.25E-01, CDC_Information); // *** Byte |
| } |
| |
| |
| ConvertDataList::~ConvertDataList() |
| { |
| for( ConvertData* p = First() ; p ; p = Next() ) |
| delete p; |
| } |
| |
| |
| double ConvertDataList::Convert( double fVal, const STRING& rFrom, const STRING& rTo ) THROWDEF_RTE_IAE |
| { |
| // This will not catch illegal units |
| // if( rFrom == rTo ) |
| // return fVal; |
| |
| ConvertData* pFrom = NULL; |
| ConvertData* pTo = NULL; |
| sal_Bool bSearchFrom = sal_True; |
| sal_Bool bSearchTo = sal_True; |
| sal_Int16 nLevelFrom = 0; |
| sal_Int16 nLevelTo = 0; |
| |
| ConvertData* p = First(); |
| while( p && ( bSearchFrom || bSearchTo ) ) |
| { |
| if( bSearchFrom ) |
| { |
| sal_Int16 n = p->GetMatchingLevel( rFrom ); |
| if( n != INV_MATCHLEV ) |
| { |
| if( n ) |
| { // only first match for partial equality rulz a little bit more |
| pFrom = p; |
| nLevelFrom = n; |
| } |
| else |
| { // ... but exact match rulz most |
| pFrom = p; |
| bSearchFrom = sal_False; |
| nLevelFrom = n; |
| } |
| } |
| } |
| |
| if( bSearchTo ) |
| { |
| sal_Int16 n = p->GetMatchingLevel( rTo ); |
| if( n != INV_MATCHLEV ) |
| { |
| if( n ) |
| { // only first match for partial equality rulz a little bit more |
| pTo = p; |
| nLevelTo = n; |
| } |
| else |
| { // ... but exact match rulz most |
| pTo = p; |
| bSearchTo = sal_False; |
| nLevelTo = n; |
| } |
| } |
| } |
| |
| p = Next(); |
| } |
| |
| if( pFrom && pTo ) |
| return pFrom->Convert( fVal, *pTo, nLevelFrom, nLevelTo ); |
| else |
| THROW_IAE; |
| } |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| |
| ScaDate::ScaDate() : |
| nOrigDay( 1 ), |
| nDay( 1 ), |
| nMonth( 1 ), |
| nYear( 1900 ), |
| bLastDayMode( sal_True ), |
| bLastDay( sal_False ), |
| b30Days( sal_False ), |
| bUSMode( sal_False ) |
| { |
| } |
| |
| ScaDate::ScaDate( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nBase ) |
| { |
| DaysToDate( nNullDate + nDate, nOrigDay, nMonth, nYear ); |
| bLastDayMode = (nBase != 5); |
| bLastDay = (nOrigDay >= ::DaysInMonth( nMonth, nYear )); |
| b30Days = (nBase == 0) || (nBase == 4); |
| bUSMode = (nBase == 0); |
| setDay(); |
| } |
| |
| ScaDate::ScaDate( const ScaDate& rCopy ) : |
| nOrigDay( rCopy.nOrigDay ), |
| nDay( rCopy.nDay ), |
| nMonth( rCopy.nMonth ), |
| nYear( rCopy.nYear ), |
| bLastDayMode( rCopy.bLastDayMode ), |
| bLastDay( rCopy.bLastDay ), |
| b30Days( rCopy.b30Days ), |
| bUSMode( rCopy.bUSMode ) |
| { |
| } |
| |
| ScaDate& ScaDate::operator=( const ScaDate& rCopy ) |
| { |
| if( this != &rCopy ) |
| { |
| nOrigDay = rCopy.nOrigDay; |
| nDay = rCopy.nDay; |
| nMonth = rCopy.nMonth; |
| nYear = rCopy.nYear; |
| bLastDayMode = rCopy.bLastDayMode; |
| bLastDay = rCopy.bLastDay; |
| b30Days = rCopy.b30Days; |
| bUSMode = rCopy.bUSMode; |
| } |
| return *this; |
| } |
| |
| void ScaDate::setDay() |
| { |
| if( b30Days ) |
| { |
| // 30-days-mode: set nDay to 30 if original was last day in month |
| nDay = Min( nOrigDay, static_cast< sal_uInt16 >( 30 ) ); |
| if( bLastDay || (nDay >= ::DaysInMonth( nMonth, nYear )) ) |
| nDay = 30; |
| } |
| else |
| { |
| // set nDay to last day in this month if original was last day |
| sal_uInt16 nLastDay = ::DaysInMonth( nMonth, nYear ); |
| nDay = bLastDay ? nLastDay : Min( nOrigDay, nLastDay ); |
| } |
| } |
| |
| sal_Int32 ScaDate::getDaysInMonthRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const |
| { |
| if( nFrom > nTo ) |
| return 0; |
| |
| sal_Int32 nRet = 0; |
| if( b30Days ) |
| nRet = (nTo - nFrom + 1) * 30; |
| else |
| { |
| for( sal_uInt16 nMonthIx = nFrom; nMonthIx <= nTo; ++nMonthIx ) |
| nRet += getDaysInMonth( nMonthIx ); |
| } |
| return nRet; |
| } |
| |
| sal_Int32 ScaDate::getDaysInYearRange( sal_uInt16 nFrom, sal_uInt16 nTo ) const |
| { |
| if( nFrom > nTo ) |
| return 0; |
| |
| return b30Days ? ((nTo - nFrom + 1) * 360) : ::GetDaysInYears( nFrom, nTo ); |
| } |
| |
| void ScaDate::doAddYears( sal_Int32 nYearCount ) throw( lang::IllegalArgumentException ) |
| { |
| sal_Int32 nNewYear = nYearCount + nYear; |
| if( (nNewYear < 0) || (nNewYear > 0x7FFF) ) |
| throw lang::IllegalArgumentException(); |
| nYear = static_cast< sal_uInt16 >( nNewYear ); |
| } |
| |
| void ScaDate::addMonths( sal_Int32 nMonthCount ) throw( lang::IllegalArgumentException ) |
| { |
| sal_Int32 nNewMonth = nMonthCount + nMonth; |
| if( nNewMonth > 12 ) |
| { |
| --nNewMonth; |
| doAddYears( nNewMonth / 12 ); |
| nMonth = static_cast< sal_uInt16 >( nNewMonth % 12 ) + 1; |
| } |
| else if( nNewMonth < 1 ) |
| { |
| doAddYears( nNewMonth / 12 - 1 ); |
| nMonth = static_cast< sal_uInt16 >( nNewMonth % 12 + 12 ); |
| } |
| else |
| nMonth = static_cast< sal_uInt16 >( nNewMonth ); |
| setDay(); |
| } |
| |
| sal_Int32 ScaDate::getDate( sal_Int32 nNullDate ) const |
| { |
| sal_uInt16 nLastDay = ::DaysInMonth( nMonth, nYear ); |
| sal_uInt16 nRealDay = (bLastDayMode && bLastDay) ? nLastDay : Min( nLastDay, nOrigDay ); |
| return ::DateToDays( nRealDay, nMonth, nYear ) - nNullDate; |
| } |
| |
| sal_Int32 ScaDate::getDiff( const ScaDate& rFrom, const ScaDate& rTo ) throw( lang::IllegalArgumentException ) |
| { |
| if( rFrom > rTo ) |
| return getDiff( rTo, rFrom ); |
| |
| sal_Int32 nDiff = 0; |
| ScaDate aFrom( rFrom ); |
| ScaDate aTo( rTo ); |
| |
| if( rTo.b30Days ) |
| { |
| // corrections for base 0 (US NASD) |
| if( rTo.bUSMode ) |
| { |
| if( ((rFrom.nMonth == 2) || (rFrom.nDay < 30)) && (aTo.nOrigDay == 31) ) |
| aTo.nDay = 31; |
| else if( (aTo.nMonth == 2) && aTo.bLastDay ) |
| aTo.nDay = ::DaysInMonth( 2, aTo.nYear ); |
| } |
| // corrections for base 4 (Europe) |
| else |
| { |
| if( (aFrom.nMonth == 2) && (aFrom.nDay == 30) ) |
| aFrom.nDay = ::DaysInMonth( 2, aFrom.nYear ); |
| if( (aTo.nMonth == 2) && (aTo.nDay == 30) ) |
| aTo.nDay = ::DaysInMonth( 2, aTo.nYear ); |
| } |
| } |
| |
| if( (aFrom.nYear < aTo.nYear) || ((aFrom.nYear == aTo.nYear) && (aFrom.nMonth < aTo.nMonth)) ) |
| { |
| // move aFrom to 1st day of next month |
| nDiff = aFrom.getDaysInMonth() - aFrom.nDay + 1; |
| aFrom.nOrigDay = aFrom.nDay = 1; |
| aFrom.bLastDay = sal_False; |
| aFrom.addMonths( 1 ); |
| |
| if( aFrom.nYear < aTo.nYear ) |
| { |
| // move aFrom to 1st day of next year |
| nDiff += aFrom.getDaysInMonthRange( aFrom.nMonth, 12 ); |
| aFrom.addMonths( 13 - aFrom.nMonth ); |
| |
| // move aFrom to 1st day of this year |
| nDiff += aFrom.getDaysInYearRange( aFrom.nYear, aTo.nYear - 1 ); |
| aFrom.addYears( aTo.nYear - aFrom.nYear ); |
| } |
| |
| // move aFrom to 1st day of this month |
| nDiff += aFrom.getDaysInMonthRange( aFrom.nMonth, aTo.nMonth - 1 ); |
| aFrom.addMonths( aTo.nMonth - aFrom.nMonth ); |
| } |
| // finally add remaining days in this month |
| nDiff += aTo.nDay - aFrom.nDay; |
| return nDiff > 0 ? nDiff : 0; |
| } |
| |
| sal_Bool ScaDate::operator<( const ScaDate& rCmp ) const |
| { |
| if( nYear != rCmp.nYear ) |
| return nYear < rCmp.nYear; |
| if( nMonth != rCmp.nMonth ) |
| return nMonth < rCmp.nMonth; |
| if( nDay != rCmp.nDay ) |
| return nDay < rCmp.nDay; |
| if( bLastDay || rCmp.bLastDay ) |
| return !bLastDay && rCmp.bLastDay; |
| return nOrigDay < rCmp.nOrigDay; |
| } |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| |
| ScaAnyConverter::ScaAnyConverter( const uno::Reference< lang::XMultiServiceFactory >& xServiceFact ) : |
| bHasValidFormat( sal_False ) |
| { |
| if( xServiceFact.is() ) |
| { |
| uno::Reference< uno::XInterface > xInstance = xServiceFact->createInstance( |
| OUString::createFromAscii( "com.sun.star.util.NumberFormatter" ) ); |
| xFormatter = uno::Reference< util::XNumberFormatter >( xInstance, uno::UNO_QUERY ); |
| } |
| } |
| |
| ScaAnyConverter::~ScaAnyConverter() |
| { |
| } |
| |
| void ScaAnyConverter::init( const uno::Reference< beans::XPropertySet >& xPropSet ) throw( uno::RuntimeException ) |
| { |
| // try to get default number format |
| bHasValidFormat = sal_False; |
| if( xFormatter.is() ) |
| { |
| // get XFormatsSupplier from outer XPropertySet |
| uno::Reference< util::XNumberFormatsSupplier > xFormatsSupp( xPropSet, uno::UNO_QUERY ); |
| if( xFormatsSupp.is() ) |
| { |
| // get XNumberFormatTypes from XNumberFormatsSupplier to get standard index |
| uno::Reference< util::XNumberFormats > xFormats( xFormatsSupp->getNumberFormats() ); |
| uno::Reference< util::XNumberFormatTypes > xFormatTypes( xFormats, uno::UNO_QUERY ); |
| if( xFormatTypes.is() ) |
| { |
| lang::Locale eLocale; |
| nDefaultFormat = xFormatTypes->getStandardIndex( eLocale ); |
| xFormatter->attachNumberFormatsSupplier( xFormatsSupp ); |
| bHasValidFormat = sal_True; |
| } |
| } |
| } |
| } |
| |
| double ScaAnyConverter::convertToDouble( const OUString& rString ) const throw( lang::IllegalArgumentException ) |
| { |
| double fValue = 0.0; |
| if( bHasValidFormat ) |
| { |
| try |
| { |
| fValue = xFormatter->convertStringToNumber( nDefaultFormat, rString ); |
| } |
| catch( uno::Exception& ) |
| { |
| throw lang::IllegalArgumentException(); |
| } |
| } |
| else |
| { |
| rtl_math_ConversionStatus eStatus; |
| sal_Int32 nEnd; |
| fValue = ::rtl::math::stringToDouble( rString, '.', ',', &eStatus, &nEnd ); |
| if( (eStatus != rtl_math_ConversionStatus_Ok) || (nEnd < rString.getLength()) ) |
| throw lang::IllegalArgumentException(); |
| } |
| return fValue; |
| } |
| |
| sal_Bool ScaAnyConverter::getDouble( |
| double& rfResult, |
| const uno::Any& rAny ) const throw( lang::IllegalArgumentException ) |
| { |
| rfResult = 0.0; |
| sal_Bool bContainsVal = sal_True; |
| switch( rAny.getValueTypeClass() ) |
| { |
| case uno::TypeClass_VOID: |
| bContainsVal = sal_False; |
| break; |
| case uno::TypeClass_DOUBLE: |
| rAny >>= rfResult; |
| break; |
| case uno::TypeClass_STRING: |
| { |
| const OUString* pString = static_cast< const OUString* >( rAny.getValue() ); |
| if( pString->getLength() ) |
| rfResult = convertToDouble( *pString ); |
| else |
| bContainsVal = sal_False; |
| } |
| break; |
| default: |
| throw lang::IllegalArgumentException(); |
| } |
| return bContainsVal; |
| } |
| |
| sal_Bool ScaAnyConverter::getDouble( |
| double& rfResult, |
| const uno::Reference< beans::XPropertySet >& xPropSet, |
| const uno::Any& rAny ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| init( xPropSet ); |
| return getDouble( rfResult, rAny ); |
| } |
| |
| double ScaAnyConverter::getDouble( |
| const uno::Reference< beans::XPropertySet >& xPropSet, |
| const uno::Any& rAny, |
| double fDefault ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| double fResult; |
| if( !getDouble( fResult, xPropSet, rAny ) ) |
| fResult = fDefault; |
| return fResult; |
| } |
| |
| sal_Bool ScaAnyConverter::getInt32( |
| sal_Int32& rnResult, |
| const uno::Reference< beans::XPropertySet >& xPropSet, |
| const uno::Any& rAny ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| double fResult; |
| sal_Bool bContainsVal = getDouble( fResult, xPropSet, rAny ); |
| if( (fResult <= -2147483649.0) || (fResult >= 2147483648.0) ) |
| throw lang::IllegalArgumentException(); |
| |
| rnResult = static_cast< sal_Int32 >( fResult ); |
| return bContainsVal; |
| } |
| |
| sal_Int32 ScaAnyConverter::getInt32( |
| const uno::Reference< beans::XPropertySet >& xPropSet, |
| const uno::Any& rAny, |
| sal_Int32 nDefault ) throw( uno::RuntimeException, lang::IllegalArgumentException ) |
| { |
| sal_Int32 nResult; |
| if( !getInt32( nResult, xPropSet, rAny ) ) |
| nResult = nDefault; |
| return nResult; |
| } |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| |
| |