symport/e32test/math/largeint.cpp
changeset 1 0a7b44b10206
child 2 806186ab5e14
equal deleted inserted replaced
0:c55016431358 1:0a7b44b10206
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\math\largeint.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "largeint.h"
       
    19 
       
    20 TLargeIntBase::TLargeIntBase(TInt n)
       
    21 	: iC(n)
       
    22 	{
       
    23 	Mem::FillZ(iX,n*sizeof(TUint32));
       
    24 	}
       
    25 
       
    26 TLargeIntBase::TLargeIntBase(TInt n, TInt32 aSigned32)
       
    27 	: iC(n)
       
    28 	{
       
    29 	TUint f = (aSigned32<0) ? 0xff : 0;
       
    30 	Mem::Fill(iX,n*sizeof(TUint32),f);
       
    31 	iX[0]=aSigned32;
       
    32 	}
       
    33 
       
    34 TLargeIntBase::TLargeIntBase(TInt n, TUint32 aUnsigned32)
       
    35 	: iC(n)
       
    36 	{
       
    37 	Mem::FillZ(iX,n*sizeof(TUint32));
       
    38 	iX[0]=aUnsigned32;
       
    39 	}
       
    40 
       
    41 TLargeIntBase::TLargeIntBase(TInt n, const TLargeIntBase& aSrc, TMode aMode)
       
    42 	: iC(n)
       
    43 	{
       
    44 	__ASSERT(aMode==ETruncate||n>=aSrc.iC);	// if not truncating, dest can't be shorter than source
       
    45 	__ASSERT(aMode!=ETruncate||n<=aSrc.iC);	// if truncating, dest can't be longer than source
       
    46 	TInt min = Min(n,aSrc.iC);
       
    47 	TInt i;
       
    48 	for (i=0; i<min; ++i)
       
    49 		iX[i] = aSrc.iX[i];
       
    50 	if (aMode==ETruncate || n==aSrc.iC)
       
    51 		return;
       
    52 	TUint32 f = (aMode==ESignExtend && (iX[i-1] & 0x80000000u)) ? 0xffffffffu : 0;
       
    53 	for (; i<n; ++i)
       
    54 		iX[i] = f;
       
    55 	}
       
    56 
       
    57 TLargeIntBase::TLargeIntBase(TInt n, const TUint32* aPtr)
       
    58 	: iC(n)
       
    59 	{
       
    60 	Mem::Copy(iX, aPtr, n*sizeof(TUint32));
       
    61 	}
       
    62 
       
    63 TLargeIntBase::TLargeIntBase(TInt n, const Int64& aSigned64)
       
    64 	: iC(n)
       
    65 	{
       
    66 	__ASSERT(n>=2);
       
    67 	Mem::Copy(iX, &aSigned64, 8);
       
    68 	TUint f = (iX[1] & 0x80000000u) ? 0xff : 0;
       
    69 	Mem::Fill(iX+2,(n-2)*sizeof(TUint32),f);
       
    70 	}
       
    71 
       
    72 TLargeIntBase::TLargeIntBase(TInt n, const Uint64& aUnsigned64)
       
    73 	: iC(n)
       
    74 	{
       
    75 	__ASSERT(n>=2);
       
    76 	Mem::Copy(iX, &aUnsigned64, 8);
       
    77 	Mem::FillZ(iX+2,(n-2)*sizeof(TUint32));
       
    78 	}
       
    79 
       
    80 void TLargeIntBase::Not()
       
    81 	{
       
    82 	TInt i;
       
    83 	for (i=0; i<iC; ++i)
       
    84 		iX[i] = ~iX[i];
       
    85 	}
       
    86 
       
    87 void TLargeIntBase::Neg()
       
    88 	{
       
    89 	Not();
       
    90 	Inc();
       
    91 	}
       
    92 
       
    93 void TLargeIntBase::Abs()
       
    94 	{
       
    95 	if (iX[iC-1] & 0x80000000u)
       
    96 		Neg();
       
    97 	}
       
    98 
       
    99 void TLargeIntBase::Inc()
       
   100 	{
       
   101 	TInt i;
       
   102 	for (i=0; i<iC && ++iX[i]==0; ++i) {}
       
   103 	}
       
   104 
       
   105 void TLargeIntBase::Dec()
       
   106 	{
       
   107 	TInt i;
       
   108 	for (i=0; i<iC && --iX[i]==0xffffffffu; ++i) {}
       
   109 	}
       
   110 
       
   111 TUint32 TLargeIntBase::Lsl()
       
   112 	{
       
   113 	TInt i;
       
   114 	TUint32 c = 0;
       
   115 	for (i=0; i<iC; ++i)
       
   116 		{
       
   117 		TUint32 x = (iX[i]<<1) | (c>>31);
       
   118 		c = iX[i];
       
   119 		iX[i] = x;
       
   120 		}
       
   121 	return c>>31;
       
   122 	}
       
   123 
       
   124 TUint32 TLargeIntBase::Lsr()
       
   125 	{
       
   126 	TInt i;
       
   127 	TUint32 c = 0;
       
   128 	for (i=iC-1; i>=0; --i)
       
   129 		{
       
   130 		TUint32 x = (iX[i]>>1) | (c<<31);
       
   131 		c = iX[i];
       
   132 		iX[i] = x;
       
   133 		}
       
   134 	return c&1;
       
   135 	}
       
   136 
       
   137 TUint32 TLargeIntBase::Asr()
       
   138 	{
       
   139 	TInt i=iC-1;
       
   140 	TUint32 c = iX[i]>>31;
       
   141 	for (; i>=0; --i)
       
   142 		{
       
   143 		TUint32 x = (iX[i]>>1) | (c<<31);
       
   144 		c = iX[i];
       
   145 		iX[i] = x;
       
   146 		}
       
   147 	return c&1;
       
   148 	}
       
   149 
       
   150 void TLargeIntBase::Lsl(TInt aCount)
       
   151 	{
       
   152 	while(--aCount>=0)
       
   153 		Lsl();
       
   154 	}
       
   155 
       
   156 void TLargeIntBase::Lsr(TInt aCount)
       
   157 	{
       
   158 	while(--aCount>=0)
       
   159 		Lsr();
       
   160 	}
       
   161 
       
   162 void TLargeIntBase::Asr(TInt aCount)
       
   163 	{
       
   164 	while(--aCount>=0)
       
   165 		Asr();
       
   166 	}
       
   167 
       
   168 void TLargeIntBase::Add(const TLargeIntBase& a)
       
   169 	{
       
   170 	__ASSERT(a.iC==iC);
       
   171 	TInt i;
       
   172 	TUint32 c = 0;
       
   173 	for (i=0; i<iC; ++i)
       
   174 		{
       
   175 		TUint32 x = iX[i];
       
   176 		TUint32 y = a.iX[i];
       
   177 		TUint32 s = x + y;
       
   178 		iX[i] = (s + (c>>31));
       
   179 		TUint32 g = (x & y) | ((x | y) &~ s);
       
   180 		TUint32 p = ~s ? 0 : s;
       
   181 		c = g | (c & p);
       
   182 		}
       
   183 	}
       
   184 
       
   185 void TLargeIntBase::Sub(const TLargeIntBase& a)
       
   186 	{
       
   187 	__ASSERT(a.iC==iC);
       
   188 	TInt i;
       
   189 	TUint32 c = 0x80000000u;
       
   190 	for (i=0; i<iC; ++i)
       
   191 		{
       
   192 		TUint32 x = iX[i];
       
   193 		TUint32 y = ~a.iX[i];
       
   194 		TUint32 s = x + y;
       
   195 		iX[i] = (s + (c>>31));
       
   196 		TUint32 g = (x & y) | ((x | y) &~ s);
       
   197 		TUint32 p = ~s ? 0 : s;
       
   198 		c = g | (c & p);
       
   199 		}
       
   200 	}
       
   201 
       
   202 void TLargeIntBase::Mul(const TLargeIntBase& a)
       
   203 	{
       
   204 	__ASSERT(a.iC==iC);
       
   205 	TUint32 temp[64];	// HACK!!
       
   206 	Mem::Copy(temp, this, (iC+1)*sizeof(TUint32));
       
   207 	TLargeIntBase& b = *(TLargeIntBase*)temp;
       
   208 	new (this) TLargeIntBase(iC,TUint32(0u));
       
   209 	TInt i;
       
   210 	for (i=0; i<32*iC; ++i)
       
   211 		{
       
   212 		Lsl();
       
   213 		if (b.Lsl())
       
   214 			Add(a);
       
   215 		}
       
   216 	}
       
   217 
       
   218 void TLargeIntBase::DivU(const TLargeIntBase& aDivisor, TLargeIntBase& aRem)
       
   219 	{
       
   220 	__ASSERT(aDivisor.iC==iC);
       
   221 	__ASSERT(aRem.iC==iC);
       
   222 	new (&aRem) TLargeIntBase(iC,TUint32(0u));
       
   223 	TInt i;
       
   224 	for (i=0; i<iC*32; ++i)
       
   225 		{
       
   226 		aRem.Lsl();
       
   227 		if (Lsl())
       
   228 			aRem.Inc();
       
   229 		if (aRem.Hs(aDivisor))
       
   230 			aRem.Sub(aDivisor), Inc();
       
   231 		}
       
   232 	}
       
   233 
       
   234 void TLargeIntBase::DivS(const TLargeIntBase& aDivisor, TLargeIntBase& aRem)
       
   235 	{
       
   236 	__ASSERT(aDivisor.iC==iC);
       
   237 	__ASSERT(aRem.iC==iC);
       
   238 	TUint32 temp[64];	// HACK!!
       
   239 	Mem::Copy(temp, &aDivisor, (iC+1)*sizeof(TUint32));
       
   240 	TLargeIntBase& divisor = *(TLargeIntBase*)temp;
       
   241 	TUint32 rs = iX[iC-1];
       
   242 	TUint32 qs = divisor.iX[iC-1] ^ rs;
       
   243 	Abs();
       
   244 	divisor.Abs();
       
   245 	DivU(divisor, aRem);
       
   246 	if (rs & 0x80000000u)
       
   247 		aRem.Neg();
       
   248 	if (qs & 0x80000000u)
       
   249 		Neg();
       
   250 	}
       
   251 
       
   252 TInt TLargeIntBase::CompareU(const TLargeIntBase& a) const
       
   253 	{
       
   254 	__ASSERT(a.iC==iC);
       
   255 	TInt i;
       
   256 	for (i=iC-1; i>=0; --i)
       
   257 		{
       
   258 		TUint32 x = iX[i];
       
   259 		TUint32 y = a.iX[i];
       
   260 		if (x>y)
       
   261 			return 1;
       
   262 		if (x<y)
       
   263 			return -1;
       
   264 		}
       
   265 	return 0;
       
   266 	}
       
   267 
       
   268 TInt TLargeIntBase::CompareS(const TLargeIntBase& a) const
       
   269 	{
       
   270 	__ASSERT(a.iC==iC);
       
   271 	TInt i;
       
   272 	TUint32 m = 0x80000000u;
       
   273 	for (i=iC-1; i>=0; --i)
       
   274 		{
       
   275 		TUint32 x = iX[i] ^ m;
       
   276 		TUint32 y = a.iX[i] ^ m;
       
   277 		m = 0;
       
   278 		if (x>y)
       
   279 			return 1;
       
   280 		if (x<y)
       
   281 			return -1;
       
   282 		}
       
   283 	return 0;
       
   284 	}
       
   285