AdjustScale() public static method

public static AdjustScale ( SqlDecimal n, int digits, bool fRound ) : SqlDecimal
n SqlDecimal
digits int
fRound bool
return SqlDecimal
Esempio n. 1
0
        public static SqlBoolean operator <=(SqlDecimal x, SqlDecimal y)
        {
            if (x.IsNull || y.IsNull)
            {
                return(SqlBoolean.Null);
            }

            if (x.IsPositive != y.IsPositive)
            {
                return(new SqlBoolean(y.IsPositive));
            }

            if (x.Scale > y.Scale)
            {
                y = SqlDecimal.AdjustScale(y, x.Scale - y.Scale, true);
            }
            else if (y.Scale > x.Scale)
            {
                x = SqlDecimal.AdjustScale(x, y.Scale - x.Scale, true);
            }

            for (int i = 3; i >= 0; i -= 1)
            {
                if (x.Data[i] == 0 && y.Data[i] == 0)
                {
                    continue;
                }
                else
                {
                    return(new SqlBoolean(x.Data[i] <= y.Data[i]));
                }
            }
            return(new SqlBoolean(true));
        }
Esempio n. 2
0
        /// <summary>
        /// Initializes a new instance of the <see cref='SqlMoney'/> class with the value given.
        /// </summary>
        public SqlMoney(decimal value)
        {
            // Since Decimal is a value type, operate directly on value, don't worry about changing it.
            SqlDecimal snum = new SqlDecimal(value);

            snum.AdjustScale(s_iMoneyScale - snum.Scale, true);
            Debug.Assert(snum.Scale == s_iMoneyScale);

            if (snum._data3 != 0 || snum._data4 != 0)
            {
                throw new OverflowException(SQLResource.s_arithOverflowMessage);
            }

            bool  fPositive = snum.IsPositive;
            ulong ulValue   = snum._data1 + (((ulong)snum._data2) << 32);

            if (fPositive && ulValue > long.MaxValue ||
                !fPositive && ulValue > unchecked ((ulong)(long.MinValue)))
            {
                throw new OverflowException(SQLResource.s_arithOverflowMessage);
            }

            _value    = fPositive ? (long)ulValue : unchecked (-(long)ulValue);
            _fNotNull = true;
        }
Esempio n. 3
0
        public static SqlBoolean operator !=(SqlDecimal x, SqlDecimal y)
        {
            if (x.IsNull || y.IsNull)
            {
                return(SqlBoolean.Null);
            }

            if (x.IsPositive != y.IsPositive)
            {
                return(SqlBoolean.True);
            }

            if (x.Scale > y.Scale)
            {
                x = SqlDecimal.AdjustScale(x, y.Scale - x.Scale, true);
            }
            else if (y.Scale > x.Scale)
            {
                y = SqlDecimal.AdjustScale(y, x.Scale - y.Scale, true);
            }

            for (int i = 0; i < 4; i += 1)
            {
                if (x.Data[i] != y.Data[i])
                {
                    return(SqlBoolean.True);
                }
            }
            return(SqlBoolean.False);
        }
Esempio n. 4
0
        public static SqlDecimal operator *(SqlDecimal x, SqlDecimal y)
        {
            // adjust the scale to the smaller of the two beforehand
            if (x.Scale > y.Scale)
            {
                x = SqlDecimal.AdjustScale(x, y.Scale - x.Scale, true);
            }
            else if (y.Scale > x.Scale)
            {
                y = SqlDecimal.AdjustScale(y, x.Scale - y.Scale, true);
            }

            return(new SqlDecimal(x.Value * y.Value));
        }
 public SqlMoney(decimal value)
 {
     SqlDecimal num2 = new SqlDecimal(value);
     num2.AdjustScale(x_iMoneyScale - num2.Scale, true);
     if ((num2.m_data3 != 0) || (num2.m_data4 != 0))
     {
         throw new OverflowException(SQLResource.ArithOverflowMessage);
     }
     bool isPositive = num2.IsPositive;
     ulong num = num2.m_data1 + (num2.m_data2 << 0x20);
     if ((isPositive && (num > 0x7fffffffffffffffL)) || (!isPositive && (num > 9223372036854775808L)))
     {
         throw new OverflowException(SQLResource.ArithOverflowMessage);
     }
     this.m_value = isPositive ? ((long) num) : ((long) -num);
     this.m_fNotNull = true;
 }
