// (C) Copyright 2002 Tim Coleman
//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using Mono.Data.Tds.Protocol;
using System;
using System.Text;
this.value[2] = data3;
this.value[3] = data4;
notNull = true;
-
+
if (precision < scale)
- throw new ArgumentException(Locale.GetText ("Invalid scale"));
+ throw new SqlTypeException (Locale.GetText ("Invalid presicion/scale combination."));
+
+ if (precision > 38)
+ throw new SqlTypeException (Locale.GetText ("Invalid precision/scale combination."));
if (this.ToDouble () > (Math.Pow (10, 38) - 1) ||
this.ToDouble () < -(Math.Pow (10, 38)))
ret [0] = value [0];
ret [1] = value [1];
ret [2] = value [2];
+ ret [3] = value [3];
return ret;
}
}
public static SqlDecimal Abs (SqlDecimal n)
{
- return new SqlDecimal (n.Precision, n.Scale, true,
- n.BinData [0], n.BinData [1],
- n.BinData [2], n.BinData [3]);
+ if (!n.notNull)
+ return n;
+ return new SqlDecimal (n.Precision, n.Scale, true, n.Data);
}
public static SqlDecimal Add (SqlDecimal x, SqlDecimal y)
int [] data;
byte newScale;
- if (digits > 0) {
+ if (digits == 0)
+ return n;
+ else if (digits > 0) {
prec = (byte)(prec + digits);
decimal d = n.Value;
if (digits > 0)
if (fRound)
n = Round (n, digits + n.scale);
else
- n = Truncate (n, digits + n.scale);
+ n = Round (Truncate (n, digits + n.scale), digits + n.scale);
data = n.Data;
newScale = n.scale;
}
public static SqlDecimal Ceiling (SqlDecimal n)
{
+ if (!n.notNull)
+ return n;
return AdjustScale (n, -(n.Scale), true);
}
public static SqlDecimal ConvertToPrecScale (SqlDecimal n, int precision, int scale)
{
- return new SqlDecimal ((byte)precision, (byte)scale, n.IsPositive, n.Data);
+// return new SqlDecimal ((byte)precision, (byte)scale, n.IsPositive, n.Data);
+ // FIXME: precision
+ return AdjustScale (n, scale - n.scale, true);
}
public static SqlDecimal Divide (SqlDecimal x, SqlDecimal y)
if (this.Scale > 0)
Result.Insert (Result.Length - this.Scale, ".");
+ if (!positive)
+ Result.Insert (0, '-');
+
return Result.ToString ();
}
int texp = 0;
int rc = 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);
int resultMi2 = (int)(hi);
int resultHi = (int)(hi >> 32);
- return new SqlDecimal (prec, (byte)sc, true, resultLo,
+ return new SqlDecimal (prec, (byte)sc, positive, resultLo,
resultMi, resultMi2,
resultHi);
}
// 10^i/2^i=5^i
factor = constantsDecadeInt32Factors [i] >> i;
- System.Console.WriteLine ("***");
+// System.Console.WriteLine ("***");
Mult128By32 (ref clo, ref chi, factor, 0);
- System.Console.WriteLine ((((double)chi) * Math.Pow (2,64) + clo));
+// System.Console.WriteLine ((((double)chi) * Math.Pow (2,64) + clo));
}
// if one of them is negative, perform subtraction
if (x.IsPositive && !y.IsPositive) return x - y;
if (y.IsPositive && !x.IsPositive) return y - x;
-
- // 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);
+
+ // adjust the scale to the larger of the two beforehand
+ if (x.scale > y.scale)
+ y = SqlDecimal.AdjustScale (y, x.scale - y.scale, true); // FIXME: should be false (fix it after AdjustScale(,,false) is fixed)
+ else if (y.scale > x.scale)
+ x = SqlDecimal.AdjustScale (x, y.scale - x.scale, true); // FIXME: should be false (fix it after AdjustScale(,,false) is fixed)
// set the precision to the greater of the two
byte resultPrecision;