Normalize() private method

Normalizes this by setting the length to the actual number of uints used in data and by setting the sign to Sign.Zero if the value of this is 0.
private Normalize ( ) : void
return void
示例#1
0
			public void BarrettReduction (BigInteger x)
			{
				BigInteger n = mod;
				uint k = n.length,
					kPlusOne = k+1,
					kMinusOne = k-1;

				// x < mod, so nothing to do.
				if (x.length < k) return;

				BigInteger q3;

				//
				// Validate pointers
				//
				if (x.data.Length < x.length) throw new IndexOutOfRangeException ("x out of range");

				// q1 = x / b^ (k-1)
				// q2 = q1 * constant
				// q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne

				// TODO: We should the method in HAC p 604 to do this (14.45)
				q3 = new BigInteger (Sign.Positive, x.length - kMinusOne + constant.length);
				Kernel.Multiply (x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);

				// r1 = x mod b^ (k+1)
				// i.e. keep the lowest (k+1) words

				uint lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;

				x.length = lengthToCopy;
				x.Normalize ();

				// r2 = (q3 * n) mod b^ (k+1)
				// partial multiplication of q3 and n

				BigInteger r2 = new BigInteger (Sign.Positive, kPlusOne);
				Kernel.MultiplyMod2p32pmod (q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);

				r2.Normalize ();

				if (r2 <= x) {
					Kernel.MinusEq (x, r2);
				} else {
					BigInteger val = new BigInteger (Sign.Positive, kPlusOne + 1);
					val.data [kPlusOne] = 0x00000001;

					Kernel.MinusEq (val, r2);
					Kernel.PlusEq (x, val);
				}

				while (x >= n)
					Kernel.MinusEq (x, n);
			}
示例#2
0
		public static BigInteger operator * (BigInteger bi1, BigInteger bi2)
		{
			if (bi1 == 0 || bi2 == 0) return 0;

			//
			// Validate pointers
			//
			if (bi1.data.Length < bi1.length) throw new IndexOutOfRangeException ("bi1 out of range");
			if (bi2.data.Length < bi2.length) throw new IndexOutOfRangeException ("bi2 out of range");

			BigInteger ret = new BigInteger (Sign.Positive, bi1.length + bi2.length);

			Kernel.Multiply (bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);

			ret.Normalize ();
			return ret;
		}
示例#3
0
		/// <summary>
		/// Generates a new, random BigInteger of the specified length.
		/// </summary>
		/// <param name="bits">The number of bits for the new number.</param>
		/// <param name="rng">A random number generator to use to obtain the bits.</param>
		/// <returns>A random number of the specified length.</returns>
		public static BigInteger GenerateRandom (int bits, RandomNumberGenerator rng)
		{
			int dwords = bits >> 5;
			int remBits = bits & 0x1F;

			if (remBits != 0)
				dwords++;

			BigInteger ret = new BigInteger (Sign.Positive, (uint)dwords + 1);
			byte [] random = new byte [dwords << 2];

			rng.GetBytes (random);
			Buffer.BlockCopy (random, 0, ret.data, 0, (int)dwords << 2);

			if (remBits != 0) {
				uint mask = (uint)(0x01 << (remBits-1));
				ret.data [dwords-1] |= mask;

				mask = (uint)(0xFFFFFFFF >> (32 - remBits));
				ret.data [dwords-1] &= mask;
			}
			else
				ret.data [dwords-1] |= 0x80000000;

			ret.Normalize ();
			return ret;
		}
示例#4
0
			public static BigInteger RightShift (BigInteger bi, int n)
			{
				if (n == 0) return new BigInteger (bi);

				int w = n >> 5;
				int s = n & ((1 << 5) - 1);

				BigInteger ret = new BigInteger (Sign.Positive, bi.length - (uint)w + 1);
				uint l = (uint)ret.data.Length - 1;

				if (s != 0) {

					uint x, carry = 0;

					while (l-- > 0) {
						x = bi.data [l + w];
						ret.data [l] = (x >> n) | carry;
						carry = x << (32 - n);
					}
				} else {
					while (l-- > 0)
						ret.data [l] = bi.data [l + w];

				}
				ret.Normalize ();
				return ret;
			}
示例#5
0
			public static BigInteger MultiplyByDword (BigInteger n, uint f)
			{
				BigInteger ret = new BigInteger (Sign.Positive, n.length + 1);

				uint i = 0;
				ulong c = 0;

				do {
					c += (ulong)n.data [i] * (ulong)f;
					ret.data [i] = (uint)c;
					c >>= 32;
				} while (++i < n.length);
				ret.data [i] = (uint)c;
				ret.Normalize ();
				return ret;

			}
