os/kernelhwsrv/kerneltest/e32test/math/t_roundtrip.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test\math\t_roundtrip.cpp
sl@0
    15
// Tests round-trip convertibility of double->string->double
sl@0
    16
// 
sl@0
    17
//
sl@0
    18
sl@0
    19
#define __E32TEST_EXTENSION__
sl@0
    20
#include <e32test.h>
sl@0
    21
#include <e32math.h>
sl@0
    22
sl@0
    23
//#define __ALWAYS_PRINT__
sl@0
    24
sl@0
    25
RTest test(_L("T_ROUNDTRIP"));
sl@0
    26
sl@0
    27
void PrintRealHex(const char* aTitle, const TReal& aIn)
sl@0
    28
	{
sl@0
    29
	volatile TUint32* in = (volatile TUint32*)&aIn;
sl@0
    30
#ifdef __DOUBLE_WORDS_SWAPPED__
sl@0
    31
	TUint32 high = in[0];
sl@0
    32
	TUint32 low = in[1];
sl@0
    33
#else
sl@0
    34
	TUint32 high = in[1];
sl@0
    35
	TUint32 low = in[0];
sl@0
    36
#endif
sl@0
    37
	TBuf<256> title;
sl@0
    38
	if (aTitle)
sl@0
    39
		title.Copy(TPtrC8((const TUint8*)aTitle));
sl@0
    40
	test.Printf(_L("%S%08x %08x\n"), &title, high, low);
sl@0
    41
	}
sl@0
    42
sl@0
    43
TInt RoundTrip(TReal& aOut, const TReal& aIn)
sl@0
    44
	{
sl@0
    45
	TBuf8<64> text;
sl@0
    46
	TRealFormat fmt;
sl@0
    47
	fmt.iType = KRealFormatExponent | KRealInjectiveLimit | KUseSigFigs | KDoNotUseTriads | KAllowThreeDigitExp;
sl@0
    48
	fmt.iWidth = 32;
sl@0
    49
	fmt.iPlaces = KIEEEDoubleInjectivePrecision;
sl@0
    50
	fmt.iPoint = '.';
sl@0
    51
#ifdef __ALWAYS_PRINT__
sl@0
    52
	PrintRealHex("Input : ", aIn);
sl@0
    53
#endif
sl@0
    54
	TInt r = text.Num(aIn, fmt);
sl@0
    55
	if (r<0)
sl@0
    56
		{
sl@0
    57
		test.Printf(_L("Result %d (Num)\n"), r);
sl@0
    58
		return r;
sl@0
    59
		}
sl@0
    60
#ifdef __ALWAYS_PRINT__
sl@0
    61
	TBuf16<64> text16;
sl@0
    62
	text16.Copy(text);
sl@0
    63
	test.Printf(_L("Text  : %S\n"), &text16);
sl@0
    64
#endif
sl@0
    65
	TLex8 lex(text);
sl@0
    66
	r = lex.Val(aOut);
sl@0
    67
	if (r < 0)
sl@0
    68
		{
sl@0
    69
		test.Printf(_L("Result %d (Val)\n"), r);
sl@0
    70
		return r;
sl@0
    71
		}
sl@0
    72
#ifdef __ALWAYS_PRINT__
sl@0
    73
	PrintRealHex("Output: ", aOut);
sl@0
    74
#endif
sl@0
    75
	volatile TUint32* in = (volatile TUint32*)&aIn;
sl@0
    76
	volatile TUint32* out = (volatile TUint32*)&aOut;
sl@0
    77
	if (in[0]!=out[0] || in[1]!=out[1])
sl@0
    78
		{
sl@0
    79
		test.Printf(_L("Unsuccessful\n"));
sl@0
    80
#ifndef __ALWAYS_PRINT__
sl@0
    81
		PrintRealHex("Input : ", aIn);
sl@0
    82
		TBuf16<64> text16;
sl@0
    83
		text16.Copy(text);
sl@0
    84
		test.Printf(_L("Text  : %S\n"), &text16);
sl@0
    85
		PrintRealHex("Output: ", aOut);
sl@0
    86
#endif
sl@0
    87
		return KErrUnknown;
sl@0
    88
		}
sl@0
    89
	return KErrNone;
sl@0
    90
	}
sl@0
    91
sl@0
    92
const TUint64 KMantissaOverflow =	UI64LIT(0x20000000000000);	// 2^53
sl@0
    93
const TUint64 KMantissaThreshold =	UI64LIT(0x10000000000000);	// 2^52
sl@0
    94
sl@0
    95
