os/kernelhwsrv/kerneltest/e32test/math/largeint.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-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