示例#6
0
			public static BigInteger [] multiByteDivide (BigInteger bi1, BigInteger bi2)
			{
				if (Kernel.Compare (bi1, bi2) == Sign.Negative)
					return new BigInteger [2] { 0, new BigInteger (bi1) };

				bi1.Normalize (); bi2.Normalize ();

				if (bi2.length == 1)
					return DwordDivMod (bi1, bi2.data [0]);

				uint remainderLen = bi1.length + 1;
				int divisorLen = (int)bi2.length + 1;

				uint mask = 0x80000000;
				uint val = bi2.data [bi2.length - 1];
				int shift = 0;
				int resultPos = (int)bi1.length - (int)bi2.length;

				while (mask != 0 && (val & mask) == 0) {
					shift++; mask >>= 1;
				}

				BigInteger quot = new BigInteger (Sign.Positive, bi1.length - bi2.length + 1);
				BigInteger rem = (bi1 << shift);

				uint [] remainder = rem.data;

				bi2 = bi2 << shift;

				int j = (int)(remainderLen - bi2.length);
				int pos = (int)remainderLen - 1;

				uint firstDivisorByte = bi2.data [bi2.length-1];
				ulong secondDivisorByte = bi2.data [bi2.length-2];

				while (j > 0) {
					ulong dividend = ((ulong)remainder [pos] << 32) + (ulong)remainder [pos-1];

					ulong q_hat = dividend / (ulong)firstDivisorByte;
					ulong r_hat = dividend % (ulong)firstDivisorByte;

					do {

						if (q_hat == 0x100000000 ||
							(q_hat * secondDivisorByte) > ((r_hat << 32) + remainder [pos-2])) {
							q_hat--;
							r_hat += (ulong)firstDivisorByte;

							if (r_hat < 0x100000000)
								continue;
						}
						break;
					} while (true);

					//
					// At this point, q_hat is either exact, or one too large
					// (more likely to be exact) so, we attempt to multiply the
					// divisor by q_hat, if we get a borrow, we just subtract
					// one from q_hat and add the divisor back.
					//

					uint t;
					uint dPos = 0;
					int nPos = pos - divisorLen + 1;
					ulong mc = 0;
					uint uint_q_hat = (uint)q_hat;
					do {
						mc += (ulong)bi2.data [dPos] * (ulong)uint_q_hat;
						t = remainder [nPos];
						remainder [nPos] -= (uint)mc;
						mc >>= 32;
						if (remainder [nPos] > t) mc++;
						dPos++; nPos++;
					} while (dPos < divisorLen);

					nPos = pos - divisorLen + 1;
					dPos = 0;

					// Overestimate
					if (mc != 0) {
						uint_q_hat--;
						ulong sum = 0;

						do {
							sum = ((ulong)remainder [nPos]) + ((ulong)bi2.data [dPos]) + sum;
							remainder [nPos] = (uint)sum;
							sum >>= 32;
							dPos++; nPos++;
						} while (dPos < divisorLen);

					}

					quot.data [resultPos--] = (uint)uint_q_hat;

					pos--;
					j--;
				}

				quot.Normalize ();
				rem.Normalize ();
				BigInteger [] ret = new BigInteger [2] { quot, rem };

				if (shift != 0)
					ret [1] >>= shift;

				return ret;
			}
示例#7
0
			public static BigInteger LeftShift (BigInteger bi, int n)
			{
				if (n == 0) return new BigInteger (bi, bi.length + 1);

				int w = n >> 5;
				n &= ((1 << 5) - 1);

				BigInteger ret = new BigInteger (Sign.Positive, bi.length + 1 + (uint)w);

				uint i = 0, l = bi.length;
				if (n != 0) {
					uint x, carry = 0;
					while (i < l) {
						x = bi.data [i];
						ret.data [i + w] = (x << n) | carry;
						carry = x >> (32 - n);
						i++;
					}
					ret.data [i + w] = carry;
				} else {
					while (i < l) {
						ret.data [i + w] = bi.data [i];
						i++;
					}
				}

				ret.Normalize ();
				return ret;
			}