class R
sl@0
    96
	{
sl@0
    97
public:
sl@0
    98
	enum {EMinExp=0, EMinNormExp=1, EMaxNormExp=2046, EMaxExp=2047};
sl@0
    99
public:
sl@0
   100
	R();
sl@0
   101
	R(const TReal& aIn);
sl@0
   102
	TReal Value() const;
sl@0
   103
	TInt Next();
sl@0
   104
	TInt Prev();
sl@0
   105
public:
sl@0
   106
	TUint64	iMant;		//	if iExp>0 2^52<=iMant<2^53 else 0<=iMant<2^52
sl@0
   107
	TInt	iExp;		//	0 < iExp < 2047
sl@0
   108
	TInt	iSign;
sl@0
   109
	};
sl@0
   110
sl@0
   111
R::R()
sl@0
   112
	{
sl@0
   113
	iMant = 0;
sl@0
   114
	iExp = 0;
sl@0
   115
	iSign = 0;
sl@0
   116
	}
sl@0
   117
sl@0
   118
R::R(const TReal& aIn)
sl@0
   119
	{
sl@0
   120
	const volatile TUint32* in = (const volatile TUint32*)&aIn;
sl@0
   121
#ifdef __DOUBLE_WORDS_SWAPPED__
sl@0
   122
	TUint32 high = in[0];
sl@0
   123
	TUint32 low = in[1];
sl@0
   124
#else
sl@0
   125
	TUint32 high = in[1];
sl@0
   126
	TUint32 low = in[0];
sl@0
   127
#endif
sl@0
   128
	iSign = high >> 31;
sl@0
   129
	iExp = (high >> 20) & EMaxExp;
sl@0
   130
	iMant = MAKE_TUINT64(high, low);
sl@0
   131
	iMant <<= 12;
sl@0
   132
	iMant >>= 12;
sl@0
   133
	if (iExp)
sl@0
   134
		iMant += KMantissaThreshold;
sl@0
   135
	}
sl@0
   136
sl@0
   137
TReal R::Value() const
sl@0
   138
	{
sl@0
   139
	TUint32 high = iSign ? 1 : 0;
sl@0
   140
	high <<= 31;
sl@0
   141
	high |= (iExp<<20);
sl@0
   142
	TUint32 mh = I64HIGH(iMant);
sl@0
   143
	mh <<= 12;
sl@0
   144
	high |= (mh>>12);
sl@0
   145
	TUint32 low = I64LOW(iMant);
sl@0
   146
sl@0
   147
	union {TReal iReal; TUint32 iX[2];} result;
sl@0
   148
#ifdef __DOUBLE_WORDS_SWAPPED__
sl@0
   149
	result.iX[0] = high;
sl@0
   150
	result.iX[1] = low;
sl@0
   151
#else
sl@0
   152
	result.iX[0] = low;
sl@0
   153
	result.iX[1] = high;
sl@0
   154
#endif
sl@0
   155
	return result.iReal;
sl@0
   156
	}
sl@0
   157
sl@0
   158
TInt R::Next()
sl@0
   159
	{
sl@0
   160
	if (iExp>0)
sl@0
   161
		{
sl@0
   162
		if (++iMant == KMantissaOverflow)
sl@0
   163
			{
sl@0
   164
			iMant >>= 1;
sl@0
   165
			if (++iExp == EMaxExp)
sl@0
   166
				return KErrOverflow;
sl@0
   167
			}
sl@0
   168
		return KErrNone;
sl@0
   169
		}
sl@0
   170
	if (++iMant == KMantissaThreshold)
sl@0
   171
		iExp = 1;
sl@0
   172
	return KErrNone;
sl@0
   173
	}
sl@0
   174
sl@0
   175
TInt R::Prev()
sl@0
   176
	{
sl@0
   177
	if (iExp == EMaxExp)
sl@0
   178
		{
sl@0
   179
		if (iMant == KMantissaThreshold)
sl@0
   180
			{
sl@0
   181
			--iExp;
sl@0
   182
			return KErrNone;
sl@0
   183
			}
sl@0
   184
		return KErrGeneral;
sl@0
   185
		}
sl@0
   186
	if (iExp>0)
sl@0
   187
		{
sl@0
   188
		if (--iMant < KMantissaThreshold)
sl@0
   189
			{
sl@0
   190
			if (--iExp)
sl@0
   191
				{
sl@0
   192
				iMant <<= 1;
sl@0
   193
				iMant++;
sl@0
   194
				}
sl@0
   195
			}
sl@0
   196
		return KErrNone;
sl@0
   197
		}
sl@0
   198
	if (iMant==0)
sl@0
   199
		return KErrUnderflow;
sl@0
   200
	--iMant;
sl@0
   201
	return KErrNone;
sl@0
   202
	}
