public static UInt64 Pack()

in csharp/EPAM.Deltix.DFP/DotNetImpl.cs [1949:2122]


		public static UInt64 Pack(bool isNegative, Int32 exponent, UInt64 coefficient, Int32 roundingMode)
		{
			UInt64 sgn = isNegative ? SignMask : 0;

			UInt64 Q_low_0, Q_low_1;
			UInt64 QH, r, mask, _C64, remainder_h;

			int extra_digits, amount, amount2;

			if (coefficient > 9999999999999999UL)
			{
				exponent++;
				coefficient = 1000000000000000UL;
			}

			// Check for possible underflow/overflow.
			if (exponent > BiasedExponentMaxValue || exponent < 0)
			{
				if (exponent < 0)
				{
					// Underflow.
					if (exponent + MaxFormatDigits < 0)
					{
						if (roundingMode == BidRoundingDown && isNegative)
							return 0x8000000000000001UL;
						if (roundingMode == BidRoundingUp && !isNegative)
							return 1L;
						return sgn;
					}

					if (isNegative && (roundingMode == BidRoundingDown || roundingMode == BidRoundingUp))
						roundingMode = 3 - roundingMode;

					// Get digits to be shifted out
					extra_digits = -exponent;
					coefficient += BidRoundConstTable[roundingMode, extra_digits];

					// Get coefficient * (2^M[extra_digits])/10^extra_digits
					{
						ulong ALBL_0, ALBL_1, ALBH_0, ALBH_1, QM2_0, QM2_1;
						{
							ulong CXH, CXL, CYH, CYL, PL, PH, PM, PM2;
							CXH = coefficient >> 32;
							CXL = (uint)((coefficient));
							CYH = BidReciprocals10_128[extra_digits, 1] >> 32;
							CYL = (uint)BidReciprocals10_128[extra_digits, 1];
							PM = CXH * CYL;
							PH = CXH * CYH;
							PL = CXL * CYL;
							PM2 = CXL * CYH;
							PH += (PM >> 32);
							PM = (PM & 0xFFFFFFFFL) + PM2 + (PL >> 32);
							ALBH_1 = PH + (PM >> 32);
							ALBH_0 = (PM << 32) + (uint)PL;
						}
						{
							ulong CXH, CXL, CYH, CYL, PL, PH, PM, PM2;
							CXH = ((coefficient)) >> 32;
							CXL = (uint)((coefficient));
							CYH = BidReciprocals10_128[extra_digits, 0] >> 32;
							CYL = (uint)BidReciprocals10_128[extra_digits, 0];
							PM = CXH * CYL;
							PH = CXH * CYH;
							PL = CXL * CYL;
							PM2 = CXL * CYH;
							PH += (PM >> 32);
							PM = (PM & 0xFFFFFFFFL) + PM2 + (PL >> 32);
							ALBL_1 = PH + (PM >> 32);
							ALBL_0 = (PM << 32) + (PL & 0xFFFFFFFFL);
						}
						Q_low_0 = ALBL_0;
						{
							ulong R64H;
							R64H = ALBH_1;
							QM2_0 = ALBL_1 + ALBH_0;
							if (QM2_0 < ALBL_1)
								R64H++;
							QM2_1 = R64H;
						}
						Q_low_1 = QM2_0;
						QH = QM2_1;
					}

					// Now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
					amount = BidRecipeScale[extra_digits];

					_C64 = QH >> amount;

					if (roundingMode == BidRoundingToNearest)
						if ((_C64 & 1) != 0)
						{
							// Check whether fractional part of initial_P/10^extra_digits is exactly .5
							// Get remainder
							amount2 = 64 - amount;
							remainder_h = 0;
							remainder_h--;
							remainder_h >>= amount2;
							remainder_h = remainder_h & QH;

							if (remainder_h == 0L
								&& (Q_low_1 < BidReciprocals10_128[extra_digits, 1]
								|| (Q_low_1 == BidReciprocals10_128[extra_digits, 1]
								&& Q_low_0 < BidReciprocals10_128[extra_digits, 0])))
							{
								_C64--;
							}
						}
					return sgn | _C64;
				}
				if (coefficient == 0L)
				{
					if (exponent > BiasedExponentMaxValue)
						exponent = BiasedExponentMaxValue;
				}
				while (coefficient < 1000000000000000L && exponent >= 3 * 256)
				{
					exponent--;
					coefficient = (coefficient << 3) + (coefficient << 1); // *= 10
				}
				if (exponent > BiasedExponentMaxValue)
				{
					// Overflow
					r = sgn | InfinityMask;
					if (roundingMode == BidRoundingDown)
					{
						if (!isNegative)
							r = MaxValue;
					}
					else
					if (roundingMode == BidRoundingToZero)
					{
						r = sgn | MaxValue;
					}
					else if (roundingMode == BidRoundingUp)
					{
						if (isNegative)
							r = MinValue;
					}
					return r;
				}
			}

			mask = 1;
			mask <<= ExponentShiftSmall;

			// Check whether coefficient fits in 10 * 5 + 3 bits.
			if (coefficient < mask)
			{
				r = (ulong)exponent;
				r <<= ExponentShiftSmall;
				r |= (coefficient | sgn);
				return r;
			}
			// Special format.

			// Eliminate the case coefficient == 10^16 after rounding.
			if (coefficient == 10000000000000000)
			{
				r = (ulong)(exponent + 1);
				r <<= ExponentShiftSmall;
				r |= (1000000000000000 | sgn);
				return r;
			}

			r = (ulong)exponent;
			r <<= ExponentShiftLarge;
			r |= (sgn | SpecialEncodingMask);

			// Add coefficient, without leading bits.
			mask = (mask >> 2) - 1;
			coefficient &= mask;
			r |= coefficient;
			return r;
		}