diff -r c55016431358 -r 0a7b44b10206 symport/e32/euser/maths/um_rtod.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symport/e32/euser/maths/um_rtod.cpp Thu Jun 25 15:59:54 2009 +0100 @@ -0,0 +1,1073 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32\euser\maths\um_rtod.cpp +// +// + +#include "um_std.h" + +#include + +#define KNeedsRounding 0x1000 +#if (KRealFormatTypeFlagsMask| KRealFormatTypesMask) & KNeedsRounding + #error KNeedsRounding already uses 0x1000 +#endif + +const TInt KMinThreeDigitExponent=100; + +_LIT8(KLit8Plus,"+"); +_LIT8(KLit8Minus,"-"); +_LIT8(KLit8Zero,"0"); +_LIT8(KLit8Inf,"Inf"); +_LIT8(KLit8Nan,"NaN"); + +LOCAL_C TInt round(const TText8* aBuf, const TInt aLen) +// +// Round number in buffer depending on digit at aBuf[aLen]. +// Return value is carry from most significant digit. +// + { + __ASSERT_DEBUG(aLen>=0,Panic(EMathUnexpectedError1)); + TText8* pB=(TText8*)aBuf+aLen; + if (*pB<'5') + return 0; // round down + while(--pB>=aBuf) + { + TText8 d=*pB; + if (d<'9') + { + ++d; + *pB=d; + return 0; + } + *pB='0'; + } + // carry propagates to exponent + *++pB='1'; + if (aLen>0) + pB[aLen]='0'; + return 1; + } + +TUint mult10(TUint64& a) +// +// Multiply a 64-bit binary fraction in a (MSB=2^-1) by 10 +// Return the fractional part in a, the integer part in the return value. +// + { + const TUint64 ten = 10; + TUint64 high; + Math::UMul64(a, ten, high, a); + return static_cast(high); + } + +LOCAL_C TInt fDigLim(TDes8& aTrg, const TReal& aSrc, TInt& aExp, const TBool aLimit) +// +// Convert the TReal at address aSrc to a decimal form suitable for use by a +// formatting routine. Writes the result into the descriptor at aTrg and the +// exponent in aExp. Returns the length of the string or a negative error number. +// +// AnnW, November 1996 - changed to handle all numbers in TReal64/96 range. +// +// The first character in aBuf is one of: +// +// '0' - indicates that aSrc is exactly zero. +// +// '+' - indicates a positive number and is followed by between 1 and KMaxPrecision +// decimal digits representing a mantissa in the range 0.1 to less than 1.0 which +// corresponds to the decimal exponent returned in aExp. +// +// '-' - indicates a negative mantissa and is otherwise the same as for '+'. +// +// If aLimit is ETrue then the format is limited to KPrecisionLimit significant digits +// + { + + TRealX x; + TInt r=x.Set(aSrc); + + if (x.IsZero()) + { + aTrg=KLit8Zero(); + return 1; + } + else // sets sign in all cases, including specials + aTrg=(x.iSign ? KLit8Minus() : KLit8Plus()); + + if (r!=KErrNone) + return r; + + x.iSign=0; + TInt e=TInt(x.iExp)-0x7fff; // 2^e<=Abs(x)<2^(e+1) + e*=19728; // log10(2)*65536 = 19728.301796... + // max error due to omission of fractional part is 9889 (towards zero) + e-=9889; // account for error, e may be too small by up to 19778 + // Now have 10^(e/65536)<=Abs(x)<4.007*10^(e/65536) + e>>=16; // Divide by 65536 - this always rounds towards -infinity + // Now have 10^e<=Abs(x)<40.07*10^e + e+=1; // Now have 0.1<=Abs(x)/10^e<4.07 + Math::MultPow10X(x,-e); // x*=10^-e so now 0.1<=x<4.07 + if (x.iExp>=0x7fff) + { + ++e; + Math::MultPow10X(x,-1); // if x>=1, multiply x by 10^-1 and increment e + } + + TUint64 mantissa = MAKE_TUINT64(x.iMantHi, x.iMantLo); + + if (x.iExp<0x7ffe) + mantissa >>= (0x7ffe - x.iExp); // shift to make exponent 0x7ffe, i.e. mantissa in range 0.1<=m<1 + + TInt prec=aLimit?KPrecisionLimit:KMaxPrecision; + + while ( mantissa && (aTrg.Length() < (prec + 2)) ) + { + TUint d = mult10(mantissa); + aTrg.Append(d+'0'); + } + if (aTrg.Length()>=prec+2) + { + e+=round(aTrg.Ptr()+1,prec); + aTrg.SetLength(prec+1); + } + aExp=e; + return aTrg.Length(); + } + +LOCAL_C TInt doExponent(TDes8* This, TDes8& aDigBuf, const TInt afDigLimSize, TInt aExp, + const TInt aNumPlcs, const TInt aNumSpace, const TText aPoint, const TUint flags) +// +// Convert the intermediate number represented in aDigBuf into its exponential representation +// and place into aTrg. +// This representation ensures that numbers are displayed to aNumDecPlcs+1 significant figures, +// but this is NOT a constant value in KTRealFormatGeneral mode. +// +// AnnW, November 1996 - changed to be able to take three-figure exponents if allowed by flags. +// + { + + TInt err; + TInt expSpace; + TInt useSigFigs=flags & KUseSigFigs; + TInt nDig=(useSigFigs ? Min(aNumPlcs,afDigLimSize) : aNumPlcs+1); + TInt threeDigitExp=flags & KAllowThreeDigitExp; + + if ((flags & KNeedsRounding) && afDigLimSize>nDig) + aExp+=round(aDigBuf.Ptr()+1,nDig); + + if (useSigFigs) // discard trailing zeros + { + while(nDig>1 && aDigBuf[nDig]=='0') + { + nDig--; + } + } + + if (aDigBuf[0]!='0') + // 100.5 is stored in aDigBuf as +1005 with and exp of 3, but it is to be displayed + // as 1.005 so exp must be decremented to 2 + aExp--; + + // Added by AnnW + if (threeDigitExp) + { + expSpace=(Abs(aExp)>=KMinThreeDigitExponent)?5:4; + } + else + { + err=(aExp<=-KMinThreeDigitExponent ? KErrUnderflow : (aExp>=KMinThreeDigitExponent ? KErrOverflow : KErrNone)); + if (err!=KErrNone) + return(err); + expSpace=4; + } + + // Check that number will fit in aNumSpace + if (aNumSpace<(expSpace+nDig+(nDig>1?1:0))) + // exponent + significant figures + point(if necessary) + return(KErrGeneral); + // end of added + + if (aDigBuf[0]=='0') // number to be converted is 0 + { + This->Append('0'); + if (nDig>1 && !useSigFigs) + { + This->Append(aPoint); + This->AppendFill('0',aNumPlcs); + } + } + else + { + This->Append(TChar(aDigBuf[1])); + if (nDig>1) + { + This->Append(aPoint); + for (TInt ii=2; ii<=nDig; ii++) + { + if (!useSigFigs) + // pad with zeros + This->Append(TChar(iiAppend(TChar(aDigBuf[ii])); + } + } + } + + This->Append('E'); + if (aExp<0) + { + aExp=-aExp; + This->Append('-'); + } + else + This->Append('+'); + + // Added by AnnW + TInt tempExp; + if (threeDigitExp && aExp>99) + { + This->Append(aExp/100+'0'); + tempExp=aExp%100; + } + else + tempExp = aExp; + // end of added + + This->Append(tempExp/10+'0'); + This->Append(tempExp%10+'0'); + return(KErrNone); + } + +LOCAL_C TInt doFixed(TDes8 *This,TDes8 &aDigBuf,const TInt afDigLimSize,TInt aExp,const TInt aNumDecPlcs, + const TInt aNumSpace,const TRealFormat &aFormat,const TUint flags) +// +// Convert the intermediate number represented in aDigBuf into its fixed representation and +// place into aTrg +// +// AnnW, November 1996 - changed to allow extra space to be left for potential sign, so that +// positive and negative numbers of the same exponent are displayed to the same precision. +// + { + + TInt err; + TInt doNotUseTriads=flags & KDoNotUseTriads; + TInt newNumSpace=aNumSpace; + // To allow positive and negative numbers with the same exponent to have the same number of + // significant figures. + if ((flags & KExtraSpaceForSign) && (aDigBuf[0]!='-')) + newNumSpace--; + + TInt roundOffset = aNumDecPlcs+aExp; + if (roundOffset>=0 && afDigLimSize>roundOffset && (flags & KNeedsRounding)) + aExp+=round(aDigBuf.Ptr()+1,roundOffset); + + if (newNumSpace<((aExp>0?aExp:1)+(aNumDecPlcs?aNumDecPlcs+1:0)+(!doNotUseTriads && aFormat.iTriLen && (aExp>(TInt)aFormat.iTriLen)?(aExp-1)/3:0))) + // exponent +ve and space < space needed for (digits before point + point + decimal places + triads) + { + err=(aExp>0 ? KErrOverflow : KErrGeneral); + return(err); + } + + if (aExp<=0) // hence number is of the form 0.NNNN + { + This->Append('0'); + if (aNumDecPlcs) + { + aExp=-aExp; + TInt nDig=aNumDecPlcs-aExp; // number of digits required from aDigBuf + This->Append(aFormat.iPoint); + if (aExp>aNumDecPlcs) + aExp=aNumDecPlcs; + This->AppendFill('0',aExp); + if (nDig>0) + { + for (TInt ii=1; iiAppend(TChar(iiDelete(0,2); // delete -0 from This + This->Append('0'); + } + } + } + else // aExp > 0 hence number is of the form NNNN.NNNN + { + for (TInt jj=1,ii=aExp; ii; ii--,jj++) + { + if (!doNotUseTriads && aFormat.iTriLen && aExp>(TInt)aFormat.iTriLen && !(ii%3) && ii!=aExp) + This->Append(aFormat.iTriad); + This->Append(TChar(jj>=aDigBuf.Length() ? '0' : aDigBuf[jj])); + } + if (aNumDecPlcs>0) + { + This->Append(aFormat.iPoint); + for (TInt ii=aExp+1; iiAppend(TChar(ii(TInt)aFormat.iTriLen))?(aExp-1)/3:0; + TInt maxDig=Min(aMaxSigFigs,afDigLimSize); + TInt maxSpace=numSpace-(aExp<=0?(2-aExp):((aExpnDig && nDig<15 && nDig>=0 && (flags & KNeedsRounding) && round(aDigBuf.Ptr()+1,nDig)) + aExp++; + + if (aDigBuf[0]=='0') // do zero first (numSpace>=0 so OK) + This->Append('0'); + else + { + // check for overflow/underflow + if ((aExp+nTriadSeps)>numSpace) + return(KErrOverflow); + if (nDig<=0) + return(KErrUnderflow); + + if ((flags&(TUint)KRealFormatTypesMask)!=(TUint)KRealFormatCalculator && aExp>aMaxSigFigs) + return(KErrOverflow); + + TInt nDecPlcs=nDig-aExp; + while(nDecPlcs>0 && aDigBuf[nDig]=='0') + { // discard trailing zeros (already done in calculator) + nDecPlcs--; + nDig--; + } + + if (aExp<=0) // hence number is of the form 0.NNNN + { + This->Append('0'); + aExp=-aExp; + // if (nDecPlcs<=0) do nothing + if (nDecPlcs>0) + { + This->Append(aFormat.iPoint); + This->AppendFill('0',aExp); + for (TInt ii=1; ii<=nDig; ii++) + This->Append(TChar(aDigBuf[ii])); + } + } + else // aExp > 0 hence number is of the form NNNN.NNNN + { + for (TInt jj=1,ii=aExp; ii; ii--,jj++) + { + if (!doNotUseTriads && aFormat.iTriLen && aExp>(TInt)aFormat.iTriLen && !(ii%3) && ii!=aExp) + This->Append(aFormat.iTriad); + This->Append(TChar(jj<=nDig ? aDigBuf[jj] : '0')); + } + if (nDecPlcs>0) + { + This->Append(aFormat.iPoint); + for (TInt ii=aExp+1; ii<=nDig; ii++) + This->Append(TChar(aDigBuf[ii])); + } + } + } + + return(KErrNone); + } + +LOCAL_C TInt doGeneral(TDes8 *This,TReal aSrc,TDes8 &aDigBuf,const TInt afDigLimSize,TInt aExp, + TInt aNumDecPlcs,const TInt aNumSpace,const TRealFormat &aFormat,TUint flags) __SOFTFP +// +// Convert the intermediate number represented in aDigBuf into either its fixed representation or +// its exponential representation as appropriate and place the result in aTrg +// +// Annw, November 1996 - changed to allow space for sign in fixed mode, three-figure exponent. + { + + TBool rounded=((flags & KNeedsRounding)==0); + TInt nDig=aDigBuf.Length()-1; // no of digits without sign + TInt type; + + // Set up tempNumSpace to allow for leaving one space free for +ve nos in fixed format + TInt fixedNumSpace=aNumSpace; + if ((flags & KExtraSpaceForSign) && (aDigBuf[0]!='-')) + fixedNumSpace--; + if (fixedNumSpace<=0) + return(KErrGeneral); + + FOREVER + { + // If aNumSpace < 5 cannot use exponential format, i.e. not enough space for XE+NN. + // If the exponent >= -3 (i.e. aExp >= -2), it is always more (or equally) efficient + // to use non-exponential format for negative exponents, i.e. XE-03 takes same no of + // spaces as 0.00X, and for positive exponents use fixed form as far as possible. + + // for Java do not used fixed format for exponents >=7 + // expMax=Min(fixedNumSpace,7) + // and replace "fixednumSpace" with "expMax" in next line + + if (aNumSpace<5 || (aExp>=-2 && aExp<=fixedNumSpace)) + { + type=KRealFormatFixed; + + // if there is at least one digit before decimal point or no. is zero + if (aExp>0 || !aSrc) + { + if (nDig!=aExp) + // nDig is the number of digits which will be used + // a decimal point needed if exponent < digits in digbuf and numspace < nDig, + // so nDig is one less than otherwise + nDig=((nDig-aExp)>0 && fixedNumSpace>aExp)?Min(fixedNumSpace-1,nDig):Min(fixedNumSpace,nDig); + aNumDecPlcs=nDig-aExp; + } + else + { + // need space for "0." and to avoid white spaces + aNumDecPlcs=Min(fixedNumSpace-2,nDig-aExp); + // need space for "0.0...0" before any digits used + nDig=aNumDecPlcs+aExp; + if (nDig<0) + return KErrGeneral; + } + } + else + { + type=KRealFormatExponent; // Do NOT use significant figures + // Need to allow space for exponent + TInt tempNumSpace=aNumSpace-4; // 4 = E+NN + if ((flags & KAllowThreeDigitExp) && (Abs(aExp-1)>=100)) + tempNumSpace--; // 5 = E+NNN + // if more than one digit available and enough digits to fill space, need to reduce + // number of digits to allow for '.' + if (((nDig=Min(tempNumSpace,nDig))>1) && nDig==tempNumSpace) + nDig--; + // in any case, aNumDecPlcs is one less that the number of digits, + // i.e. one digit before the point + aNumDecPlcs=nDig-1; + } + // if too many digbuf chars to fit then we need to round + // round() returns 1 if had to carry from msdigit + if ((afDigLimSize>nDig && !rounded) && ((rounded=round(aDigBuf.Ptr()+1,nDig))!=0)) + aExp++; + else + break; + } + while(aNumDecPlcs>0 && aDigBuf[nDig]=='0') + { // discard trailing zeros + aNumDecPlcs--; + nDig--; + } + flags=flags & ~KNeedsRounding; + + if (type==KRealFormatExponent) + return(doExponent(This,aDigBuf,afDigLimSize,aExp,aNumDecPlcs,aNumSpace,(TText)aFormat.iPoint,flags)); + return(doFixed(This,aDigBuf,afDigLimSize,aExp,aNumDecPlcs,aNumSpace,aFormat,flags)); + } + + LOCAL_C TInt doCalculator(TDes8 *This,TDes8 &aDigBuf,const TInt afDigLimSize,TInt aExp, + TInt aMaxSigFigs,const TInt aMaxSpace,const TRealFormat &aFormat, TUint flags) +// +// Added by AnnW, November 1996 +// Convert the intermediate number represented in aDigBuf into either its no exponent or its +// exponential representation with a fixed number of significant figures and place the result +// in aTrg +// + { + + TBool threeDigExp=((flags & KAllowThreeDigitExp)!=0); + + // first check that enough space has been allowed for all the possible characters + // point + sign + all sig figs + exponent + if (aMaxSpace<(2+aMaxSigFigs+(threeDigExp?5:4))) + return(KErrGeneral); + + // now discard trailing zeros + TInt nDig=afDigLimSize; + while(nDig>1 && aDigBuf[nDig]=='0') + { + nDig--; + } + + TInt maxDig=Min(aMaxSigFigs,nDig); // max digs available + TBool rounded=((flags & KNeedsRounding)==0); + TInt type; + TBool useNoExp; + + FOREVER + { + useNoExp=ETrue; + nDig=maxDig; + + // use no exponent for all numbers which will not use > aMaxSigFigs digits + if (aExp>aMaxSigFigs || (aExp<=0 && (1-aExp+nDig)>aMaxSigFigs)) + useNoExp=EFalse; + + if (useNoExp) + type=KRealFormatNoExponent; + else + { + type=KRealFormatExponent; + threeDigExp=((Abs(aExp-1)>=KMinThreeDigitExponent && threeDigExp)!=0); + TInt temp=aMaxSpace-(threeDigExp?5:4); + nDig=Min(maxDig,temp-((temp>1 && maxDig>1)?1:0)); + } + + // if too many digbuf chars to fit then we need to round + // round() returns 1 if had to carry from msdigit + if ((afDigLimSize>nDig && !rounded) && ((rounded=round(aDigBuf.Ptr()+1,nDig))!=0)) + { + aExp++; + maxDig=1; + } + else + break; + } + + TInt numSpace=aMaxSpace-(aDigBuf[0]=='-'?1:0); + flags=flags & ~KNeedsRounding; + + if (type==KRealFormatExponent) + return(doExponent(This,aDigBuf,afDigLimSize,aExp,nDig,numSpace,(TText)aFormat.iPoint,flags)); + else + { + flags|=KExtraSpaceForSign; + return(doNoExponent(This,aDigBuf,afDigLimSize,aExp,nDig,numSpace,aFormat,flags)); + } + } + +TInt ProcessErrors(TDes8* aDes, TInt anError) + { + if (anError==KErrNone) + return aDes->Length(); + if (anError==KErrUnderflow) + aDes->Append(TChar('0')); + if (anError==KErrOverflow) + aDes->Append(KLit8Inf()); + if (anError==KErrArgument) + aDes->Append(KLit8Nan()); + return anError; + } + +LOCAL_C TInt rtob(TDes8 *This,TReal aVal,const TRealFormat &aFormat) __SOFTFP +// +// Converts the real at aSrc. Returns the length of the converted string or an error number +// if the buffer is too small, the number is out of range or there is insufficient KMaxPrecision +// to represent the number. +// +// The conversion format is interpreted as follows: +// KRealFormatFixed - ndec decimal places (including zero), negative values with a leading minus +// sign, triad separators are available and a space may be left in front of positive numbers to +// allow negative positve numbers to be given to the same precision. +// KRealFormatExponent - exponent notation specifying either decimal places or significant +// figures in the mantissa and a signed exponent given to a maximum of two or three digits, +// and no triad separator. +// KTRealFormatGeneral - converts either as fixed or exponent to make best use of the available +// width. The number of decimal spaces is chosen automatically as a function of width +// (ndec is ignored), no triad. +// KRealFormatNoExponent - as KRealForamtFixed, but specifying maximum significant figures and +// not introducing trailing zeros. +// KRealFormatCalculator - as KRealFormatGeneral, but behaves as a conventional calculator. A +// maximum number of significant figures is specified and the number is displayed without an +// exponent whenever possible, with no trailing zeros and no triads. +// +// If an error value other than KErrGeneral is returned the real is converted to some string: +// "+/-Inf" if the error is KErrOverflow, "NaN" if the error is KErrArgument or "0" if it is +// KErrUnderflow. +// + { + if (aFormat.iWidth>This->MaxLength()) + return(KErrGeneral); + TBuf8<0x20> digbuf; + TInt exp=0; + TInt numspace=aFormat.iWidth; + TInt maxspace=numspace; + TInt ret=fDigLim(digbuf,aVal,exp,((aFormat.iType & KGeneralLimit)!=0)); + digbuf.ZeroTerminate(); + TInt type, flags; + + if (digbuf[0]=='0') + exp=0; + else + { + if (digbuf[0]=='-' && ret!=KErrArgument) // NaN has no sign + { + This->Append('-'); + numspace--; + } + if (ret<0) + return ProcessErrors(This, ret); + else + ret--; + } + + //Added by AnnW + if (numspace<=0) + return(KErrGeneral); + if (aFormat.iType & ~KRealFormatTypesMask & ~KRealFormatTypeFlagsMask) + return(KErrGeneral); + type=aFormat.iType & KRealFormatTypesMask; + flags=((aFormat.iType & KRealFormatTypeFlagsMask)| KNeedsRounding); + // end of added + + switch(type) + { + case KRealFormatFixed: + flags=flags & ~KUseSigFigs; // if flag is NOT set and iTriLen!=0, uses triads + ret=doFixed(This,digbuf,ret,exp,aFormat.iPlaces,numspace,aFormat,flags); + break; + case KRealFormatExponent: + ret=doExponent(This,digbuf,ret,exp,aFormat.iPlaces,numspace,(TText)aFormat.iPoint,flags); + break; + case KRealFormatGeneral: + flags=(flags & ~KUseSigFigs) | KDoNotUseTriads; + ret=doGeneral(This,aVal,digbuf,ret,exp,aFormat.iPlaces,numspace,aFormat,flags); + break; + case KRealFormatNoExponent: + flags=flags | KUseSigFigs; // if flag is NOT set and iTriLen!=0, uses triads + ret=doNoExponent(This,digbuf,ret,exp,aFormat.iPlaces,numspace,aFormat,flags); + break; + case KRealFormatCalculator: + flags=(flags | KUseSigFigs) | KDoNotUseTriads | KRealFormatCalculator; + ret=doCalculator(This,digbuf,ret,exp,aFormat.iPlaces,maxspace,aFormat,flags); + break; + default: + return(KErrGeneral); + } + return ProcessErrors(This, ret); + } + + + + +EXPORT_C TRealFormat::TRealFormat() +/** +Default constructor. + +The public data members of the constructed object are assigned +the following values: + +TRealFormat::iType - set to KRealFormatGeneral + +TRealFormat::iWidth - set to KDefaultRealWidth + +TRealFormat::iPlaces - set to 0 + +TRealFormat::iPoint - set to the decimal separator character defined in + a TLocale object and returned by the DecimalSeparator() + member function of that class. + +TRealFormat::iTriad - set to the character used to delimit groups of three + digits in the integer portion of a number; the character + is defined in a TLocale object and returned by the + ThousandsSeparator() member function of that class. + +TRealFormat::iTriLen - set to 1 + +@see TLocale::DecimalSeparator +@see TLocale::ThousandsSeparator +*/ + { + + iType=KRealFormatGeneral; + iWidth=KDefaultRealWidth; + iPlaces=0; + TLocale locale; + iPoint=locale.DecimalSeparator(); + iTriad=locale.ThousandsSeparator(); + iTriLen=1; + } + + + + +EXPORT_C TRealFormat::TRealFormat(TInt aWidth) +/** +Constructs the object taking the width of the character representation. + +The remaining public data members of the constructed object are assigned +the following values: + +TRealFormat::iType - set to KRealFormatGeneral + +TRealFormat::iWidth - set to the aWidth argument + +TRealFormat::iPlaces - set to 0 + +TRealFormat::iPoint - set to the decimal separator character defined in + a TLocale object and returned by the DecimalSeparator() + member function of that class. + +TRealFormat::iTriad - set to the character used to delimit groups of three + digits in the integer portion of a number; the character + is defined in a TLocale object and returned by the + ThousandsSeparator() member function of that class. + +TRealFormat::iTriLen - set to 1 + +@param aWidth The width of the character representation of the real number. + +@see TLocale::DecimalSeparator +@see TLocale::ThousandsSeparator +*/ + { + + iType=KRealFormatGeneral; + iWidth=aWidth; + iPlaces=0; + TLocale locale; + iPoint=locale.DecimalSeparator(); + iTriad=locale.ThousandsSeparator(); + iTriLen=1; + } + + + + +EXPORT_C TRealFormat::TRealFormat(TInt aWidth,TInt aDecimals) +/** +Constructs the object taking the width of the character representation +and a value which is interpreted as the number of digits to follow +the decimal point. + +The remaining public data members of the constructed object are assigned +the following values: + +TRealFormat::iType - set to KRealFormatFixed + +TRealFormat::iWidth - set to the aWidth argument + +TRealFormat::iPlaces - set to the aDecimals argument + +TRealFormat::iPoint - set to the decimal separator character defined in + a TLocale object and returned by the DecimalSeparator() + member function of that class. + +TRealFormat::iTriad - set to the character used to delimit groups of three + digits in the integer portion of a number; the character + is defined in a TLocale object and returned by the + ThousandsSeparator() member function of that class. + +TRealFormat::iTriLen - set to 1 + +Note that if the iType data member is changed after construction, aDecimalPlaces +may be interpreted as the number of significant digits. For more information, +see KRealFormatFixed and the other format types, and KExtraSpaceForSign and the +other format flags. + +@param aWidth The width of the character representation of the real number. +@param aDecimals The number of digits to follow the decimal point. + +@see TLocale::DecimalSeparator() +@see TLocale::ThousandsSeparator() +@see KRealFormatFixed +@see KExtraSpaceForSign +*/ + { + + iType=KRealFormatFixed; + iWidth=aWidth; + iPlaces=aDecimals; + TLocale locale; + iPoint=locale.DecimalSeparator(); + iTriad=locale.ThousandsSeparator(); + iTriLen=1; + } + + + + +EXPORT_C TInt Math::Round(TReal &aTrg,const TReal &aSrc,TInt aDecimalPlaces) +/** +Rounds to a specified number of decimal places. + +The function rounds a number to a given number, n, of decimal places. +Rounding may be thought of as multiplying the number by 10 to the power of n, +rounding to the nearest integer, and then dividing the result by 10 to +the power of n and returning that as the answer. + +In the process of rounding, numbers ending with .5 are rounded away from zero, +so that 1.5 becomes 2, 2.5 becomes 3, -1.5 becomes -2, etc. + +@param aTrg A reference containing the result. +@param aSrc The number to be rounded. +@param aDecimalPlaces The number of decimal places to round to: must be + zero or positive. + +@return KErrNone if successful, otherwise another of the system-wide error codes. +*/ + { + + if (aSrc==0.0) + { + aTrg=aSrc; + return(KErrNone); + } + TInt ret,exp; + TBuf8<0x20> rbuf; + if ((ret=fDigLim(rbuf,aSrc,exp,EFalse))<0) + return(ret); + if ((exp+aDecimalPlaces)<0) + { // Number too small to be rounded + aTrg=0; + return(KErrNone); + } + if ((ret-2)<(exp+aDecimalPlaces)) //ret is the string length, including prefixed +/- + { // Rounding will have no effect + aTrg=aSrc; + return(KErrNone); + } + if ((ret=round(rbuf.Ptr()+1,exp+aDecimalPlaces))!=KErrNone) + exp++; + rbuf.Insert(1,TPtrC8((TText8*)".",1)); + rbuf.SetLength(exp+aDecimalPlaces+2); + if (!(exp+aDecimalPlaces)) + rbuf.Append('0'); +// rbuf.AppendFormat(TPtrC8((TText8*)"%c%d",4),'E',exp); + rbuf.Append(TChar('E')); + rbuf.AppendNum(exp); + return(((TLex8)rbuf).Val(aTrg,(TChar)'.')); + } + +EXPORT_C TInt TDes8::Num(TReal aVal,const TRealFormat &aFormat) __SOFTFP +/** +Converts the specified floating point number into a character representation +and copies the conversion into this descriptor, replacing any existing data. + +The length of this descriptor is set to reflect the new data. + +The character representation of the real number is dictated by the specified +format. + +Note that the function leaves if the iType data member of the specified +TRealFormat object has both an invalid character representation format +(i.e. the format type) and invalid format flags. + +@param aVal The floating point number to be converted. +@param aFormat The format of the conversion. + +@return If the conversion is successful, the length of this descriptor. If + the conversion fails, a negative value indicating the cause of failure. + In addition, extra information on the cause of the failure may be + appended onto this descriptor. The possible values and their meaning + are: + + 1.KErrArgument - the supplied floating point number is not a valid + number. The three characters NaN are appended to this descriptor. + + 2.KErrOverflow - the number is too large to represent. + 2.1 For positive overflow, the three characters Inf are appended + to this descriptor. + 2.2 For negative overflow, the four characters -Inf are appended + to this descriptor. + + 3.KErrUnderflow - the number is too small to represent. + 3.1 For positive underflow, the three characters Inf are appended + to this descriptor. + 3.2 For negative underflow, the four characters -Inf are appended + to this descriptor. + + 4.KErrGeneral - the conversion cannot be completed. There are a + number of possible reasons for this, but the two most common + are: + 4.1 the maximum number of characters necessary to represent the number, + as defined in the TRealFormat object, is greater than the maximum + length of this descriptor + 4.2 the character representation format (i.e. the format type), as + defined in the TRealFormat object is not recognised. + +@see TRealFormat::iType +*/ + { + + Zero(); + return(rtob(this,aVal,aFormat)); + } + +EXPORT_C TInt TDes8::AppendNum(TReal aVal,const TRealFormat &aFormat) __SOFTFP +/** +Converts the specified floating point number into a character representation +and appends the conversion onto the end of this descriptor's data. + +The length of this descriptor is incremented to reflect the new content. + +The character representation of the real number is dictated by the specified +format. + +@param aVal The floating point number to be converted. +@param aFormat The format of the conversion. + +@return If the conversion is successful, the length of this descriptor. If + the conversion fails, a negative value indicating the cause of failure. + In addition, extra information on the cause of the failure may be + appended onto this descriptor. The possible values and their meaning + are: + + 1.KErrArgument - the supplied floating point number is not a valid + number. The three characters NaN are appended to this descriptor. + + 2.KErrOverflow - the number is too large to represent. + 2.1 For positive overflow, the three characters Inf are appended + to this descriptor. + 2.2 For negative overflow, the four characters -Inf are appended + to this descriptor. + + 3.KErrUnderflow - the number is too small to represent. + 3.1 For positive underflow, the three characters Inf are appended + to this descriptor. + 3.2 For negative underflow, the four characters -Inf are appended + to this descriptor. + + 4.KErrGeneral - the conversion cannot be completed. There are a + number of possible reasons for this, but the two most common + are: + 4.1 the maximum number of characters necessary to represent the number, + as defined in the TRealFormat object, is greater than the maximum + length of this descriptor + 4.2 the character representation format (i.e. the format type), as + defined in the TRealFormat object is not recognised +*/ + { + + return(rtob(this,aVal,aFormat)); + } + +EXPORT_C TInt TDes16::Num(TReal aVal,const TRealFormat &aFormat) __SOFTFP +/** +Converts the specified floating point number into a character representation +and copies the conversion into this descriptor, replacing any existing data. + +The length of this descriptor is set to reflect the new data. + +The character representation of the real number is dictated by the specified +format. + +Note that the function leaves if the iType data member of the specified +TRealFormat object has both an invalid character representation format +(i.e. the format type) and invalid format flags. + +@param aVal The floating point number to be converted. +@param aFormat The format of the conversion. + +@return If the conversion is successful, the length of this descriptor. If + the conversion fails, a negative value indicating the cause of failure. + In addition, extra information on the cause of the failure may be + appended onto this descriptor. The possible values and their meaning + are: + + 1.KErrArgument - the supplied floating point number is not a valid + number. The three characters NaN are appended to this descriptor. + + 2.KErrOverflow - the number is too large to represent. + 2.1 For positive overflow, the three characters Inf are appended + to this descriptor. + 2.2 For negative overflow, the four characters -Inf are appended + to this descriptor. + + 3.KErrUnderflow - the number is too small to represent. + 3.1 For positive underflow, the three characters Inf are appended + to this descriptor. + 3.2 For negative underflow, the four characters -Inf are appended + to this descriptor. + + 4.KErrGeneral - the conversion cannot be completed. There are a + number of possible reasons for this, but the two most common + are: + 4.1 the maximum number of characters necessary to represent the number, + as defined in the TRealFormat object, is greater than the maximum + length of this descriptor + 4.2 the character representation format (i.e. the format type), as + defined in the TRealFormat object is not recognised. + +@see TRealFormat::iType +*/ + { + + Zero(); + return (AppendNum(aVal,aFormat)); + } + +EXPORT_C TInt TDes16::AppendNum(TReal aVal,const TRealFormat &aFormat) __SOFTFP +/** +Converts the specified floating point number into a character representation +and appends the conversion onto the end of this descriptor's data. + +The length of this descriptor is incremented to reflect the new content. + +The character representation of the real number is dictated by the specified +format. + +@param aVal The floating point number to be converted. +@param aFormat The format of the conversion. + +@return If the conversion is successful, the length of this descriptor. If + the conversion fails, a negative value indicating the cause of failure. + In addition, extra information on the cause of the failure may be + appended onto this descriptor. The possible values and their meaning + are: + + 1.KErrArgument - the supplied floating point number is not a valid + number. The three characters NaN are appended to this descriptor. + + 2.KErrOverflow - the number is too large to represent. + 2.1 For positive overflow, the three characters Inf are appended + to this descriptor. + 2.2 For negative overflow, the four characters -Inf are appended + to this descriptor. + + 3.KErrUnderflow - the number is too small to represent. + 3.1 For positive underflow, the three characters Inf are appended + to this descriptor. + 3.2 For negative underflow, the four characters -Inf are appended + to this descriptor. + + 4.KErrGeneral - the conversion cannot be completed. There are a + number of possible reasons for this, but the two most common + are: + 4.1 the maximum number of characters necessary to represent the number, + as defined in the TRealFormat object, is greater than the maximum + length of this descriptor + 4.2 the character representation format (i.e. the format type), as + defined in the TRealFormat object is not recognised +*/ + { + + HBufC8 *temp=HBufC8::New(MaxLength()); + if (temp==NULL) + return(KErrNoMemory); + TPtr8 p(temp->Des()); + TInt ret=rtob(&p,aVal,aFormat); + const TText8 *pTemp=temp->Ptr(); + for (TInt ii=temp->Length();ii>0;ii--) + Append(*pTemp++); + if (ret>0) + ret=Length(); + User::Free(temp); + return (ret); + }