Esempio n. 6
0
        /// <summary>
        /// Initializes a new instance of the <see cref='SqlMoney'/> class with the value given.
        /// </summary>
        public SqlMoney(decimal value)
        {
            // Since Decimal is a value type, operate directly on value, don't worry about changing it.
            SqlDecimal snum = new SqlDecimal(value);
            snum.AdjustScale(s_iMoneyScale - snum.Scale, true);
            Debug.Assert(snum.Scale == s_iMoneyScale);

            if (snum._data3 != 0 || snum._data4 != 0)
                throw new OverflowException(SQLResource.s_arithOverflowMessage);

            bool fPositive = snum.IsPositive;
            ulong ulValue = snum._data1 + (((ulong)snum._data2) << 32);
            if (fPositive && ulValue > long.MaxValue ||
                !fPositive && ulValue > unchecked((ulong)(long.MinValue)))
                throw new OverflowException(SQLResource.s_arithOverflowMessage);

            _value = fPositive ? (long)ulValue : unchecked(-(long)ulValue);
            _fNotNull = true;
        }
        public SqlMoney(decimal value)
        {
            SqlDecimal num2 = new SqlDecimal(value);

            num2.AdjustScale(x_iMoneyScale - num2.Scale, true);
            if ((num2.m_data3 != 0) || (num2.m_data4 != 0))
            {
                throw new OverflowException(SQLResource.ArithOverflowMessage);
            }
            bool  isPositive = num2.IsPositive;
            ulong num        = num2.m_data1 + (num2.m_data2 << 0x20);

            if ((isPositive && (num > 0x7fffffffffffffffL)) || (!isPositive && (num > 9223372036854775808L)))
            {
                throw new OverflowException(SQLResource.ArithOverflowMessage);
            }
            this.m_value    = isPositive ? ((long)num) : ((long)-num);
            this.m_fNotNull = true;
        }
Esempio n. 8
0
        // Power - Compute the power of a numeric
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static SqlDecimal Power(SqlDecimal n, double exp)
        {
            n.AssertValid();

            if (n.IsNull)
                return SqlDecimal.Null;

            byte prec = n.Precision;
            int scale = n.Scale;
            double dBaseNum = n.ToDouble();

            n = new SqlDecimal(Math.Pow(dBaseNum, exp));
            n.AdjustScale(scale - (int)n.Scale, true);

            n.m_bPrec = MaxPrecision;

            return n;
        }
