1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/math/t_roundtrip.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,296 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\math\t_roundtrip.cpp
1.18 +// Tests round-trip convertibility of double->string->double
1.19 +//
1.20 +//
1.21 +
1.22 +#define __E32TEST_EXTENSION__
1.23 +#include <e32test.h>
1.24 +#include <e32math.h>
1.25 +
1.26 +//#define __ALWAYS_PRINT__
1.27 +
1.28 +RTest test(_L("T_ROUNDTRIP"));
1.29 +
1.30 +void PrintRealHex(const char* aTitle, const TReal& aIn)
1.31 + {
1.32 + volatile TUint32* in = (volatile TUint32*)&aIn;
1.33 +#ifdef __DOUBLE_WORDS_SWAPPED__
1.34 + TUint32 high = in[0];
1.35 + TUint32 low = in[1];
1.36 +#else
1.37 + TUint32 high = in[1];
1.38 + TUint32 low = in[0];
1.39 +#endif
1.40 + TBuf<256> title;
1.41 + if (aTitle)
1.42 + title.Copy(TPtrC8((const TUint8*)aTitle));
1.43 + test.Printf(_L("%S%08x %08x\n"), &title, high, low);
1.44 + }
1.45 +
1.46 +TInt RoundTrip(TReal& aOut, const TReal& aIn)
1.47 + {
1.48 + TBuf8<64> text;
1.49 + TRealFormat fmt;
1.50 + fmt.iType = KRealFormatExponent | KRealInjectiveLimit | KUseSigFigs | KDoNotUseTriads | KAllowThreeDigitExp;
1.51 + fmt.iWidth = 32;
1.52 + fmt.iPlaces = KIEEEDoubleInjectivePrecision;
1.53 + fmt.iPoint = '.';
1.54 +#ifdef __ALWAYS_PRINT__
1.55 + PrintRealHex("Input : ", aIn);
1.56 +#endif
1.57 + TInt r = text.Num(aIn, fmt);
1.58 + if (r<0)
1.59 + {
1.60 + test.Printf(_L("Result %d (Num)\n"), r);
1.61 + return r;
1.62 + }
1.63 +#ifdef __ALWAYS_PRINT__
1.64 + TBuf16<64> text16;
1.65 + text16.Copy(text);
1.66 + test.Printf(_L("Text : %S\n"), &text16);
1.67 +#endif
1.68 + TLex8 lex(text);
1.69 + r = lex.Val(aOut);
1.70 + if (r < 0)
1.71 + {
1.72 + test.Printf(_L("Result %d (Val)\n"), r);
1.73 + return r;
1.74 + }
1.75 +#ifdef __ALWAYS_PRINT__
1.76 + PrintRealHex("Output: ", aOut);
1.77 +#endif
1.78 + volatile TUint32* in = (volatile TUint32*)&aIn;
1.79 + volatile TUint32* out = (volatile TUint32*)&aOut;
1.80 + if (in[0]!=out[0] || in[1]!=out[1])
1.81 + {
1.82 + test.Printf(_L("Unsuccessful\n"));
1.83 +#ifndef __ALWAYS_PRINT__
1.84 + PrintRealHex("Input : ", aIn);
1.85 + TBuf16<64> text16;
1.86 + text16.Copy(text);
1.87 + test.Printf(_L("Text : %S\n"), &text16);
1.88 + PrintRealHex("Output: ", aOut);
1.89 +#endif
1.90 + return KErrUnknown;
1.91 + }
1.92 + return KErrNone;
1.93 + }
1.94 +
1.95 +const TUint64 KMantissaOverflow = UI64LIT(0x20000000000000); // 2^53
1.96 +const TUint64 KMantissaThreshold = UI64LIT(0x10000000000000); // 2^52
1.97 +
1.98 +class R
1.99 + {
1.100 +public:
1.101 + enum {EMinExp=0, EMinNormExp=1, EMaxNormExp=2046, EMaxExp=2047};
1.102 +public:
1.103 + R();
1.104 + R(const TReal& aIn);
1.105 + TReal Value() const;
1.106 + TInt Next();
1.107 + TInt Prev();
1.108 +public:
1.109 + TUint64 iMant; // if iExp>0 2^52<=iMant<2^53 else 0<=iMant<2^52
1.110 + TInt iExp; // 0 < iExp < 2047
1.111 + TInt iSign;
1.112 + };
1.113 +
1.114 +R::R()
1.115 + {
1.116 + iMant = 0;
1.117 + iExp = 0;
1.118 + iSign = 0;
1.119 + }
1.120 +
1.121 +R::R(const TReal& aIn)
1.122 + {
1.123 + const volatile TUint32* in = (const volatile TUint32*)&aIn;
1.124 +#ifdef __DOUBLE_WORDS_SWAPPED__
1.125 + TUint32 high = in[0];
1.126 + TUint32 low = in[1];
1.127 +#else
1.128 + TUint32 high = in[1];
1.129 + TUint32 low = in[0];
1.130 +#endif
1.131 + iSign = high >> 31;
1.132 + iExp = (high >> 20) & EMaxExp;
1.133 + iMant = MAKE_TUINT64(high, low);
1.134 + iMant <<= 12;
1.135 + iMant >>= 12;
1.136 + if (iExp)
1.137 + iMant += KMantissaThreshold;
1.138 + }
1.139 +
1.140 +TReal R::Value() const
1.141 + {
1.142 + TUint32 high = iSign ? 1 : 0;
1.143 + high <<= 31;
1.144 + high |= (iExp<<20);
1.145 + TUint32 mh = I64HIGH(iMant);
1.146 + mh <<= 12;
1.147 + high |= (mh>>12);
1.148 + TUint32 low = I64LOW(iMant);
1.149 +
1.150 + union {TReal iReal; TUint32 iX[2];} result;
1.151 +#ifdef __DOUBLE_WORDS_SWAPPED__
1.152 + result.iX[0] = high;
1.153 + result.iX[1] = low;
1.154 +#else
1.155 + result.iX[0] = low;
1.156 + result.iX[1] = high;
1.157 +#endif
1.158 + return result.iReal;
1.159 + }
1.160 +
1.161 +TInt R::Next()
1.162 + {
1.163 + if (iExp>0)
1.164 + {
1.165 + if (++iMant == KMantissaOverflow)
1.166 + {
1.167 + iMant >>= 1;
1.168 + if (++iExp == EMaxExp)
1.169 + return KErrOverflow;
1.170 + }
1.171 + return KErrNone;
1.172 + }
1.173 + if (++iMant == KMantissaThreshold)
1.174 + iExp = 1;
1.175 + return KErrNone;
1.176 + }
1.177 +
1.178 +TInt R::Prev()
1.179 + {
1.180 + if (iExp == EMaxExp)
1.181 + {
1.182 + if (iMant == KMantissaThreshold)
1.183 + {
1.184 + --iExp;
1.185 + return KErrNone;
1.186 + }
1.187 + return KErrGeneral;
1.188 + }
1.189 + if (iExp>0)
1.190 + {
1.191 + if (--iMant < KMantissaThreshold)
1.192 + {
1.193 + if (--iExp)
1.194 + {
1.195 + iMant <<= 1;
1.196 + iMant++;
1.197 + }
1.198 + }
1.199 + return KErrNone;
1.200 + }
1.201 + if (iMant==0)
1.202 + return KErrUnderflow;
1.203 + --iMant;
1.204 + return KErrNone;
1.205 + }
1.206 +
1.207 +void DoTest(R& aR, TInt& aErrorCount)
1.208 + {
1.209 + TReal out;
1.210 + TInt r;
1.211 + r = RoundTrip(out, aR.Value());
1.212 + if (r==KErrUnknown)
1.213 + ++aErrorCount;
1.214 + R R1(aR);
1.215 + R R2(aR);
1.216 + if (R1.Next()==KErrNone)
1.217 + {
1.218 + r = RoundTrip(out, R1.Value());
1.219 + if (r==KErrUnknown)
1.220 + ++aErrorCount;
1.221 + }
1.222 + if (R2.Prev()==KErrNone)
1.223 + {
1.224 + r = RoundTrip(out, R2.Value());
1.225 + if (r==KErrUnknown)
1.226 + ++aErrorCount;
1.227 + }
1.228 + }
1.229 +
1.230 +void DoTest(TInt aExp, TInt& aErrorCount)
1.231 + {
1.232 + R x;
1.233 + x.iExp = aExp;
1.234 + x.iMant = KMantissaThreshold;
1.235 + if (aExp==0)
1.236 + {
1.237 + do {
1.238 + x.iMant >>= 1;
1.239 + DoTest(x, aErrorCount);
1.240 + } while (x.iMant);
1.241 + }
1.242 + else
1.243 + {
1.244 + DoTest(x, aErrorCount);
1.245 + }
1.246 + }
1.247 +
1.248 +void DoTestPow10(TInt aPow, TInt& aErrorCount)
1.249 + {
1.250 + TReal64 r64;
1.251 + TInt r = Math::Pow10(r64, aPow);
1.252 + if (r<0)
1.253 + return;
1.254 + R x(r64);
1.255 + DoTest(x, aErrorCount);
1.256 + }
1.257 +
1.258 +void DoTestRandom(TInt& aErrorCount)
1.259 + {
1.260 + static TInt64 randSeed = I64LIT(0x3333333333333333);
1.261 + R x;
1.262 + x.iExp = Math::Rand(randSeed) & R::EMaxExp;
1.263 + x.iMant = ((TUint64)Math::Rand(randSeed) << 32) | (TUint64)Math::Rand(randSeed);
1.264 + while (x.iMant > KMantissaThreshold)
1.265 + x.iMant >>= 1;
1.266 + x.iSign = Math::Rand(randSeed) & 0x1;
1.267 + DoTest(x, aErrorCount);
1.268 + }
1.269 +
1.270 +TInt E32Main()
1.271 + {
1.272 + test.Title();
1.273 + test.Start(_L("Testing conversion from double->string->double"));
1.274 +
1.275 + TInt exp;
1.276 + TInt errors = 0;
1.277 + test.Next(_L("Test the conversion of powers of 2"));
1.278 + for (exp = 0; exp < 2047; ++exp)
1.279 + {
1.280 + DoTest(exp, errors);
1.281 + }
1.282 +
1.283 + test.Next(_L("Test the conversion of powers of 10"));
1.284 + for (exp = -325; exp < 325; ++exp)
1.285 + {
1.286 + DoTestPow10(exp, errors);
1.287 + }
1.288 +
1.289 + test.Next(_L("Test the conversion of some random numbers"));
1.290 + for (exp = 0; exp < 100; ++exp)
1.291 + {
1.292 + DoTestRandom(errors);
1.293 + }
1.294 +
1.295 + test_Equal(0, errors);
1.296 +
1.297 + test.End();
1.298 + return KErrNone;
1.299 + }