Mono.Math.BigInteger.ModulusRing.BarrettReduction C# (CSharp) Method

BarrettReduction() public method

public BarrettReduction ( BigInteger x ) : void
x BigInteger
return void
			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);
			}