Esempio n. 9
0
        //    MultNm()
        //
        //    Multiply two numerics.
        //
        //  Parameters:
        //        x    - IN Multiplier
        //        y    - IN Multiplicand
        //
        //    Result scale and precision(same as in SQL Server Manual and Hydra):
        //        scale = s1 + s2
        //        precision = s1 + s2 + (p1 - s1) + (p2 - s2) + 1
        //
        //    Overflow Rules:
        //        If scale is greater than NUMERIC_MAX_PRECISION it is set to
        //    NUMERIC_MAX_PRECISION.  If precision is greater than NUMERIC_MAX_PRECISION
        //    it is set to NUMERIC_MAX_PRECISION, then scale is reduced to keep the
        //    integer part untruncated but keeping a minimum value of x_cNumeDivScaleMin.
        //    For example, if using the above formula, the resulting precision is 46 and
        //    scale is 10, the precision will be reduced to 38. To keep the integral part
        //    untruncated the scale needs be reduced to 2, but since x_cNumeDivScaleMin
        //    is set to 6 currently, resulting scale will be 6.
        //        O_OVERFLOW is returned only if the actual precision is greater than
        //     NUMERIC_MAX_PRECISION or the actual length is greater than x_cbNumeBuf.
        //
        //    Algorithm:
        //        Starting from the lowest significant UI4, for each UI4 of the multiplier
        //    iterate through the UI4s of the multiplicand starting from
        //    the least significant UI4s, multiply the multiplier UI4 with
        //    multiplicand UI4, update the result buffer with the product modulo
        //    x_dwlBaseUI4 at the same index as the multiplicand, and carry the quotient to
        //    add to the next multiplicand UI4.  Until the end of the multiplier data
        //    array is reached.
        //
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public static SqlDecimal operator *(SqlDecimal x, SqlDecimal y)
        {
            x.AssertValid();
            y.AssertValid();

            if (x.IsNull || y.IsNull)
                return Null;

            //Implementation:
            //        I) Figure result scale,prec
            //        II) Perform mult.
            //        III) Adjust product to result scale,prec

            // Local variables for actual multiplication
            int iulPlier;           //index of UI4 in the Multiplier
            uint ulPlier;            //current multiplier UI4
            ulong dwlAccum;           //accumulated sum
            ulong dwlNextAccum;       //overflow of accumulated sum
            int culCand = y.m_bLen; //length of multiplicand in UI4s

            //Local variables to track scale,precision
            int ActualScale;                    // Scale after mult done
            int ResScale;                       // Final scale we will force result to
            int ResPrec;                        // Final precision we will force result to
            int ResInteger;                     // # of digits in integer part of result (prec-scale)
            int lScaleAdjust;   //How much result scale will be adjusted
            bool fResPositive;  // Result sign

            SqlDecimal ret;


            //I) Figure result prec,scale
            ActualScale = x.m_bScale + y.m_bScale;
            ResScale = ActualScale;
            ResInteger = (x.m_bPrec - x.m_bScale) + (y.m_bPrec - y.m_bScale) + 1;

            //result precision = s1 + s2 + (p1 - s1) + (p2 - s2) + 1
            ResPrec = ResScale + ResInteger;

            // Downward adjust res prec,scale if either larger than NUMERIC_MAX_PRECISION
            if (ResPrec > s_NUMERIC_MAX_PRECISION)
                ResPrec = s_NUMERIC_MAX_PRECISION;
            if (ResScale > s_NUMERIC_MAX_PRECISION)
                ResScale = s_NUMERIC_MAX_PRECISION;

            //
            // It is possible when two large numbers are being multiplied the scale
            // can be reduced to 0 to keep data untruncated; the fix here is to
            // preserve a minimum scale of 6.
            //
            // If overflow, reduce the scale to avoid truncation of data
            ResScale = Math.Min((ResPrec - ResInteger), ResScale);
            // But keep a minimum scale of NUMERIC_MIN_DVSCALE
            ResScale = Math.Max(ResScale, Math.Min(ActualScale, s_cNumeDivScaleMin));

            lScaleAdjust = ResScale - ActualScale;

            fResPositive = (x.IsPositive == y.IsPositive);//positive if both signs same.

            // II) Perform multiplication

            uint[] rglData1 = new uint[4] { x.m_data1, x.m_data2, x.m_data3, x.m_data4 };
            uint[] rglData2 = new uint[4] { y.m_data1, y.m_data2, y.m_data3, y.m_data4 };

            //Local buffer to hold the result of multiplication.
            //Longer than CReNumeBuf because full precision of multiplication is carried out
            const int x_culNumeMultRes = 9;       // Maximum # UI4s in result buffer in multiplication
            uint[] rgulRes = new uint[x_culNumeMultRes]; //new [] are already initialized to zero
            int culRes;             // # of UI4s in result
            int idRes = 0;

            //Iterate over the bytes of multiplier
            for (iulPlier = 0; iulPlier < x.m_bLen; iulPlier++)
            {
                ulPlier = rglData1[iulPlier];
                dwlAccum = 0;

                //Multiply each UI4 of multiCand by ulPliear and accumulate into result buffer

                // Start on correct place in result
                idRes = iulPlier;

                for (int iulCand = 0; iulCand < culCand; iulCand++)
                {
                    // dwlAccum = dwlAccum + rgulRes[idRes] + ulPlier*rglData2[iulCand]
                    //        use dwlNextAccum to detect overflow of DWORDLONG
                    dwlNextAccum = dwlAccum + rgulRes[idRes];
                    ulong ulTemp = (ulong)rglData2[iulCand];
                    dwlAccum = (ulong)ulPlier * ulTemp;
                    dwlAccum += dwlNextAccum;
                    if (dwlAccum < dwlNextAccum) // indicates dwl addition overflowed
                        dwlNextAccum = s_ulInt32Base; // = maxUI64/x_dwlBaseUI4
                    else
                        dwlNextAccum = 0;

                    // Update result and accum
                    rgulRes[idRes++] = (uint)(dwlAccum);// & x_ulInt32BaseForMod); // equiv to mod x_lInt32Base
                    dwlAccum = (dwlAccum >> 32) + dwlNextAccum; // equiv to div BaseUI4 + dwlNAccum

                    // dwlNextAccum can't overflow next iteration
                    Debug.Assert(dwlAccum < s_ulInt32Base * 2);
                }

                Debug.Assert(dwlAccum < s_ulInt32Base); // can never final accum > 1 more UI4
                if (dwlAccum != 0)
                    rgulRes[idRes++] = (uint)dwlAccum;
            }
            // Skip leading 0s (may exist if we are multiplying by 0)
            for (; (rgulRes[idRes] == 0) && (idRes > 0); idRes--)
                ;
            // Calculate actual result length
            culRes = idRes + 1;

            // III) Adjust precision,scale to result prec,scale
            if (lScaleAdjust != 0)
            {
                // If need to decrease scale
                if (lScaleAdjust < 0)
                {
                    Debug.Assert(s_NUMERIC_MAX_PRECISION == ResPrec);

                    // have to adjust - might yet end up fitting.
                    // Cannot call AdjustScale - number cannot fit in a numeric, so
                    // have to duplicate code here

                    uint ulRem;          //Remainder when downshifting
                    uint ulShiftBase;    //What to multiply by to effect scale adjust

                    do
                    {
                        if (lScaleAdjust <= -9)
                        {
                            ulShiftBase = s_rgulShiftBase[8];
                            lScaleAdjust += 9;
                        }
                        else
                        {
                            ulShiftBase = s_rgulShiftBase[-lScaleAdjust - 1];
                            lScaleAdjust = 0;
                        }
                        MpDiv1(rgulRes, ref culRes, ulShiftBase, out ulRem);
                    }
                    while (lScaleAdjust != 0);

                    // Still do not fit?
                    if (culRes > s_cNumeMax)
                        throw new OverflowException(SQLResource.ArithOverflowMessage);

                    for (idRes = culRes; idRes < s_cNumeMax; idRes++)
                        rgulRes[idRes] = 0;
                    ret = new SqlDecimal(rgulRes, (byte)culRes, (byte)ResPrec, (byte)ResScale, fResPositive);

                    // Is it greater than 10**38?
                    if (ret.FGt10_38())
                        throw new OverflowException(SQLResource.ArithOverflowMessage);

                    ret.AssertValid();

                    // If remainder is 5 or above, increment/decrement by 1.
                    if (ulRem >= ulShiftBase / 2)
                        ret.AddULong(1);
                    // After adjusting, if the result is 0 and remainder is less than 5,
                    // set the sign to be positive
                    if (ret.FZero())
                        ret.SetPositive();

                    return ret;
                }

                // Otherwise call AdjustScale
                if (culRes > s_cNumeMax)    // Do not fit now, so will not fit after adjustment
                    throw new OverflowException(SQLResource.ArithOverflowMessage);
                // NOTE: Have not check for value in the range (10**38..2**128),
                // as we'll call AdjustScale with positive argument, and it'll
                // return "normal" overflow

                for (idRes = culRes; idRes < s_cNumeMax; idRes++)
                    rgulRes[idRes] = 0;
                ret = new SqlDecimal(rgulRes, (byte)culRes, (byte)ResPrec, (byte)ActualScale, fResPositive);

                if (ret.FZero())
                    ret.SetPositive();

                ret.AssertValid();

                ret.AdjustScale(lScaleAdjust, true);

                return ret;
            }
            else
            {
                if (culRes > s_cNumeMax)
                    throw new OverflowException(SQLResource.ArithOverflowMessage);

                for (idRes = culRes; idRes < s_cNumeMax; idRes++)
                    rgulRes[idRes] = 0;
                ret = new SqlDecimal(rgulRes, (byte)culRes, (byte)ResPrec, (byte)ResScale, fResPositive);

                // Is it greater than 10**38?
                if (ret.FGt10_38())
                    throw new OverflowException(SQLResource.ArithOverflowMessage);

                if (ret.FZero())
                    ret.SetPositive();

                ret.AssertValid();

                return ret;
            }
        }
 public static SqlDecimal operator *(SqlDecimal x, SqlDecimal y)
 {
     SqlDecimal num11;
     if (x.IsNull || y.IsNull)
     {
         return Null;
     }
     int bLen = y.m_bLen;
     int num10 = x.m_bScale + y.m_bScale;
     int num3 = num10;
     int num13 = ((x.m_bPrec - x.m_bScale) + (y.m_bPrec - y.m_bScale)) + 1;
     int num6 = num3 + num13;
     if (num6 > NUMERIC_MAX_PRECISION)
     {
         num6 = NUMERIC_MAX_PRECISION;
     }
     if (num3 > NUMERIC_MAX_PRECISION)
     {
         num3 = NUMERIC_MAX_PRECISION;
     }
     num3 = Math.Max(Math.Min(num6 - num13, num3), Math.Min(num10, x_cNumeDivScaleMin));
     int digits = num3 - num10;
     bool fPositive = x.IsPositive == y.IsPositive;
     uint[] numArray5 = new uint[] { x.m_data1, x.m_data2, x.m_data3, x.m_data4 };
     uint[] numArray4 = new uint[] { y.m_data1, y.m_data2, y.m_data3, y.m_data4 };
     uint[] rgulU = new uint[9];
     int index = 0;
     for (int i = 0; i < x.m_bLen; i++)
     {
         uint num16 = numArray5[i];
         ulong num2 = 0L;
         index = i;
         for (int j = 0; j < bLen; j++)
         {
             ulong num7 = num2 + rgulU[index];
             ulong num15 = numArray4[j];
             num2 = num16 * num15;
             num2 += num7;
             if (num2 < num7)
             {
                 num7 = x_ulInt32Base;
             }
             else
             {
                 num7 = 0L;
             }
             rgulU[index++] = (uint) num2;
             num2 = (num2 >> 0x20) + num7;
         }
         if (num2 != 0L)
         {
             rgulU[index++] = (uint) num2;
         }
     }
     while ((rgulU[index] == 0) && (index > 0))
     {
         index--;
     }
     int ciulU = index + 1;
     if (digits != 0)
     {
         if (digits < 0)
         {
             uint num12;
             uint num14;
             do
             {
                 if (digits <= -9)
                 {
                     num12 = x_rgulShiftBase[8];
                     digits += 9;
                 }
                 else
                 {
                     num12 = x_rgulShiftBase[-digits - 1];
                     digits = 0;
                 }
                 MpDiv1(rgulU, ref ciulU, num12, out num14);
             }
             while (digits != 0);
             if (ciulU > x_cNumeMax)
             {
                 throw new OverflowException(SQLResource.ArithOverflowMessage);
             }
             for (index = ciulU; index < x_cNumeMax; index++)
             {
                 rgulU[index] = 0;
             }
             num11 = new SqlDecimal(rgulU, (byte) ciulU, (byte) num6, (byte) num3, fPositive);
             if (num11.FGt10_38())
             {
                 throw new OverflowException(SQLResource.ArithOverflowMessage);
             }
             if (num14 >= (num12 / 2))
             {
                 num11.AddULong(1);
             }
             if (num11.FZero())
             {
                 num11.SetPositive();
             }
             return num11;
         }
         if (ciulU > x_cNumeMax)
         {
             throw new OverflowException(SQLResource.ArithOverflowMessage);
         }
         for (index = ciulU; index < x_cNumeMax; index++)
         {
             rgulU[index] = 0;
         }
         num11 = new SqlDecimal(rgulU, (byte) ciulU, (byte) num6, (byte) num10, fPositive);
         if (num11.FZero())
         {
             num11.SetPositive();
         }
         num11.AdjustScale(digits, true);
         return num11;
     }
     if (ciulU > x_cNumeMax)
     {
         throw new OverflowException(SQLResource.ArithOverflowMessage);
     }
     for (index = ciulU; index < x_cNumeMax; index++)
     {
         rgulU[index] = 0;
     }
     num11 = new SqlDecimal(rgulU, (byte) ciulU, (byte) num6, (byte) num3, fPositive);
     if (num11.FGt10_38())
     {
         throw new OverflowException(SQLResource.ArithOverflowMessage);
     }
     if (num11.FZero())
     {
         num11.SetPositive();
     }
     return num11;
 }
 public static SqlDecimal Power(SqlDecimal n, double exp)
 {
     if (n.IsNull)
     {
         return Null;
     }
     byte precision = n.Precision;
     int scale = n.Scale;
     double x = n.ToDouble();
     n = new SqlDecimal(Math.Pow(x, exp));
     n.AdjustScale(scale - n.Scale, true);
     n.m_bPrec = MaxPrecision;
     return n;
 }
