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); }