kerneltest/e32test/math/largeint.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/math/largeint.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,285 @@
+// 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 "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\math\largeint.cpp
+// 
+//
+
+#include "largeint.h"
+
+TLargeIntBase::TLargeIntBase(TInt n)
+	: iC(n)
+	{
+	Mem::FillZ(iX,n*sizeof(TUint32));
+	}
+
+TLargeIntBase::TLargeIntBase(TInt n, TInt32 aSigned32)
+	: iC(n)
+	{
+	TUint f = (aSigned32<0) ? 0xff : 0;
+	Mem::Fill(iX,n*sizeof(TUint32),f);
+	iX[0]=aSigned32;
+	}
+
+TLargeIntBase::TLargeIntBase(TInt n, TUint32 aUnsigned32)
+	: iC(n)
+	{
+	Mem::FillZ(iX,n*sizeof(TUint32));
+	iX[0]=aUnsigned32;
+	}
+
+TLargeIntBase::TLargeIntBase(TInt n, const TLargeIntBase& aSrc, TMode aMode)
+	: iC(n)
+	{
+	__ASSERT(aMode==ETruncate||n>=aSrc.iC);	// if not truncating, dest can't be shorter than source
+	__ASSERT(aMode!=ETruncate||n<=aSrc.iC);	// if truncating, dest can't be longer than source
+	TInt min = Min(n,aSrc.iC);
+	TInt i;
+	for (i=0; i<min; ++i)
+		iX[i] = aSrc.iX[i];
+	if (aMode==ETruncate || n==aSrc.iC)
+		return;
+	TUint32 f = (aMode==ESignExtend && (iX[i-1] & 0x80000000u)) ? 0xffffffffu : 0;
+	for (; i<n; ++i)
+		iX[i] = f;
+	}
+
+TLargeIntBase::TLargeIntBase(TInt n, const TUint32* aPtr)
+	: iC(n)
+	{
+	Mem::Copy(iX, aPtr, n*sizeof(TUint32));
+	}
+
+TLargeIntBase::TLargeIntBase(TInt n, const Int64& aSigned64)
+	: iC(n)
+	{
+	__ASSERT(n>=2);
+	Mem::Copy(iX, &aSigned64, 8);
+	TUint f = (iX[1] & 0x80000000u) ? 0xff : 0;
+	Mem::Fill(iX+2,(n-2)*sizeof(TUint32),f);
+	}
+
+TLargeIntBase::TLargeIntBase(TInt n, const Uint64& aUnsigned64)
+	: iC(n)
+	{
+	__ASSERT(n>=2);
+	Mem::Copy(iX, &aUnsigned64, 8);
+	Mem::FillZ(iX+2,(n-2)*sizeof(TUint32));
+	}
+
+void TLargeIntBase::Not()
+	{
+	TInt i;
+	for (i=0; i<iC; ++i)
+		iX[i] = ~iX[i];
+	}
+
+void TLargeIntBase::Neg()
+	{
+	Not();
+	Inc();
+	}
+
+void TLargeIntBase::Abs()
+	{
+	if (iX[iC-1] & 0x80000000u)
+		Neg();
+	}
+
+void TLargeIntBase::Inc()
+	{
+	TInt i;
+	for (i=0; i<iC && ++iX[i]==0; ++i) {}
+	}
+
+void TLargeIntBase::Dec()
+	{
+	TInt i;
+	for (i=0; i<iC && --iX[i]==0xffffffffu; ++i) {}
+	}
+
+TUint32 TLargeIntBase::Lsl()
+	{
+	TInt i;
+	TUint32 c = 0;
+	for (i=0; i<iC; ++i)
+		{
+		TUint32 x = (iX[i]<<1) | (c>>31);
+		c = iX[i];
+		iX[i] = x;
+		}
+	return c>>31;
+	}
+
+TUint32 TLargeIntBase::Lsr()
+	{
+	TInt i;
+	TUint32 c = 0;
+	for (i=iC-1; i>=0; --i)
+		{
+		TUint32 x = (iX[i]>>1) | (c<<31);
+		c = iX[i];
+		iX[i] = x;
+		}
+	return c&1;
+	}
+
+TUint32 TLargeIntBase::Asr()
+	{
+	TInt i=iC-1;
+	TUint32 c = iX[i]>>31;
+	for (; i>=0; --i)
+		{
+		TUint32 x = (iX[i]>>1) | (c<<31);
+		c = iX[i];
+		iX[i] = x;
+		}
+	return c&1;
+	}
+
+void TLargeIntBase::Lsl(TInt aCount)
+	{
+	while(--aCount>=0)
+		Lsl();
+	}
+
+void TLargeIntBase::Lsr(TInt aCount)
+	{
+	while(--aCount>=0)
+		Lsr();
+	}
+
+void TLargeIntBase::Asr(TInt aCount)
+	{
+	while(--aCount>=0)
+		Asr();
+	}
+
+void TLargeIntBase::Add(const TLargeIntBase& a)
+	{
+	__ASSERT(a.iC==iC);
+	TInt i;
+	TUint32 c = 0;
+	for (i=0; i<iC; ++i)
+		{
+		TUint32 x = iX[i];
+		TUint32 y = a.iX[i];
+		TUint32 s = x + y;
+		iX[i] = (s + (c>>31));
+		TUint32 g = (x & y) | ((x | y) &~ s);
+		TUint32 p = ~s ? 0 : s;
+		c = g | (c & p);
+		}
+	}
+
+void TLargeIntBase::Sub(const TLargeIntBase& a)
+	{
+	__ASSERT(a.iC==iC);
+	TInt i;
+	TUint32 c = 0x80000000u;
+	for (i=0; i<iC; ++i)
+		{
+		TUint32 x = iX[i];
+		TUint32 y = ~a.iX[i];
+		TUint32 s = x + y;
+		iX[i] = (s + (c>>31));
+		TUint32 g = (x & y) | ((x | y) &~ s);
+		TUint32 p = ~s ? 0 : s;
+		c = g | (c & p);
+		}
+	}
+
+void TLargeIntBase::Mul(const TLargeIntBase& a)
+	{
+	__ASSERT(a.iC==iC);
+	TUint32 temp[64];	// HACK!!
+	Mem::Copy(temp, this, (iC+1)*sizeof(TUint32));
+	TLargeIntBase& b = *(TLargeIntBase*)temp;
+	new (this) TLargeIntBase(iC,TUint32(0u));
+	TInt i;
+	for (i=0; i<32*iC; ++i)
+		{
+		Lsl();
+		if (b.Lsl())
+			Add(a);
+		}
+	}
+
+void TLargeIntBase::DivU(const TLargeIntBase& aDivisor, TLargeIntBase& aRem)
+	{
+	__ASSERT(aDivisor.iC==iC);
+	__ASSERT(aRem.iC==iC);
+	new (&aRem) TLargeIntBase(iC,TUint32(0u));
+	TInt i;
+	for (i=0; i<iC*32; ++i)
+		{
+		aRem.Lsl();
+		if (Lsl())
+			aRem.Inc();
+		if (aRem.Hs(aDivisor))
+			aRem.Sub(aDivisor), Inc();
+		}
+	}
+
+void TLargeIntBase::DivS(const TLargeIntBase& aDivisor, TLargeIntBase& aRem)
+	{
+	__ASSERT(aDivisor.iC==iC);
+	__ASSERT(aRem.iC==iC);
+	TUint32 temp[64];	// HACK!!
+	Mem::Copy(temp, &aDivisor, (iC+1)*sizeof(TUint32));
+	TLargeIntBase& divisor = *(TLargeIntBase*)temp;
+	TUint32 rs = iX[iC-1];
+	TUint32 qs = divisor.iX[iC-1] ^ rs;
+	Abs();
+	divisor.Abs();
+	DivU(divisor, aRem);
+	if (rs & 0x80000000u)
+		aRem.Neg();
+	if (qs & 0x80000000u)
+		Neg();
+	}
+
+TInt TLargeIntBase::CompareU(const TLargeIntBase& a) const
+	{
+	__ASSERT(a.iC==iC);
+	TInt i;
+	for (i=iC-1; i>=0; --i)
+		{
+		TUint32 x = iX[i];
+		TUint32 y = a.iX[i];
+		if (x>y)
+			return 1;
+		if (x<y)
+			return -1;
+		}
+	return 0;
+	}
+
+TInt TLargeIntBase::CompareS(const TLargeIntBase& a) const
+	{
+	__ASSERT(a.iC==iC);
+	TInt i;
+	TUint32 m = 0x80000000u;
+	for (i=iC-1; i>=0; --i)
+		{
+		TUint32 x = iX[i] ^ m;
+		TUint32 y = a.iX[i] ^ m;
+		m = 0;
+		if (x>y)
+			return 1;
+		if (x<y)
+			return -1;
+		}
+	return 0;
+	}
+