Esempio n. 12
0
        public static SqlDecimal operator -(SqlDecimal x, SqlDecimal y)
        {
            if (x.IsNull || y.IsNull)
            {
                return(SqlDecimal.Null);
            }

            if (x.IsPositive && !y.IsPositive)
            {
                y = new SqlDecimal(y.Precision, y.Scale, !y.IsPositive, y.Data);
                return(x + y);
            }
            if (!x.IsPositive && y.IsPositive)
            {
                x = new SqlDecimal(x.Precision, x.Scale, !x.IsPositive, x.Data);
                x = (x + y);
                return(new SqlDecimal(x.Precision, x.Scale, false, x.Data));
            }
            if (!x.IsPositive && !y.IsPositive)
            {
                y = new SqlDecimal(y.Precision, y.Scale, !y.IsPositive, y.Data);
                x = new SqlDecimal(x.Precision, x.Scale, !x.IsPositive, x.Data);
                return(y - x);
            }
            // adjust the scale to the larger of the two beforehand
            if (x.scale > y.scale)
            {
                y = SqlDecimal.AdjustScale(y, x.scale - y.scale, false);
            }
            else if (y.scale > x.scale)
            {
                x = SqlDecimal.AdjustScale(x, y.scale - x.scale, false);
            }

            //calculation of the new Precision for the result
            byte resultPrecision = (byte)(Math.Max(x.Scale, y.Scale) +
                                          Math.Max(x.Precision - x.Scale, y.Precision - y.Scale));

            int[] op1_Data;
            int[] op2_Data;
            if (x >= y)
            {
                op1_Data = x.Data;
                op2_Data = y.Data;
            }
            else
            {
                op1_Data = y.Data;
                op2_Data = x.Data;
            }

            ulong res   = 0;
            int   carry = 0;

            int[] resultBits = new int[4];


            /*
             * if ((uint)op2_Data [i] > (uint)op1_Data [i]) {
             *       carry = UInt32.MaxValue;
             *       op2_Data [i] = op2_Data [i] >> 1;
             * } else
             *       carr = 0;
             *      res = (uint)carry; +(ulong)((uint)op1_Data [i]) - (ulong)((uint)op2_Data [i])
             */

            for (int i = 0; i < 4; i += 1)
            {
                res   = (ulong)((uint)op1_Data [i]) - (ulong)((uint)op2_Data [i]) + (ulong)carry;
                carry = 0;
                if ((uint)op2_Data [i] > (uint)op1_Data [i])
                {
                    carry = -1;
                }
                resultBits [i] = (int)res;
            }

            if (carry > 0)
            {
                throw new OverflowException();
            }
            else
            {
                return(new SqlDecimal(resultPrecision, x.Scale, (x >= y).Value, resultBits));
            }
        }