示例#8
0
			/// <summary>
			/// Performs n / d and n % d in one operation.
			/// </summary>
			/// <param name="n">A BigInteger, upon exit this will hold n / d</param>
			/// <param name="d">The divisor</param>
			/// <returns>n % d</returns>
			public static uint SingleByteDivideInPlace (BigInteger n, uint d)
			{
				ulong r = 0;
				uint i = n.length;

				while (i-- > 0) {
					r <<= 32;
					r |= n.data [i];
					n.data [i] = (uint)(r / d);
					r %= d;
				}
				n.Normalize ();

				return (uint)r;
			}
示例#9
0
			public static BigInteger [] DwordDivMod (BigInteger n, uint d)
			{
				BigInteger ret = new BigInteger (Sign.Positive , n.length);

				ulong r = 0;
				uint i = n.length;

				while (i-- > 0) {
					r <<= 32;
					r |= n.data [i];
					ret.data [i] = (uint)(r / d);
					r %= d;
				}
				ret.Normalize ();

				BigInteger rem = (uint)r;

				return new BigInteger [] {ret, rem};
			}
示例#10
0
			public static void PlusEq (BigInteger bi1, BigInteger bi2)
			{
				uint [] x, y;
				uint yMax, xMax, i = 0;
				bool flag = false;

				// x should be bigger
				if (bi1.length < bi2.length){
					flag = true;
					x = bi2.data;
					xMax = bi2.length;
					y = bi1.data;
					yMax = bi1.length;
				} else {
					x = bi1.data;
					xMax = bi1.length;
					y = bi2.data;
					yMax = bi2.length;
				}

				uint [] r = bi1.data;

				ulong sum = 0;

				// Add common parts of both numbers
				do {
					sum += ((ulong)x [i]) + ((ulong)y [i]);
					r [i] = (uint)sum;
					sum >>= 32;
				} while (++i < yMax);

				// Copy remainder of longer number while carry propagation is required
				bool carry = (sum != 0);

				if (carry){

					if (i < xMax) {
						do
							carry = ((r [i] = x [i] + 1) == 0);
						while (++i < xMax && carry);
					}

					if (carry) {
						r [i] = 1;
						bi1.length = ++i;
						return;
					}
				}

				// Copy the rest
				if (flag && i < xMax - 1) {
					do
						r [i] = x [i];
					while (++i < xMax);
				}

				bi1.length = xMax + 1;
				bi1.Normalize ();
			}
示例#11
0
			public static BigInteger Subtract (BigInteger big, BigInteger small)
			{
				BigInteger result = new BigInteger (Sign.Positive, big.length);

				uint [] r = result.data, b = big.data, s = small.data;
				uint i = 0, c = 0;

				do {

					uint x = s [i];
					if (((x += c) < c) | ((r [i] = b [i] - x) > ~x))
						c = 1;
					else
						c = 0;

				} while (++i < small.length);

				if (i == big.length) goto fixup;

				if (c == 1) {
					do
						r [i] = b [i] - 1;
					while (b [i++] == 0 && i < big.length);

					if (i == big.length) goto fixup;
				}

				do
					r [i] = b [i];
				while (++i < big.length);

				fixup:

					result.Normalize ();
				return result;
			}
示例#12
0
			/// <summary>
			/// Adds two numbers with the same sign.
			/// </summary>
			/// <param name="bi1">A BigInteger</param>
			/// <param name="bi2">A BigInteger</param>
			/// <returns>bi1 + bi2</returns>
			public static BigInteger AddSameSign (BigInteger bi1, BigInteger bi2)
			{
				uint [] x, y;
				uint yMax, xMax, i = 0;

				// x should be bigger
				if (bi1.length < bi2.length) {
					x = bi2.data;
					xMax = bi2.length;
					y = bi1.data;
					yMax = bi1.length;
				} else {
					x = bi1.data;
					xMax = bi1.length;
					y = bi2.data;
					yMax = bi2.length;
				}
				
				BigInteger result = new BigInteger (Sign.Positive, xMax + 1);

				uint [] r = result.data;

				ulong sum = 0;

				// Add common parts of both numbers
				do {
					sum = ((ulong)x [i]) + ((ulong)y [i]) + sum;
					r [i] = (uint)sum;
					sum >>= 32;
				} while (++i < yMax);

				// Copy remainder of longer number while carry propagation is required
				bool carry = (sum != 0);

				if (carry) {

					if (i < xMax) {
						do
							carry = ((r [i] = x [i] + 1) == 0);
						while (++i < xMax && carry);
					}

					if (carry) {
						r [i] = 1;
						result.length = ++i;
						return result;
					}
				}

				// Copy the rest
				if (i < xMax) {
					do
						r [i] = x [i];
					while (++i < xMax);
				}

				result.Normalize ();
				return result;
			}
