/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/XNumberFormatTypes.hpp>
#include <com/sun/star/util/NumberFormatter.hpp>
#include <string.h>
#include <stdio.h>
#include <o3tl/any.hxx>
#include <rtl/math.hxx>
#include <algorithm>
#include <cmath>
#include <memory>
#include "analysisdefs.hxx"
#include "analysishelper.hxx"
#include <analysis.hrc>
#include <strings.hrc>
#include "deffuncname.hxx"
using namespace ::com::sun::star;
using namespace sca::analysis;
#define UNIQUE false // function name does not exist in Calc
#define DOUBLE true // function name exists in Calc
#define STDPAR false // all parameters are described
#define INTPAR 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, nullptr }
#define FUNCDATAS( FUNCNAME, DBL, OPT, NUMOFPAR, CAT, SUFFIX ) \
{ "get" #FUNCNAME, ANALYSIS_FUNCNAME_##FUNCNAME, ANALYSIS_##FUNCNAME, DBL, OPT, ANALYSIS_DEFFUNCNAME_##FUNCNAME, NUMOFPAR, CAT, SUFFIX }
const FuncDataBase pFuncDatas[] =
{
// UNIQUE or INTPAR or
// function name DOUBLE STDPAR # of param category
FUNCDATA( Workday, UNIQUE, INTPAR, 3, FDCategory::DateTime ),
FUNCDATA( Yearfrac, UNIQUE, INTPAR, 3, FDCategory::DateTime ),
FUNCDATA( Edate, UNIQUE, INTPAR, 2, FDCategory::DateTime ),
FUNCDATAS( Weeknum, DOUBLE, INTPAR, 2, FDCategory::DateTime, "_EXCEL2003" ),
FUNCDATA( Eomonth, UNIQUE, INTPAR, 2, FDCategory::DateTime ),
FUNCDATAS( Networkdays, DOUBLE, INTPAR, 3, FDCategory::DateTime, "_EXCEL2003" ),
FUNCDATA( Iseven, DOUBLE, STDPAR, 1, FDCategory::Inf ),
FUNCDATA( Isodd, DOUBLE, STDPAR, 1, FDCategory::Inf ),
FUNCDATA( Multinomial, UNIQUE, STDPAR, 1, FDCategory::Math ),
FUNCDATA( Seriessum, UNIQUE, STDPAR, 4, FDCategory::Math ),
FUNCDATA( Quotient, UNIQUE, STDPAR, 2, FDCategory::Math ),
FUNCDATA( Mround, UNIQUE, STDPAR, 2, FDCategory::Math ),
FUNCDATA( Sqrtpi, UNIQUE, STDPAR, 1, FDCategory::Math ),
FUNCDATA( Randbetween, UNIQUE, STDPAR, 2, FDCategory::Math ),
FUNCDATAS( Gcd, DOUBLE, INTPAR, 1, FDCategory::Math, "_EXCEL2003" ),
FUNCDATAS( Lcm, DOUBLE, INTPAR, 1, FDCategory::Math, "_EXCEL2003" ),
FUNCDATA( Besseli, UNIQUE, STDPAR, 2, FDCategory::Tech ),
FUNCDATA( Besselj, UNIQUE, STDPAR, 2, FDCategory::Tech ),
FUNCDATA( Besselk, UNIQUE, STDPAR, 2, FDCategory::Tech ),
FUNCDATA( Bessely, UNIQUE, STDPAR, 2, FDCategory::Tech ),
FUNCDATA( Bin2Oct, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Bin2Dec, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Bin2Hex, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Oct2Bin, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Oct2Dec, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Oct2Hex, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Dec2Bin, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Dec2Hex, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Dec2Oct, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Hex2Bin, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Hex2Dec, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Hex2Oct, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Delta, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Erf, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Erfc, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Gestep, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Factdouble, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imabs, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imaginary, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Impower, UNIQUE, STDPAR, 2, FDCategory::Tech ),
FUNCDATA( Imargument, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imcos, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imdiv, UNIQUE, STDPAR, 2, FDCategory::Tech ),
FUNCDATA( Imexp, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imconjugate, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imln, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imlog10, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imlog2, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Improduct, UNIQUE, INTPAR, 2, FDCategory::Tech ),
FUNCDATA( Imreal, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imsin, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imsub, UNIQUE, STDPAR, 2, FDCategory::Tech ),
FUNCDATA( Imsqrt, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imsum, UNIQUE, INTPAR, 1, FDCategory::Tech ),
FUNCDATA( Imtan, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imsec, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imcsc, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imcot, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imsinh, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imcosh, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imsech, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Imcsch, UNIQUE, STDPAR, 1, FDCategory::Tech ),
FUNCDATA( Complex, UNIQUE, STDPAR, 3, FDCategory::Tech ),
FUNCDATA( Convert, UNIQUE, STDPAR, 3, FDCategory::Tech ),
FUNCDATA( Amordegrc, UNIQUE, INTPAR, 7, FDCategory::Finance ),
FUNCDATA( Amorlinc, UNIQUE, INTPAR, 7, FDCategory::Finance ),
FUNCDATA( Accrint, UNIQUE, INTPAR, 7, FDCategory::Finance ),
FUNCDATA( Accrintm, UNIQUE, INTPAR, 5, FDCategory::Finance ),
FUNCDATA( Received, UNIQUE, INTPAR, 5, FDCategory::Finance ),
FUNCDATA( Disc, UNIQUE, INTPAR, 5, FDCategory::Finance ),
FUNCDATA( Duration, UNIQUE, INTPAR, 6, FDCategory::Finance ),
FUNCDATA( Effect, DOUBLE, STDPAR, 2, FDCategory::Finance ),
FUNCDATA( Cumprinc, DOUBLE, STDPAR, 6, FDCategory::Finance ),
FUNCDATA( Cumipmt, DOUBLE, STDPAR, 6, FDCategory::Finance ),
FUNCDATA( Price, UNIQUE, INTPAR, 7, FDCategory::Finance ),
FUNCDATA( Pricedisc, UNIQUE, INTPAR, 5, FDCategory::Finance ),
FUNCDATA( Pricemat, UNIQUE, INTPAR, 6, FDCategory::Finance ),
FUNCDATA( Mduration, UNIQUE, INTPAR, 6, FDCategory::Finance ),
FUNCDATA( Nominal, DOUBLE, STDPAR, 2, FDCategory::Finance ),
FUNCDATA( Dollarfr, UNIQUE, STDPAR, 2, FDCategory::Finance ),
FUNCDATA( Dollarde, UNIQUE, STDPAR, 2, FDCategory::Finance ),
FUNCDATA( Yield, UNIQUE, INTPAR, 7, FDCategory::Finance ),
FUNCDATA( Yielddisc, UNIQUE, INTPAR, 5, FDCategory::Finance ),
FUNCDATA( Yieldmat, UNIQUE, INTPAR, 6, FDCategory::Finance ),
FUNCDATA( Tbilleq, UNIQUE, INTPAR, 3, FDCategory::Finance ),
FUNCDATA( Tbillprice, UNIQUE, INTPAR, 3, FDCategory::Finance ),
FUNCDATA( Tbillyield, UNIQUE, INTPAR, 3, FDCategory::Finance ),
FUNCDATA( Oddfprice, UNIQUE, INTPAR, 9, FDCategory::Finance ),
FUNCDATA( Oddfyield, UNIQUE, INTPAR, 9, FDCategory::Finance ),
FUNCDATA( Oddlprice, UNIQUE, INTPAR, 8, FDCategory::Finance ),
FUNCDATA( Oddlyield, UNIQUE, INTPAR, 8, FDCategory::Finance ),
FUNCDATA( Xirr, UNIQUE, INTPAR, 3, FDCategory::Finance ),
FUNCDATA( Xnpv, UNIQUE, STDPAR, 3, FDCategory::Finance ),
FUNCDATA( Intrate, UNIQUE, INTPAR, 5, FDCategory::Finance ),
FUNCDATA( Coupncd, UNIQUE, INTPAR, 4, FDCategory::Finance ),
FUNCDATA( Coupdays, UNIQUE, INTPAR, 4, FDCategory::Finance ),
FUNCDATA( Coupdaysnc, UNIQUE, INTPAR, 4, FDCategory::Finance ),
FUNCDATA( Coupdaybs, UNIQUE, INTPAR, 4, FDCategory::Finance ),
FUNCDATA( Couppcd, UNIQUE, INTPAR, 4, FDCategory::Finance ),
FUNCDATA( Coupnum, UNIQUE, INTPAR, 4, FDCategory::Finance ),
FUNCDATA( Fvschedule, UNIQUE, STDPAR, 2, FDCategory::Finance )
};
#undef FUNCDATA
namespace sca::analysis {
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 = (static_cast<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 )
{
if( nDays < 0 )
throw lang::IllegalArgumentException();
sal_Int32 nTempDays;
sal_Int32 i = 0;
bool bCalc;
do
{
nTempDays = nDays;
rYear = static_cast<sal_uInt16>((nTempDays / 365) - i);
nTempDays -= (static_cast<sal_Int32>(rYear) -1) * 365;
nTempDays -= (( rYear -1) / 4) - (( rYear -1) / 100) + ((rYear -1) / 400);
bCalc = false;
if ( nTempDays < 1 )
{
i++;
bCalc = true;
}
else
{
if ( nTempDays > 365 )
{
if ( (nTempDays != 366) || !IsLeapYear( rYear ) )
{
i--;
bCalc = true;
}
}
}
}
while ( bCalc );
rMonth = 1;
while ( nTempDays > DaysInMonth( rMonth, rYear ) )
{
nTempDays -= DaysInMonth( rMonth, rYear );
rMonth++;
}
rDay = static_cast<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( const uno::Reference< beans::XPropertySet >& xOpt )
{
if( xOpt.is() )
{
try
{
uno::Any aAny = xOpt->getPropertyValue( u"NullDate"_ustr );
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, bool bLeapYear1,
sal_uInt16 nDay2, sal_uInt16 nMonth2, sal_uInt16 nYear2,
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 )
{
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, 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;
}
sal_Int32 GetDiffDate( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode,
sal_Int32* pOptDaysIn1stYear )
{
bool bNeg = nStartDate > nEndDate;
if( bNeg )
std::swap( nStartDate, nEndDate );
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 );
bool bLeap = IsLeapYear( nY1 );
sal_Int32 nDays, nMonths;
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 lang::IllegalArgumentException();
}
return bNeg? -nRet : nRet;
}
double GetYearDiff( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode )
{
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 )
{
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 lang::IllegalArgumentException();
}
}
// tdf69569 making code compliant with change request for ODFF1.2 par 4.11.7.7
/**
* Function GetYearFrac implements YEARFRAC as defined in:
* Open Document Format for Office Applications version 1.2 Part 2, par. 6.10.24
* The calculations are defined in:
* Open Document Format for Office Applications version 1.2 Part 2, par. 4.11.7
*/
double GetYearFrac( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode )
{
if( nStartDate == nEndDate )
return 0.0; // nothing to do...
if( nStartDate > nEndDate )
std::swap( nStartDate, nEndDate );
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 );
// calculate days between nDate1 and nDate2
sal_Int32 nDayDiff;
switch( nMode )
{
case 0: // 0=USA (NASD) 30/360
if ( nDay1 == 31 )
{
nDay1--;
}
if ( nDay1 == 30 && nDay2 == 31 )
{
nDay2--;
}
else
{
if ( nMonth1 == 2 && nDay1 == ( IsLeapYear( nYear1 ) ? 29 : 28 ) )
{
nDay1 = 30;
if ( nMonth2 == 2 && nDay2 == ( IsLeapYear( nYear2 ) ? 29 : 28 ) )
{
nDay2 = 30;
}
}
}
nDayDiff = ( nYear2 - nYear1 ) * 360 + ( nMonth2 - nMonth1 ) * 30 + ( nDay2 - nDay1 );
break;
case 1: // 1=exact/exact
case 2: // 2=exact/360
case 3: // 3=exact/365
nDayDiff = nDate2 - nDate1;
break;
case 4: // 4=Europe 30/360
if ( nDay1 == 31 )
{
nDay1--;
}
if ( nDay2 == 31 )
{
nDay2--;
}
nDayDiff = ( nYear2 - nYear1 ) * 360 + ( nMonth2 - nMonth1 ) * 30 + ( nDay2 - nDay1 );
break;
default:
throw lang::IllegalArgumentException();
}
//calculate days in year
double nDaysInYear;
switch( nMode )
{
case 0: // 0=USA (NASD) 30/360
case 2: // 2=exact/360
case 4: // 4=Europe 30/360
nDaysInYear = 360;
break;
case 1: // 1=exact/exact
{
const bool isYearDifferent = ( nYear1 != nYear2 );
// ODFv1.2 part 2 section 4.11.7.7.7
if ( isYearDifferent &&
( ( nYear2 != nYear1 + 1 ) ||
( nMonth1 < nMonth2 ) ||
( nMonth1 == nMonth2 && nDay1 < nDay2 ) ) )
{
// return average of days in year between nDate1 and nDate2, inclusive
sal_Int32 nDayCount = 0;
for ( sal_uInt16 i = nYear1; i <= nYear2; i++ )
nDayCount += ( IsLeapYear( i ) ? 366 : 365 );
nDaysInYear = static_cast<double>(nDayCount) / static_cast<double>( nYear2 - nYear1 + 1 );
}
else
{
// as a consequence, !isYearDifferent or
// nYear2 == nYear + 1 and (nMonth1 > nMonth2 or
// (nMonth1 == nMonth2 and nDay1 >= nDay2))
assert( ( !isYearDifferent ||
( nYear1 + 1 == nYear2 &&
( nMonth1 > nMonth2 ||
( nMonth1 == nMonth2 || nDay1 >= nDay2 ) ) ) ) );
// ODFv1.2 part 2 section 4.11.7.7.8 (CHANGE REQUEST PENDING, see tdf6959)
if ( !isYearDifferent && IsLeapYear( nYear1 ) )
{
nDaysInYear = 366;
}
else
{
// ODFv1.2 part 2 section 4.11.7.7.9/10 (CHANGE REQUEST PENDING, see tdf69569)
// we need to determine whether there is a 29 February
// between nDate1 (inclusive) and nDate2 (inclusive)
// the case of nYear1 == nYear2 is adequately tested in previous test
if( isYearDifferent &&
( ( IsLeapYear( nYear1 ) &&
( ( nMonth1 < 2 ) || ( ( nMonth1 == 2 ) && ( nDay1 <= 29 ) ) ) ) ||
( IsLeapYear( nYear2 ) &&
( nMonth2 > 2 || ( ( nMonth2 == 2 ) && ( nDay2 == 29 ) ) ) ) ) )
{
nDaysInYear = 366;
}
else
{
nDaysInYear = 365;
}
}
}
}
break;
case 3: // 3=exact/365
nDaysInYear = 365;
break;
// coverity[dead_error_begin] - following conditions exist to avoid compiler warning
default:
throw lang::IllegalArgumentException();
}
return double( nDayDiff ) / nDaysInYear;
}
double BinomialCoefficient( double n, double k )
{
// This method is a copy of BinomKoeff()
// found in sc/source/core/tool/interpr3.cxx
double nVal = 0.0;
k = ::rtl::math::approxFloor(k);
if (n < k)
nVal = 0.0;
else if (k == 0.0)
nVal = 1.0;
else
{
nVal = n/k;
n--;
k--;
while (k > 0.0)
{
nVal *= n/k;
k--;
n--;
}
}
return nVal;
}
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 OUString& aStr, sal_uInt16 nBase, sal_uInt16 nCharLim )
{
if ( nBase < 2 || nBase > 36 )
throw lang::IllegalArgumentException();
sal_uInt32 nStrLen = aStr.getLength();
if( nStrLen > nCharLim )
throw lang::IllegalArgumentException();
else if( !nStrLen )
return 0.0;
double fVal = 0.0;
const sal_Unicode* p = aStr.getStr();
sal_uInt16 nFirstDig = 0;
bool bFirstDig = 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 )
throw lang::IllegalArgumentException(); // illegal char!
if( bFirstDig )
{
bFirstDig = false;
nFirstDig = n;
}
fVal = fVal * fBase + double( n );
p++;
}
if( nStrLen == nCharLim && !bFirstDig && (nFirstDig >= nBase / 2) )
{ // handling negative values
fVal = ( pow( double( nBase ), double( nCharLim ) ) - fVal ); // complement
fVal *= -1.0;
}
return fVal;
}
static char GetMaxChar( sal_uInt16 nBase )
{
const char* const c = "--123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return c[ nBase ];
}
OUString ConvertFromDec( double fNum, double fMin, double fMax, sal_uInt16 nBase,
sal_Int32 nPlaces, sal_Int32 nMaxPlaces, bool bUsePlaces )
{
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 lang::IllegalArgumentException();
sal_Int64 nNum = static_cast< sal_Int64 >( fNum );
bool bNeg = nNum < 0;
if( bNeg )
nNum = sal_Int64( pow( double( nBase ), double( nMaxPlaces ) ) ) + nNum;
OUString aRet(OUString::number(nNum, nBase).toAsciiUpperCase());
if( bUsePlaces )
{
sal_Int32 nLen = aRet.getLength();
if( !bNeg && nLen > nPlaces )
{
throw lang::IllegalArgumentException();
}
else if( ( bNeg && nLen < nMaxPlaces ) || ( !bNeg && nLen < nPlaces ) )
{
sal_Int32 nLeft = nPlaces - nLen;
std::unique_ptr<char[]> p( new char[ nLeft + 1 ] );
memset( p.get(), bNeg ? GetMaxChar( nBase ) : '0', nLeft );
p[ nLeft ] = 0x00;
aRet = OUString( p.get(), nLeft, RTL_TEXTENCODING_MS_1252 ) + aRet;
}
}
return aRet;
}
double Erf( double x )
{
return std::erf(x);
}
double Erfc( double x )
{
return std::erfc(x);
}
static bool IsNum( sal_Unicode c )
{
return c >= '0' && c <= '9';
}
static bool IsComma( sal_Unicode c )
{
return c == '.' || c == ',';
}
static bool IsExpStart( sal_Unicode c )
{
return c == 'e' || c == 'E';
}
static bool IsImagUnit( sal_Unicode c )
{
return c == 'i' || c == 'j';
}
static sal_uInt16 GetVal( sal_Unicode c )
{
return sal_uInt16( c - '0' );
}
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, S_Sign, S_IntStart, S_Int, S_IgnoreIntDigs, S_Frac, S_IgnoreFracDigs, S_ExpSign, S_Exp };
State eS = S_Sign;
bool bNegNum = false;
bool bNegExp = false;
const sal_Unicode* p = rp;
sal_Unicode c;
while( eS != S_End )
{
c = *p;
switch( eS )
{
case S_Sign:
if( IsNum( c ) )
{
fInt = GetVal( c );
nDigCnt--;
eS = S_Int;
}
else if( c == '-' )
{
bNegNum = true;
eS = S_IntStart;
}
else if( c == '+' )
eS = S_IntStart;
else if( IsComma( c ) )
eS = S_Frac;
else
return 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 true;
}
else
return 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 = 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 false;
}
else
eS = S_End;
break;
// coverity[dead_error_begin] - following conditions exist to avoid compiler warning
case S_End:
break;
}
p++;
}
p--; // set pointer back to last
rp = p;
fInt += fFrac;
if (fInt != 0.0) // exact check; log10(0.0) may entail a pole error
{
sal_Int32 nLog10 = sal_Int32( log10( fInt ) );
if( bNegExp )
nExp = -nExp;
if( nLog10 + nExp > nMaxExp )
return false;
fInt = ::rtl::math::pow10Exp( fInt, nExp );
}
if( bNegNum )
fInt = -fInt;
rRet = fInt;
return true;
}
OUString GetString( double f, bool bLeadingSign, sal_uInt16 nMaxDig )
{
const int nBuff = 256;
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 );
OUString 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 )
{
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 );
fCost -= fNRate;
double fRest = fCost - fRestVal; // aboriginal cost - residual value - sum of all write-downs
for( sal_uInt32 n = 0 ; n < nPer ; n++ )
{
fNRate = ::rtl::math::round( fRate * fCost );
fRest -= fNRate;
if( fRest < 0.0 )
{
switch( nPer - n )
{
case 0:
case 1:
return ::rtl::math::round( fCost * 0.5 );
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 )
{
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 );
double fResult = 0.0;
if( nPer == 0 )
fResult = f0Rate;
else if( nPer <= nNumOfFullPeriods )
fResult = fOneRate;
else if( nPer == nNumOfFullPeriods + 1 )
fResult = fCostDelta - fOneRate * nNumOfFullPeriods - f0Rate;
if ( fResult > 0.0 )
return fResult;
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 )
{
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 )
{
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*/ )
{
// If you change this to not unconditionally throw, the
// SAL_WNOUNREACHABLE_CODE_PUSH/POP around the caller in
// financial.cxx can be removed.
throw uno::RuntimeException();
}
double getYield_( sal_Int32 nNullDate, sal_Int32 nSettle, sal_Int32 nMat, double fCoup, double fPrice,
double fRedemp, sal_Int32 nFreq, sal_Int32 nBase )
{
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 && !rtl::math::approxEqual(fPriceN, fPrice) ; nIter++ )
{
fPriceN = getPrice_( nNullDate, nSettle, nMat, fRate, fYieldN, fRedemp, nFreq, nBase );
if( rtl::math::approxEqual(fPrice, fPrice1) )
return fYield1;
else if( rtl::math::approxEqual(fPrice, fPrice2) )
return fYield2;
else if( rtl::math::approxEqual(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 lang::IllegalArgumentException(); // 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 )
{
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*/ )
{
// If you change this to not unconditionally throw, the
// SAL_WNOUNREACHABLE_CODE_PUSH/POP around the caller in
// financial.cxx can be removed.
throw uno::RuntimeException();
}
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 )
{
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 )
{
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 GetPmt( double fRate, double fNper, double fPv, double fFv, sal_Int32 nPayType )
{
double fPmt;
if( fRate == 0.0 )
fPmt = ( fPv + fFv ) / fNper;
else
{
double fTerm = pow( 1.0 + fRate, fNper );
if( nPayType > 0 )
fPmt = ( fFv * fRate / ( fTerm - 1.0 ) + fPv * fRate / ( 1.0 - 1.0 / fTerm ) ) / ( 1.0 + fRate );
else
fPmt = fFv * fRate / ( fTerm - 1.0 ) + fPv * fRate / ( 1.0 - 1.0 / fTerm );
}
return -fPmt;
}
double GetFv( double fRate, double fNper, double fPmt, double fPv, sal_Int32 nPayType )
{
double fFv;
if( fRate == 0.0 )
fFv = fPv + fPmt * fNper;
else
{
double fTerm = pow( 1.0 + fRate, fNper );
if( nPayType > 0 )
fFv = fPv * fTerm + fPmt * ( 1.0 + fRate ) * ( fTerm - 1.0 ) / fRate;
else
fFv = fPv * fTerm + fPmt * ( fTerm - 1.0 ) / fRate;
}
return -fFv;
}
// financial functions COUP***
// COUPPCD: find last coupon date before settlement (can be equal to settlement)
/// @throws css::lang::IllegalArgumentException
static void lcl_GetCouppcd( ScaDate& rDate, const ScaDate& rSettle, const ScaDate& rMat, sal_Int32 nFreq )
{
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 )
{
if( nSettle >= nMat || isFreqInvalid(nFreq) )
throw lang::IllegalArgumentException();
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)
/// @throws css::lang::IllegalArgumentException
static void lcl_GetCoupncd( ScaDate& rDate, const ScaDate& rSettle, const ScaDate& rMat, sal_Int32 nFreq )
{
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 )
{
if( nSettle >= nMat || isFreqInvalid(nFreq) )
throw lang::IllegalArgumentException();
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 )
{
if( nSettle >= nMat || isFreqInvalid(nFreq) )
throw lang::IllegalArgumentException();
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 )
{
if( nSettle >= nMat || isFreqInvalid(nFreq) )
throw lang::IllegalArgumentException();
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 )
{
if( nSettle >= nMat || isFreqInvalid(nFreq) )
throw lang::IllegalArgumentException();
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 )
{
if( nSettle >= nMat || isFreqInvalid(nFreq) )
throw lang::IllegalArgumentException();
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 );
}
FuncData::FuncData(const FuncDataBase& r) :
aIntName( OUString::createFromAscii( r.pIntName ) ),
pUINameID( r.pUINameID ),
pDescrID( r.pDescrID ),
bDouble( r.bDouble ),
bWithOpt( r.bWithOpt ),
nParam( r.nNumOfParams ),
eCat( r.eCat )
{
if (r.pSuffix)
aSuffix = OUString::createFromAscii(r.pSuffix);
aCompList.resize(2);
aCompList[0] = OUString(r.pCompListID[0], strlen(r.pCompListID[0]), RTL_TEXTENCODING_UTF8);
aCompList[1] = OUString(r.pCompListID[1], strlen(r.pCompListID[1]), RTL_TEXTENCODING_UTF8);
}
sal_uInt16 FuncData::GetStrIndex( sal_uInt16 nParamNum ) const
{
if( !bWithOpt )
nParamNum++;
if( nParamNum > nParam )
return nParam * 2;
else
return nParamNum * 2;
}
void InitFuncDataList(FuncDataList& rList)
{
for(const auto & rFuncData : pFuncDatas)
rList.emplace_back(rFuncData);
}
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 )
{
maVector.insert( maVector.begin() + nIndex + 1, nDay );
return;
}
}
maVector.insert( maVector.begin(), nDay );
}
void SortedIndividualInt32List::Insert( sal_Int32 nDay, sal_Int32 nNullDate, bool bInsertOnWeekend )
{
if( !nDay )
return;
nDay += nNullDate;
if( bInsertOnWeekend || (GetDayOfWeek( nDay ) < 5) )
Insert( nDay );
}
void SortedIndividualInt32List::Insert(
double fDay, sal_Int32 nNullDate, bool bInsertOnWeekend )
{
if( (fDay < -2147483648.0) || (fDay > 2147483649.0) )
throw lang::IllegalArgumentException();
Insert( static_cast< sal_Int32 >( fDay ), nNullDate, bInsertOnWeekend );
}
bool SortedIndividualInt32List::Find( sal_Int32 nVal ) const
{
sal_uInt32 nE = Count();
if( !nE || nVal < Get( 0 ) || nVal > Get( nE - 1 ) )
return false;
// linear search
for( sal_uInt32 n = 0 ; n < nE ; n++ )
{
sal_Int32 nRef = Get( n );
if( nRef == nVal )
return true;
else if( nRef > nVal )
return false;
}
return false;
}
void SortedIndividualInt32List::InsertHolidayList(
const ScaAnyConverter& rAnyConv,
const uno::Any& rHolAny,
sal_Int32 nNullDate,
bool bInsertOnWeekend )
{
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 )
{
rAnyConv.init( xOptions );
if( rHolAny.getValueTypeClass() == uno::TypeClass_SEQUENCE )
{
uno::Sequence< uno::Sequence< uno::Any > > aAnySeq;
if( !(rHolAny >>= aAnySeq) )
throw lang::IllegalArgumentException();
for (const uno::Sequence<uno::Any>& rSubSeq : aAnySeq)
{
for( const uno::Any& rAny : rSubSeq )
InsertHolidayList( rAnyConv, rAny, nNullDate, false/*bInsertOnWeekend*/ );
}
}
else
InsertHolidayList( rAnyConv, rHolAny, nNullDate, false/*bInsertOnWeekend*/ );
}
void ScaDoubleList::Append(
const uno::Sequence< uno::Sequence< double > >& rValueSeq )
{
for( const uno::Sequence< double >& rSubSeq : rValueSeq )
{
for( const double fValue : rSubSeq )
Append( fValue );
}
}
void ScaDoubleList::Append(
const uno::Sequence< uno::Sequence< sal_Int32 > >& rValueSeq )
{
for( const uno::Sequence< sal_Int32 >& rSubSeq : rValueSeq )
{
for( const sal_Int32 nValue : rSubSeq )
Append( nValue );
}
}
void ScaDoubleList::Append(
const ScaAnyConverter& rAnyConv,
const uno::Any& rAny,
bool bIgnoreEmpty )
{
if( auto s = o3tl::tryAccess<
css::uno::Sequence<css::uno::Sequence<css::uno::Any>>>(rAny) )
Append( rAnyConv, *s, 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,
bool bIgnoreEmpty )
{
for( const uno::Any& rAny : rAnySeq )
Append( rAnyConv, rAny, bIgnoreEmpty );
}
void ScaDoubleList::Append(
const ScaAnyConverter& rAnyConv,
const uno::Sequence< uno::Sequence< uno::Any > >& rAnySeq,
bool bIgnoreEmpty )
{
for( const uno::Sequence< uno::Any >& rArray : rAnySeq )
Append( rAnyConv, rArray, bIgnoreEmpty );
}
void ScaDoubleList::Append(
ScaAnyConverter& rAnyConv,
const uno::Reference< beans::XPropertySet >& xOpt,
const uno::Sequence< uno::Any >& rAnySeq )
{
rAnyConv.init( xOpt );
Append( rAnyConv, rAnySeq, true/*bIgnoreEmpty*/ );
}
bool ScaDoubleList::CheckInsert( double ) const
{
return true;
}
bool ScaDoubleListGT0::CheckInsert( double fValue ) const
{
if( fValue < 0.0 )
throw lang::IllegalArgumentException();
return fValue > 0.0;
}
bool ScaDoubleListGE0::CheckInsert( double fValue ) const
{
if( fValue < 0.0 )
throw lang::IllegalArgumentException();
return true;
}
Complex::Complex( const OUString& rStr )
{
if( !ParseString( rStr, *this ) )
throw lang::IllegalArgumentException();
}
inline bool Complex::IsImagUnit( sal_Unicode c )
{
return c == 'i' || c == 'j';
}
bool Complex::ParseString( const OUString& 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.r = 0.0;
rCompl.i = 1.0;
rCompl.c = *pStr;
return true;
}
double f;
if( !ParseDouble( pStr, f ) )
return false;
switch( *pStr )
{
case '-': // imag part follows
case '+':
{
double r = f;
if( IsImagUnit( pStr[ 1 ] ) )
{
rCompl.c = pStr[ 1 ];
if( pStr[ 2 ] == 0 )
{
rCompl.r = f;
rCompl.i = ( *pStr == '+' )? 1.0 : -1.0;
return true;
}
}
else if( ParseDouble( pStr, f ) && IsImagUnit( *pStr ) )
{
rCompl.c = *pStr;
pStr++;
if( *pStr == 0 )
{
rCompl.r = r;
rCompl.i = f;
return true;
}
}
}
break;
case 'j':
case 'i':
rCompl.c = *pStr;
pStr++;
if( *pStr == 0 )
{
rCompl.i = f;
rCompl.r = 0.0;
return true;
}
break;
case 0: // only real-part
rCompl.r = f;
rCompl.i = 0.0;
return true;
}
return false;
}
OUString Complex::GetString() const
{
finiteOrThrow(r);
finiteOrThrow(i);
OUStringBuffer aRet;
bool bHasImag = i != 0.0;
bool bHasReal = !bHasImag || (r != 0.0);
if( bHasReal )
aRet.append(::GetString( r, false ));
if( bHasImag )
{
if( i == 1.0 )
{
if( bHasReal )
aRet.append('+');
}
else if( i == -1.0 )
aRet.append('-');
else
aRet.append(::GetString( i, bHasReal ));
aRet.append((c != 'j') ? 'i' : 'j');
}
return aRet.makeStringAndClear();
}
double Complex::Arg() const
{
if( r == 0.0 && i == 0.0 )
throw lang::IllegalArgumentException();
double phi = acos( r / Abs() );
if( i < 0.0 )
phi = -phi;
return phi;
}
void Complex::Power( double fPower )
{
if( r == 0.0 && i == 0.0 )
{
if( fPower <= 0 )
throw lang::IllegalArgumentException();
r = i = 0.0;
return;
}
double p, phi;
p = Abs();
phi = acos( r / p );
if( i < 0.0 )
phi = -phi;
p = pow( p, fPower );
phi *= fPower;
r = cos( phi ) * p;
i = sin( phi ) * p;
}
void Complex::Sqrt()
{
static const double fMultConst = M_SQRT1_2;
double p = Abs();
double i_ = sqrt( p - r ) * fMultConst;
r = sqrt( p + r ) * fMultConst;
i = ( i < 0.0 )? -i_ : i_;
}
void Complex::Sin()
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
if( i )
{
double r_;
r_ = sin( r ) * cosh( i );
i = cos( r ) * sinh( i );
r = r_;
}
else
r = sin( r );
}
void Complex::Cos()
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
if( i )
{
double r_;
r_ = cos( r ) * cosh( i );
i = -( sin( r ) * sinh( i ) );
r = r_;
}
else
r = cos( r );
}
void Complex::Div( const Complex& z )
{
if( z.r == 0 && z.i == 0 )
throw lang::IllegalArgumentException();
double a1 = r;
double a2 = z.r;
double b1 = i;
double b2 = z.i;
double f = 1.0 / ( a2 * a2 + b2 * b2 );
r = ( a1 * a2 + b1 * b2 ) * f;
i = ( a2 * b1 - a1 * b2 ) * f;
if( !c ) c = z.c;
}
void Complex::Exp()
{
double fE = exp( r );
r = fE * cos( i );
i = fE * sin( i );
}
void Complex::Ln()
{
if( r == 0.0 && i == 0.0 )
throw lang::IllegalArgumentException();
double fAbs = Abs();
bool bNegi = i < 0.0;
i = acos( r / fAbs );
if( bNegi )
i = -i;
r = log( fAbs );
}
void Complex::Log10()
{
Ln();
Mult( M_LOG10E );
}
void Complex::Log2()
{
Ln();
Mult( M_LOG2E );
}
void Complex::Tan()
{
if ( i )
{
if( !::rtl::math::isValidArcArg( 2.0 * r ) )
throw lang::IllegalArgumentException();
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 lang::IllegalArgumentException();
r = tan( r );
}
}
void Complex::Sec()
{
if( i )
{
if( !::rtl::math::isValidArcArg( 2 * r ) )
throw lang::IllegalArgumentException();
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 lang::IllegalArgumentException();
r = 1.0 / cos( r );
}
}
void Complex::Csc()
{
if( i )
{
if( !::rtl::math::isValidArcArg( 2 * r ) )
throw lang::IllegalArgumentException();
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 lang::IllegalArgumentException();
r = 1.0 / sin( r );
}
}
void Complex::Cot()
{
if ( i )
{
if( !::rtl::math::isValidArcArg( 2.0 * r ) )
throw lang::IllegalArgumentException();
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 lang::IllegalArgumentException();
r = 1.0 / tan( r );
}
}
void Complex::Sinh()
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
if( i )
{
double r_;
r_ = sinh( r ) * cos( i );
i = cosh( r ) * sin( i );
r = r_;
}
else
r = sinh( r );
}
void Complex::Cosh()
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
if( i )
{
double r_;
r_ = cosh( r ) * cos( i );
i = sinh( r ) * sin( i );
r = r_;
}
else
r = cosh( r );
}
void Complex::Sech()
{
if ( i )
{
if( !::rtl::math::isValidArcArg( 2.0 * r ) )
throw lang::IllegalArgumentException();
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 lang::IllegalArgumentException();
r = 1.0 / cosh( r );
}
}
void Complex::Csch()
{
if ( i )
{
if( !::rtl::math::isValidArcArg( 2.0 * r ) )
throw lang::IllegalArgumentException();
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 lang::IllegalArgumentException();
r = 1.0 / sinh( r );
}
}
ComplexList::~ComplexList()
{
}
void ComplexList::Append( const uno::Sequence< uno::Sequence< OUString > >& r )
{
for( const uno::Sequence< OUString >& rList : r )
{
for( const OUString& rStr : rList )
{
if( !rStr.isEmpty() )
Append( Complex( rStr ) );
}
}
}
void ComplexList::Append( const uno::Sequence< uno::Any >& aMultPars )
{
for( const uno::Any& r : aMultPars )
{
switch( r.getValueTypeClass() )
{
case uno::TypeClass_VOID: break;
case uno::TypeClass_STRING:
{
auto pStr = o3tl::forceAccess<OUString>(r);
if( !pStr->isEmpty() )
Append( Complex( *pStr ) );
}
break;
case uno::TypeClass_DOUBLE:
Append( Complex( *o3tl::forceAccess<double>(r), 0.0 ) );
break;
case uno::TypeClass_SEQUENCE:
{
uno::Sequence< uno::Sequence< uno::Any > > aValArr;
if( !(r >>= aValArr) )
throw lang::IllegalArgumentException();
for (const uno::Sequence<uno::Any>& rArr : aValArr)
Append( rArr );
}
break;
default:
throw lang::IllegalArgumentException();
}
}
}
ConvertData::ConvertData(const char p[], double fC, ConvertDataClass e, bool bPrefSupport)
: fConst(fC)
, aName(p, strlen(p), RTL_TEXTENCODING_MS_1252)
, eClass(e)
, bPrefixSupport(bPrefSupport)
{
}
ConvertData::~ConvertData()
{
}
sal_Int16 ConvertData::GetMatchingLevel( const OUString& rRef ) const
{
OUString aStr = rRef;
sal_Int32 nLen = rRef.getLength();
sal_Int32 nIndex = rRef.lastIndexOf( '^' );
if( nIndex > 0 && nIndex == ( nLen - 2 ) )
aStr = aStr.subView( 0, nLen - 2 ) + OUStringChar( aStr[ nLen - 1 ] );
if( aName == aStr )
return 0;
else
{
const sal_Unicode* p = aStr.getStr();
nLen = aStr.getLength();
bool bPref = bPrefixSupport;
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> "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
{
if( Class() != r.Class() )
throw lang::IllegalArgumentException();
bool bBinFromLev = ( nLevFrom > 0 && ( nLevFrom % 10 ) == 0 );
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::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
{
if( Class() != r.Class() )
throw lang::IllegalArgumentException();
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()
{
#define NEWD(str,unit,cl) maVector.emplace_back(new ConvertData(str,unit,cl))
#define NEWDP(str,unit,cl) maVector.emplace_back(new ConvertData(str,unit,cl,true))
#define NEWL(str,unit,offs,cl) maVector.emplace_back(new ConvertDataLinear(str,unit,offs,cl))
#define NEWLP(str,unit,offs,cl) maVector.emplace_back(new ConvertDataLinear(str,unit,offs,cl,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 ); // Angstrom
NEWD( "Pica", 2.8346456692913386E03, CDC_Length ); // Pica Point (1/72 Inch) 2834,6456692913385826771653543307
NEWD( "picapt", 2.8346456692913386E03, CDC_Length ); // Pica Point (1/72 Inch) 2834,6456692913385826771653543307
NEWD( "pica", 2.36220472441E02, CDC_Length ); // pica (1/6 Inch)
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 -> https://en.wikipedia.org/wiki/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
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
// 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.0288413621105798E02, CDC_Volume ); // US teaspoon 1/768 gallon
NEWD( "tbs", 6.7628045403685994E01, CDC_Volume ); // US tablespoon 1/256 gallon
NEWD( "oz", 3.3814022701842997E01, CDC_Volume ); // Ounce Liquid 1/128 gallon
NEWD( "cup", 4.2267528377303746E00, CDC_Volume ); // Cup 1/16 gallon
NEWD( "pt", 2.1133764188651873E00, CDC_Volume ); // US Pint 1/8 gallon
NEWD( "us_pt", 2.1133764188651873E00, CDC_Volume ); // US Pint also
NEWD( "uk_pt", 1.7597539863927023E00, CDC_Volume ); // UK Pint 1/8 imperial gallon
NEWD( "qt", 1.0566882094325937E00, CDC_Volume ); // Quart 1/4 gallon
NEWD( "gal", 2.6417205235814842E-01, CDC_Volume ); // Gallon 1/3.785411784
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 Angstrom
NEWD( "Pica3", 2.2776990435870636E07, CDC_Volume ); // *** Cubic Pica Point (1/72 inch)
NEWD( "picapt3", 2.2776990435870636E07, CDC_Volume ); // *** Cubic Pica Point (1/72 inch)
NEWD( "pica3", 1.31811287245E04, CDC_Volume ); // *** Cubic Pica (1/6 inch)
NEWD( "barrel", 6.2898107704321051E-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", 2.0000000000000000E02, CDC_Volume ); // *** Modern teaspoon
NEWD( "uk_gal", 2.1996924829908779E-01, CDC_Volume ); // U.K. / Imperial gallon 1/4.54609
NEWD( "uk_qt", 8.7987699319635115E-01, CDC_Volume ); // U.K. / Imperial quart 1/4 imperial gallon
// 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 Angstrom
NEWD( "Pica2", 8.0352160704321409E06, CDC_Area ); // *** Square Pica Point (1/72 inch)
NEWD( "picapt2", 8.0352160704321409E06, CDC_Area ); // *** Square Pica Point (1/72 inch)
NEWD( "pica2", 5.58001116002232E04, CDC_Area ); // *** Square Pica (1/6 inch)
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
// 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( "ludicrous speed", 2.0494886343432328E-14, 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()
{
}
double ConvertDataList::Convert( double fVal, const OUString& rFrom, const OUString& rTo )
{
ConvertData* pFrom = nullptr;
ConvertData* pTo = nullptr;
bool bSearchFrom = true;
bool bSearchTo = true;
sal_Int16 nLevelFrom = 0;
sal_Int16 nLevelTo = 0;
for( const auto& rItem : maVector )
{
ConvertData* p = rItem.get();
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 = 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 = false;
nLevelTo = n;
}
}
}
if( !bSearchFrom && !bSearchTo )
break;
}
if( !pFrom || !pTo )
throw lang::IllegalArgumentException();
return pFrom->Convert( fVal, *pTo, nLevelFrom, nLevelTo );
}
ScaDate::ScaDate() :
nOrigDay( 1 ),
nDay( 1 ),
nMonth( 1 ),
nYear( 1900 ),
bLastDayMode( true ),
bLastDay( false ),
b30Days( false ),
bUSMode( 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 = std::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 : std::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 )
{
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 )
{
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 : std::min( nLastDay, nOrigDay );
return ::DateToDays( nRealDay, nMonth, nYear ) - nNullDate;
}
sal_Int32 ScaDate::getDiff( const ScaDate& rFrom, const ScaDate& rTo )
{
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 = 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 std::max<sal_Int32>(nDiff, 0);
}
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< uno::XComponentContext >& xContext )
: nDefaultFormat(0)
, bHasValidFormat(false)
{
xFormatter = util::NumberFormatter::create(xContext);
}
ScaAnyConverter::~ScaAnyConverter()
{
}
void ScaAnyConverter::init( const uno::Reference< beans::XPropertySet >& xPropSet )
{
// try to get default number format
bHasValidFormat = false;
if( !xFormatter.is() )
return;
// get XFormatsSupplier from outer XPropertySet
uno::Reference< util::XNumberFormatsSupplier > xFormatsSupp( xPropSet, uno::UNO_QUERY );
if( !xFormatsSupp.is() )
return;
// 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 = true;
}
}
double ScaAnyConverter::convertToDouble( const OUString& rString ) const
{
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;
}
bool ScaAnyConverter::getDouble(
double& rfResult,
const uno::Any& rAny ) const
{
rfResult = 0.0;
bool bContainsVal = true;
switch( rAny.getValueTypeClass() )
{
case uno::TypeClass_VOID:
bContainsVal = false;
break;
case uno::TypeClass_STRING:
{
auto pString = o3tl::forceAccess< OUString >( rAny );
if( !pString->isEmpty() )
rfResult = convertToDouble( *pString );
else
bContainsVal = false;
}
break;
case uno::TypeClass_HYPER:
rfResult = rAny.get<sal_Int64>();
break;
case uno::TypeClass_UNSIGNED_HYPER:
rfResult = rAny.get<sal_uInt64>();
break;
default:
if( !( rAny >>= rfResult ) )
throw lang::IllegalArgumentException();
}
return bContainsVal;
}
bool ScaAnyConverter::getDouble(
double& rfResult,
const uno::Reference< beans::XPropertySet >& xPropSet,
const uno::Any& rAny )
{
init( xPropSet );
return getDouble( rfResult, rAny );
}
double ScaAnyConverter::getDouble(
const uno::Reference< beans::XPropertySet >& xPropSet,
const uno::Any& rAny,
double fDefault )
{
double fResult;
if( !getDouble( fResult, xPropSet, rAny ) )
fResult = fDefault;
return fResult;
}
bool ScaAnyConverter::getInt32(
sal_Int32& rnResult,
const uno::Reference< beans::XPropertySet >& xPropSet,
const uno::Any& rAny )
{
double fResult;
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 )
{
sal_Int32 nResult;
if( !getInt32( nResult, xPropSet, rAny ) )
nResult = nDefault;
return nResult;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V530 The return value of function 'append' is required to be utilized.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: r, i, c.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.
↑ V1023 A pointer without owner is added to the 'maVector' container by the 'emplace_back' method. A memory leak will occur in case of an exception.