sl@0
   203
sl@0
   204
void DoTest(R& aR, TInt& aErrorCount)
sl@0
   205
	{
sl@0
   206
	TReal out;
sl@0
   207
	TInt r;
sl@0
   208
	r = RoundTrip(out, aR.Value());
sl@0
   209
	if (r==KErrUnknown)
sl@0
   210
		++aErrorCount;
sl@0
   211
	R R1(aR);
sl@0
   212
	R R2(aR);
sl@0
   213
	if (R1.Next()==KErrNone)
sl@0
   214
		{
sl@0
   215
		r = RoundTrip(out, R1.Value());
sl@0
   216
		if (r==KErrUnknown)
sl@0
   217
			++aErrorCount;
sl@0
   218
		}
sl@0
   219
	if (R2.Prev()==KErrNone)
sl@0
   220
		{
sl@0
   221
		r = RoundTrip(out, R2.Value());
sl@0
   222
		if (r==KErrUnknown)
sl@0
   223
			++aErrorCount;
sl@0
   224
		}
sl@0
   225
	}
sl@0
   226
sl@0
   227
void DoTest(TInt aExp, TInt& aErrorCount)
sl@0
   228
	{
sl@0
   229
	R x;
sl@0
   230
	x.iExp = aExp;
sl@0
   231
	x.iMant = KMantissaThreshold;
sl@0
   232
	if (aExp==0)
sl@0
   233
		{
sl@0
   234
		do	{
sl@0
   235
			x.iMant >>= 1;
sl@0
   236
			DoTest(x, aErrorCount);
sl@0
   237
			} while (x.iMant);
sl@0
   238
		}
sl@0
   239
	else
sl@0
   240
		{
sl@0
   241
		DoTest(x, aErrorCount);
sl@0
   242
		}
sl@0
   243
	}
sl@0
   244
sl@0
   245
void DoTestPow10(TInt aPow, TInt& aErrorCount)
sl@0
   246
	{
sl@0
   247
	TReal64 r64;
sl@0
   248
	TInt r = Math::Pow10(r64, aPow);
sl@0
   249
	if (r<0)
sl@0
   250
		return;
sl@0
   251
	R x(r64);
sl@0
   252
	DoTest(x, aErrorCount);
sl@0
   253
	}
sl@0
   254
sl@0
   255
void DoTestRandom(TInt& aErrorCount)
sl@0
   256
	{
sl@0
   257
	static TInt64 randSeed = I64LIT(0x3333333333333333);
sl@0
   258
	R x;
sl@0
   259
	x.iExp = Math::Rand(randSeed) & R::EMaxExp;
sl@0
   260
	x.iMant = ((TUint64)Math::Rand(randSeed) << 32) | (TUint64)Math::Rand(randSeed);
sl@0
   261
	while (x.iMant > KMantissaThreshold)
sl@0
   262
		x.iMant >>= 1;
sl@0
   263
	x.iSign = Math::Rand(randSeed) & 0x1;
sl@0
   264
	DoTest(x, aErrorCount);
sl@0
   265
	}
sl@0
   266
sl@0
   267
TInt E32Main()
sl@0
   268
	{
sl@0
   269
	test.Title();
sl@0
   270
	test.Start(_L("Testing conversion from double->string->double"));
sl@0
   271
sl@0
   272
	TInt exp;
sl@0
   273
	TInt errors = 0;
sl@0
   274
	test.Next(_L("Test the conversion of powers of 2"));
sl@0
   275
	for (exp = 0; exp < 2047; ++exp)
sl@0
   276
		{
sl@0
   277
		DoTest(exp, errors);
sl@0
   278
		}
sl@0
   279
sl@0
   280
	test.Next(_L("Test the conversion of powers of 10"));
sl@0
   281
	for (exp = -325; exp < 325; ++exp)
sl@0
   282
		{
sl@0
   283
		DoTestPow10(exp, errors);
sl@0
   284
		}
sl@0
   285
sl@0
   286
	test.Next(_L("Test the conversion of some random numbers"));
sl@0
   287
	for (exp = 0; exp < 100; ++exp)
sl@0
   288
		{
sl@0
   289
		DoTestRandom(errors);
sl@0
   290
		}
sl@0
   291
sl@0
   292
	test_Equal(0, errors);
sl@0
   293
sl@0
   294
	test.End();
sl@0
   295
	return KErrNone;
sl@0
   296
	}