示例#13
0
/* known to be buggy in some cases */
#if false
			private unsafe BigInteger EvenModTwoPow (BigInteger exp)
			{
				exp.Normalize ();
				uint [] wkspace = new uint [mod.length << 1 + 1];

				BigInteger resultNum = new BigInteger (2, mod.length << 1 +1);

				uint value = exp.data [exp.length - 1];
				uint mask = 0x80000000;

				// Find the first bit of the exponent
				while ((value & mask) == 0)
					mask >>= 1;

				//
				// We know that the first itr will make the val 2,
				// so eat one bit of the exponent
				//
				mask >>= 1;

				uint wPos = exp.length - 1;

				do {
					value = exp.data [wPos];
					do {
						Kernel.SquarePositive (resultNum, ref wkspace);
						if (resultNum.length >= mod.length)
							BarrettReduction (resultNum);

						if ((value & mask) != 0) {
							//
							// resultNum = (resultNum * 2) % mod
							//

							fixed (uint* u = resultNum.data) {
								//
								// Double
								//
								uint* uu = u;
								uint* uuE = u + resultNum.length;
								uint x, carry = 0;
								while (uu < uuE) {
									x = *uu;
									*uu = (x << 1) | carry;
									carry = x >> (32 - 1);
									uu++;
								}

								// subtraction inlined because we know it is square
								if (carry != 0 || resultNum >= mod) {
									uu = u;
									uint c = 0;
									uint [] s = mod.data;
									uint i = 0;
									do {
										uint a = s [i];
										if (((a += c) < c) | ((* (uu++) -= a) > ~a))
											c = 1;
										else
											c = 0;
										i++;
									} while (uu < uuE);
								}
							}
						}
					} while ((mask >>= 1) > 0);
					mask = 0x80000000;
				} while (wPos-- > 0);

				return resultNum;
			}
示例#14
0
			private unsafe BigInteger EvenPow (uint b, BigInteger exp)
			{
				exp.Normalize ();
				uint [] wkspace = new uint [mod.length << 1 + 1];
				BigInteger resultNum = new BigInteger ((BigInteger)b, mod.length << 1 + 1);

				uint pos = (uint)exp.BitCount () - 2;

				//
				// We know that the first itr will make the val b
				//

				do {
					//
					// r = r ^ 2 % m
					//
					Kernel.SquarePositive (resultNum, ref wkspace);
					if (!(resultNum.length < mod.length))
						BarrettReduction (resultNum);

					if (exp.TestBit (pos)) {

						//
						// r = r * b % m
						//

						// TODO: Is Unsafe really speeding things up?
						fixed (uint* u = resultNum.data) {

							uint i = 0;
							ulong mc = 0;

							do {
								mc += (ulong)u [i] * (ulong)b;
								u [i] = (uint)mc;
								mc >>= 32;
							} while (++i < resultNum.length);

							if (resultNum.length < mod.length) {
								if (mc != 0) {
									u [i] = (uint)mc;
									resultNum.length++;
									while (resultNum >= mod)
										Kernel.MinusEq (resultNum, mod);
								}
							} else if (mc != 0) {

								//
								// First, we estimate the quotient by dividing
								// the first part of each of the numbers. Then
								// we correct this, if necessary, with a subtraction.
								//

								uint cc = (uint)mc;

								// We would rather have this estimate overshoot,
								// so we add one to the divisor
								uint divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
									(mod.data [mod.length-1] + 1));

								uint t;

								i = 0;
								mc = 0;
								do {
									mc += (ulong)mod.data [i] * (ulong)divEstimate;
									t = u [i];
									u [i] -= (uint)mc;
									mc >>= 32;
									if (u [i] > t) mc++;
									i++;
								} while (i < resultNum.length);
								cc -= (uint)mc;

								if (cc != 0) {

									uint sc = 0, j = 0;
									uint [] s = mod.data;
									do {
										uint a = s [j];
										if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
										else sc = 0;
										j++;
									} while (j < resultNum.length);
									cc -= sc;
								}
								while (resultNum >= mod)
									Kernel.MinusEq (resultNum, mod);
							} else {
								while (resultNum >= mod)
									Kernel.MinusEq (resultNum, mod);
							}
						}
					}
				} while (pos-- > 0);

				return resultNum;
			}