Esempio n. 13
0
        public static SqlDecimal operator +(SqlDecimal x, SqlDecimal y)
        {
            if (x.IsNull || y.IsNull)
            {
                return(SqlDecimal.Null);
            }
            //if one of them is negative, perform subtraction
            if (x.IsPositive && !y.IsPositive)
            {
                y = new SqlDecimal(y.Precision, y.Scale, !y.IsPositive, y.Data);
                return(x - y);
            }
            if (!x.IsPositive && y.IsPositive)
            {
                x = new SqlDecimal(x.Precision, x.Scale, !x.IsPositive, x.Data);
                return(y - x);
            }
            if (!x.IsPositive && !y.IsPositive)
            {
                x = new SqlDecimal(x.Precision, x.Scale, !x.IsPositive, x.Data);
                y = new SqlDecimal(y.Precision, y.Scale, !y.IsPositive, y.Data);
                x = (x + y);
                return(new SqlDecimal(x.Precision, x.Scale, !x.IsPositive, x.Data));
            }
            // adjust the scale to the larger of the two beforehand
            if (x.scale > y.scale)
            {
                y = SqlDecimal.AdjustScale(y, x.scale - y.scale, false);
            }
            else if (y.scale > x.scale)
            {
                x = SqlDecimal.AdjustScale(x, y.scale - x.scale, false);
            }

            byte resultPrecision = (byte)(Math.Max(x.Scale, y.Scale) +
                                          Math.Max(x.Precision - x.Scale, y.Precision - y.Scale) + 1);

            if (resultPrecision > MaxPrecision)
            {
                resultPrecision = MaxPrecision;
            }

            int [] xData      = x.Data;
            int [] yData      = y.Data;
            int [] resultBits = new int[4];
            ulong  carry      = 0;
            ulong  res        = 0;

            for (int i = 0; i < 4; i++)
            {
                res            = (ulong)((uint)xData [i]) + (ulong)((uint)yData [i]) + carry;
                resultBits [i] = (int)(res & (UInt32.MaxValue));
                carry          = res >> 32;
            }

            if (carry > 0)
            {
                throw new OverflowException();
            }
            else
            {
                return(new SqlDecimal(resultPrecision, x.Scale, x.IsPositive, resultBits));
            }
        }