public static UInt64 Round()

in csharp/EPAM.Deltix.DFP/DotNetImpl.cs [408:536]


		public static UInt64 Round(UInt64 value, int n, RoundingMode roundType)
		{
			if (!IsFinite(value))
				return value;
			if (n > MaxExponent)
				return value;
			if (n < MinExponent)
				return Zero;

			BID_UINT64 partsSignMask;
			int partsExponent;
			BID_UINT64 partsCoefficient;
			// DotNetReImpl.unpack_BID64(out partsSignMask, out partsExponent, out partsCoefficient, value);
			{ // Copy-paste the toParts method for speedup
				partsSignMask = value & 0x8000000000000000UL;

				if ((value & DotNetReImpl.SPECIAL_ENCODING_MASK64) == DotNetReImpl.SPECIAL_ENCODING_MASK64)
				{
					//if ((value & DotNetReImpl.INFINITY_MASK64) == DotNetReImpl.INFINITY_MASK64) - Non finite values are already checked
					//{
					//	partsExponent = 0;
					//	partsCoefficient = value & 0xfe03ffffffffffffUL;
					//	if ((value & 0x0003ffffffffffffUL) >= 1000000000000000UL)
					//		partsCoefficient = value & 0xfe00000000000000UL;
					//	if ((value & DotNetReImpl.NAN_MASK64) == DotNetReImpl.INFINITY_MASK64)
					//		partsCoefficient = value & DotNetReImpl.SINFINITY_MASK64;
					//	return 0;   // NaN or Infinity
					//} else
					{
						// Check for non-canonical values.
						BID_UINT64 coeff = (value & DotNetReImpl.LARGE_COEFF_MASK64) | DotNetReImpl.LARGE_COEFF_HIGH_BIT64;

						// check for non-canonical values
						if (coeff >= 10000000000000000UL)
							coeff = 0;
						partsCoefficient = coeff;
						// get exponent
						BID_UINT64 tmp = value >> DotNetReImpl.EXPONENT_SHIFT_LARGE64;
						partsExponent = (int)(tmp & DotNetReImpl.EXPONENT_MASK64);
					}
				}
				else
				{
					// exponent
					BID_UINT64 tmp = value >> DotNetReImpl.EXPONENT_SHIFT_SMALL64;
					partsExponent = (int)(tmp & DotNetReImpl.EXPONENT_MASK64);
					// coefficient
					partsCoefficient = (value & DotNetReImpl.SMALL_COEFF_MASK64);
				}
			}

			if (partsCoefficient == 0)
				return Zero;

			int exponent = partsExponent - DotNetReImpl.DECIMAL_EXPONENT_BIAS + n;

			if (exponent >= 0) // value is already rounded
				return value;
			// All next - negative exponent case

			BID_UINT64 divFactor;
			int addExponent = 0;
			{ // Truncate all digits except last one
				int absPower = -exponent;
				if (absPower >= MaxFormatDigits)
				{
					divFactor = MaxCoefficient + 1;
					int expShift = MaxFormatDigits;
					addExponent = absPower - expShift;

				}
				else
				{
					divFactor = PowersOfTen[absPower];
				}
			}

			// Process last digit
			switch (roundType)
			{
				case RoundingMode.Up:
					partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor - 1) / divFactor) * divFactor : divFactor;
					break;

				case RoundingMode.Down:
					partsCoefficient = addExponent == 0 ? (partsCoefficient / divFactor) * divFactor : 0;
					break;

				case RoundingMode.Ceiling:
					if (partsSignMask == 0/*!parts.isNegative()*/)
						partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor - 1) / divFactor) * divFactor : divFactor;
					else
						partsCoefficient = addExponent == 0 ? (partsCoefficient / divFactor) * divFactor : 0;
					break;

				case RoundingMode.Floor:
					if (partsSignMask == 0/*!parts.isNegative()*/)
						partsCoefficient = addExponent == 0 ? (partsCoefficient / divFactor) * divFactor : 0;
					else
						partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor - 1) / divFactor) * divFactor : divFactor;
					break;

				case RoundingMode.HalfUp:
					partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor / 2) / divFactor) * divFactor : 0;
					break;

				case RoundingMode.HalfDown:
					partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor / 2 - 1) / divFactor) * divFactor : 0;
					break;

				case RoundingMode.HalfEven:
					partsCoefficient = addExponent == 0 ? ((partsCoefficient + divFactor / 2 - 1 + ((partsCoefficient / divFactor) & 1L)) / divFactor) * divFactor : 0;
					break;

				case RoundingMode.Unnecessary:
					if (addExponent != 0 /*&& partsCoefficient != 0 - always true: checked earlier*/ || partsCoefficient % divFactor != 0)
						throw new ArithmeticException("Rounding necessary");
					return value;

				default:
					throw new ArgumentException("Unsupported roundType(=" + roundType + ") value.");
			}
			partsExponent += addExponent;
			if (partsCoefficient == 0)
				return Zero;

			BID_UINT32 fpsf = DotNetReImpl.BID_EXACT_STATUS;
			return DotNetReImpl.get_BID64(partsSignMask, partsExponent, partsCoefficient, DotNetReImpl.BID_ROUNDING_TO_NEAREST, ref fpsf);
		}