public static SqlBoolean LessThan(SqlDecimal x, SqlDecimal y)
 {
     return(x < y);
 }
 public static SqlDecimal Divide(SqlDecimal x, SqlDecimal y)
 {
     return(x / y);
 }
 public static SqlBoolean GreaterThan(SqlDecimal x, SqlDecimal y)
 {
     return(x > y);
 }
        // From decimal.c
        private static void DecimalDivSub(ref SqlDecimal x, ref SqlDecimal y, ref ulong clo, ref ulong chi, ref int exp)
        {
            ulong xlo, xmi, xhi;
            ulong tlo = 0;
            ulong tmi = 0;
            ulong thi = 0;
            ;
            uint ylo = 0;
            uint ymi = 0;
            uint ymi2 = 0;
            uint yhi = 0;
            int ashift = 0;
            int bshift = 0;
            int extraBit = 0;

            xhi = ((ulong) x.Data[3] << 32) | (ulong) x.Data[2];
            xmi = ((ulong) x.Data[1] << 32) | (ulong) x.Data[0];
            xlo = 0;
            ylo = (uint) y.Data[0];
            ymi = (uint) y.Data[1];
            ymi2 = (uint) y.Data[2];
            yhi = (uint) y.Data[3];

            if (ylo == 0 && ymi == 0 && ymi2 == 0 && yhi == 0)
            {
                throw new DivideByZeroException();
            }

            if (xmi == 0 && xhi == 0)
            {
                clo = chi = 0;
                return;
            }

            // enlarge dividend to get maximal precision
            for (ashift = 0; (xhi & LIT_GUINT64_HIGHBIT) == 0; ++ashift)
            {
                LShift128(ref xmi, ref xhi);
            }

            // ensure that divisor is at least 2^95 
            for (bshift = 0; (yhi & LIT_GUINT32_HIGHBIT) == 0; ++bshift)
            {
                LShift128(ref ylo, ref ymi, ref ymi2, ref yhi);
            }

            thi = ((ulong) yhi) << 32 | ymi2;
            tmi = ((ulong) ymi) << 32 | ylo;
            tlo = 0;

            if (xhi > thi || (xhi == thi && xmi >= tmi))
            {
                Sub192(xlo, xmi, xhi, tlo, tmi, thi, ref xlo, ref xmi, ref xhi);
                extraBit = 1;
            }
            else
            {
                extraBit = 0;
            }

            Div192By128To128(xlo, xmi, xhi, ylo, ymi, ymi2, yhi, ref clo, ref chi);

            exp = 128 + ashift - bshift;

            if (extraBit != 0)
            {
                RShift128(ref clo, ref chi);
                chi += LIT_GUINT64_HIGHBIT;
                exp--;
            }

            // try loss free right shift
            while (exp > 0 && (clo & 1) == 0)
            {
                RShift128(ref clo, ref chi);
                exp--;
            }
        }
        public static SqlDecimal operator -(SqlDecimal x, SqlDecimal y)
        {
            if (x.IsNull || y.IsNull)
            {
                return(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 = AdjustScale(y, x.scale - y.scale, false);
            }
            else if (y.scale > x.scale)
            {
                x = AdjustScale(x, y.scale - x.scale, false);
            }

            //calculation of the new Precision for the result
            var 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;
            var   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   = ((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));
            }
        }
        public static SqlDecimal operator +(SqlDecimal x, SqlDecimal y)
        {
            if (x.IsNull || y.IsNull)
            {
                return 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 = AdjustScale(y, x.scale - y.scale, false);
            }
            else if (y.scale > x.scale)
            {
                x = AdjustScale(x, y.scale - x.scale, false);
            }

            var 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;
            var resultBits = new int[4];
            ulong carry = 0;
            ulong res = 0;
            for (int i = 0; i < 4; i++)
            {
                res = ((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);
            }
        }
 public static SqlDecimal Subtract(SqlDecimal x, SqlDecimal y)
 {
     return (x - y);
 }
 public int CompareTo(SqlDecimal value)
 {
     if (value.IsNull)
     {
         return 1;
     }
     else
     {
         return this.Value.CompareTo(value.Value);
     }
 }
 public static SqlDecimal ConvertToPrecScale(SqlDecimal n, int precision, int scale)
 {
     int prec = n.Precision;
     int sc = n.Scale;
     n = AdjustScale(n, scale - n.scale, true);
     if ((n.Scale >= sc) && (precision < n.Precision))
     {
         throw new SqlTruncateException();
     }
     else
     {
         prec = precision;
         return new SqlDecimal((byte) prec, n.scale, n.IsPositive, n.Data);
     }
 }
        public static SqlDecimal AdjustScale(SqlDecimal n, int digits, bool fRound)
        {
            byte prec = n.Precision;
            if (n.IsNull)
            {
                throw new SqlNullValueException();
            }

            byte scale;
            if (digits == 0)
            {
                return n;
            }
            else if (digits > 0)
            {
                prec = (byte) (prec + digits);
                scale = (byte) (n.scale + digits);
                // use Math.Pow once the Ctr (double) is fixed to  handle
                // values greater than Decimal.MaxValue
                // the current code creates too many sqldecimal objects 
                //n = n * (new SqlDecimal ((double)Math.Pow (10, digits)));
                for (int i = 0; i < digits; i++)
                {
                    n *= 10;
                }
            }
            else
            {
                if (n.Scale < Math.Abs(digits))
                {
                    throw new SqlTruncateException();
                }

                if (fRound)
                {
                    n = Round(n, digits + n.scale);
                }
                else
                {
                    n = Round(Truncate(n, digits + n.scale), digits + n.scale);
                }
                scale = n.scale;
            }

            return new SqlDecimal(prec, scale, n.positive, n.Data);
        }
 public static SqlDecimal Ceiling(SqlDecimal n)
 {
     if (!n.notNull)
     {
         return n;
     }
     return AdjustScale(n, -(n.Scale), true);
 }
 public static SqlDecimal Add(SqlDecimal x, SqlDecimal y)
 {
     return (x + y);
 }
 public static SqlDecimal Abs(SqlDecimal n)
 {
     if (!n.notNull)
     {
         return n;
     }
     return new SqlDecimal(n.Precision, n.Scale, true, n.Data);
 }
        public static SqlDecimal operator -(SqlDecimal x, SqlDecimal y)
        {
            if (x.IsNull || y.IsNull)
            {
                return 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 = AdjustScale(y, x.scale - y.scale, false);
            }
            else if (y.scale > x.scale)
            {
                x = AdjustScale(x, y.scale - x.scale, false);
            }

            //calculation of the new Precision for the result
            var 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;
            var 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 = ((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);
            }
        }
 public static SqlDecimal Multiply(SqlDecimal x, SqlDecimal y)
 {
     return(x * y);
 }
 public static SqlDecimal Divide(SqlDecimal x, SqlDecimal y)
 {
     return (x/y);
 }
 public static SqlDecimal Subtract(SqlDecimal x, SqlDecimal y)
 {
     return(x - y);
 }
 public static SqlDecimal Floor(SqlDecimal n)
 {
     return AdjustScale(n, -(n.Scale), false);
 }
 public static SqlInt32 Sign(SqlDecimal n)
 {
     if (n.IsNull)
     {
         return SqlInt32.Null;
     }
     return (n.IsPositive ? 1 : -1);
 }
 public static SqlBoolean GreaterThan(SqlDecimal x, SqlDecimal y)
 {
     return (x > y);
 }
        private static SqlDecimal DecimalDiv(SqlDecimal x, SqlDecimal y)
        {
            ulong lo = 0;
            ulong hi = 0;
            int sc = 0; // scale
            int texp = 0;
            byte prec = 0; // precision
            bool positive = ! (x.positive ^ y.positive);

            prec = x.Precision >= y.Precision ? x.Precision : y.Precision;
            DecimalDivSub(ref x, ref y, ref lo, ref hi, ref texp);

            sc = x.Scale - y.Scale;

            Rescale128(ref lo, ref hi, ref sc, texp, 0, 38, 1);

            uint r = 0;
            while (prec < sc)
            {
                Div128By32(ref hi, ref lo, 10, ref r);
                sc--;
            }

            if (r >= 5)
            {
                lo++;
            }

            while (((hi)*Math.Pow(2, 64) + lo) - Math.Pow(10, prec) > 0)
            {
                prec++;
            }

            while ((prec + sc) > MaxScale)
            {
                Div128By32(ref hi, ref lo, 10, ref r);
                sc--;
                if (r >= 5)
                {
                    lo++;
                }
            }

            var resultLo = (int) lo;
            var resultMi = (int) (lo >> 32);
            var resultMi2 = (int) (hi);
            var resultHi = (int) (hi >> 32);

            return new SqlDecimal(prec, (byte) sc, positive, resultLo,
                                  resultMi, resultMi2,
                                  resultHi);
        }
 public static SqlBoolean GreaterThanOrEqual(SqlDecimal x, SqlDecimal y)
 {
     return (x >= y);
 }
        public static SqlDecimal operator +(SqlDecimal x, SqlDecimal y)
        {
            if (x.IsNull || y.IsNull)
            {
                return(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 = AdjustScale(y, x.scale - y.scale, false);
            }
            else if (y.scale > x.scale)
            {
                x = AdjustScale(x, y.scale - x.scale, false);
            }

            var 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;
            var   resultBits = new int[4];
            ulong carry      = 0;
            ulong res        = 0;

            for (int i = 0; i < 4; i++)
            {
                res           = ((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));
            }
        }
 public static SqlBoolean LessThan(SqlDecimal x, SqlDecimal y)
 {
     return (x < y);
 }
 public static SqlDecimal Add(SqlDecimal x, SqlDecimal y)
 {
     return(x + y);
 }
 public static SqlBoolean LessThanOrEqual(SqlDecimal x, SqlDecimal y)
 {
     return (x <= y);
 }
 public static SqlDecimal Floor(SqlDecimal n)
 {
     return(AdjustScale(n, -(n.Scale), false));
 }
 public static SqlDecimal Multiply(SqlDecimal x, SqlDecimal y)
 {
     return (x*y);
 }
 public static SqlBoolean GreaterThanOrEqual(SqlDecimal x, SqlDecimal y)
 {
     return(x >= y);
 }
 public static SqlBoolean NotEquals(SqlDecimal x, SqlDecimal y)
 {
     return (x != y);
 }
 public static SqlBoolean LessThanOrEqual(SqlDecimal x, SqlDecimal y)
 {
     return(x <= y);
 }
        public static SqlDecimal Power(SqlDecimal n, double exp)
        {
            if (n.IsNull)
            {
                return Null;
            }

            return new SqlDecimal(Math.Pow(n.ToDouble(), exp));
        }
 public static SqlBoolean NotEquals(SqlDecimal x, SqlDecimal y)
 {
     return(x != y);
 }
        public static SqlDecimal Round(SqlDecimal n, int position)
        {
            if (n.IsNull)
            {
                throw new SqlNullValueException();
            }

            decimal d = n.Value;
            d = Math.Round(d, position);
            return new SqlDecimal(d);
        }
        // From decimal.c
        private static void DecimalDivSub(ref SqlDecimal x, ref SqlDecimal y, ref ulong clo, ref ulong chi, ref int exp)
        {
            ulong xlo, xmi, xhi;
            ulong tlo = 0;
            ulong tmi = 0;
            ulong thi = 0;

            ;
            uint ylo      = 0;
            uint ymi      = 0;
            uint ymi2     = 0;
            uint yhi      = 0;
            int  ashift   = 0;
            int  bshift   = 0;
            int  extraBit = 0;

            xhi  = ((ulong)x.Data[3] << 32) | (ulong)x.Data[2];
            xmi  = ((ulong)x.Data[1] << 32) | (ulong)x.Data[0];
            xlo  = 0;
            ylo  = (uint)y.Data[0];
            ymi  = (uint)y.Data[1];
            ymi2 = (uint)y.Data[2];
            yhi  = (uint)y.Data[3];

            if (ylo == 0 && ymi == 0 && ymi2 == 0 && yhi == 0)
            {
                throw new DivideByZeroException();
            }

            if (xmi == 0 && xhi == 0)
            {
                clo = chi = 0;
                return;
            }

            // enlarge dividend to get maximal precision
            for (ashift = 0; (xhi & LIT_GUINT64_HIGHBIT) == 0; ++ashift)
            {
                LShift128(ref xmi, ref xhi);
            }

            // ensure that divisor is at least 2^95
            for (bshift = 0; (yhi & LIT_GUINT32_HIGHBIT) == 0; ++bshift)
            {
                LShift128(ref ylo, ref ymi, ref ymi2, ref yhi);
            }

            thi = ((ulong)yhi) << 32 | ymi2;
            tmi = ((ulong)ymi) << 32 | ylo;
            tlo = 0;

            if (xhi > thi || (xhi == thi && xmi >= tmi))
            {
                Sub192(xlo, xmi, xhi, tlo, tmi, thi, ref xlo, ref xmi, ref xhi);
                extraBit = 1;
            }
            else
            {
                extraBit = 0;
            }

            Div192By128To128(xlo, xmi, xhi, ylo, ymi, ymi2, yhi, ref clo, ref chi);

            exp = 128 + ashift - bshift;

            if (extraBit != 0)
            {
                RShift128(ref clo, ref chi);
                chi += LIT_GUINT64_HIGHBIT;
                exp--;
            }

            // try loss free right shift
            while (exp > 0 && (clo & 1) == 0)
            {
                RShift128(ref clo, ref chi);
                exp--;
            }
        }
 public static SqlDecimal Truncate(SqlDecimal n, int position)
 {
     int diff = n.scale - position;
     if (diff == 0)
     {
         return n;
     }
     int[] data = n.Data;
     var d = new decimal(data[0], data[1], data[2], !n.positive, 0);
     decimal x = 10;
     for (int i = 0; i < diff; i++, x *= 10)
     {
         d = d - d%x;
     }
     data = Decimal.GetBits(d);
     data[3] = 0;
     return new SqlDecimal(n.precision, n.scale, n.positive, data);
 }