2 // Mono.Data.TdsTypes.TdsDecimal
5 // Tim Coleman <tim@timcoleman.com>
7 // (C) Copyright Tim Coleman, 2002
10 using Mono.Data.TdsClient;
12 using System.Data.SqlTypes;
13 using System.Globalization;
15 namespace Mono.Data.TdsTypes {
16 public struct TdsDecimal : INullable, IComparable
27 // borrowed from System.Decimal
28 const int SCALE_SHIFT = 16;
29 const int SIGN_SHIFT = 31;
30 const int RESERVED_SS32_BITS = 0x7F00FFFF;
32 public static readonly byte MaxPrecision = 38;
33 public static readonly byte MaxScale = 28;
34 public static readonly TdsDecimal MaxValue = new TdsDecimal (79228162514264337593543950335.0);
35 public static readonly TdsDecimal MinValue = new TdsDecimal (-79228162514264337593543950335.0);
36 public static readonly TdsDecimal Null;
42 public TdsDecimal (decimal value)
44 int[] binData = Decimal.GetBits (value);
46 this.precision = MaxPrecision; // this value seems unclear
48 this.scale = (byte)(binData[3] >> SCALE_SHIFT);
49 if (this.scale > MaxScale || (this.scale & RESERVED_SS32_BITS) != 0)
50 throw new ArgumentException(Locale.GetText ("Invalid scale"));
52 this.positive = ((binData[3] >> SIGN_SHIFT) > 0);
53 this.value = new int[4];
54 this.value[0] = binData[0];
55 this.value[1] = binData[1];
56 this.value[2] = binData[2];
61 public TdsDecimal (double value) : this ((decimal)value) { }
62 public TdsDecimal (int value) : this ((decimal)value) { }
63 public TdsDecimal (long value) : this ((decimal)value) { }
65 public TdsDecimal (byte bPrecision, byte bScale, bool fPositive, int[] bits) : this (bPrecision, bScale, fPositive, bits[0], bits[1], bits[2], bits[3]) { }
67 public TdsDecimal (byte bPrecision, byte bScale, bool fPositive, int data1, int data2, int data3, int data4)
69 this.precision = bPrecision;
71 this.positive = fPositive;
72 this.value = new int[4];
73 this.value[0] = data1;
74 this.value[1] = data2;
75 this.value[2] = data3;
76 this.value[3] = data4;
85 public byte[] BinData {
86 get { throw new NotImplementedException (); }
92 throw new TdsNullValueException ();
99 get { return !notNull; }
102 public bool IsPositive {
103 get { return positive; }
106 public byte Precision {
107 get { return precision; }
111 get { return scale; }
114 public decimal Value {
117 throw new TdsNullValueException ();
119 if (this.value[3] > 0)
120 throw new OverflowException ();
122 System.Console.WriteLine( "boo!" );
123 return new decimal (value[0], value[1], value[2], !positive, scale);
132 public static TdsDecimal Abs (TdsDecimal n)
134 throw new NotImplementedException();
137 public static TdsDecimal Add (TdsDecimal x, TdsDecimal y)
143 public static TdsDecimal AdjustScale (TdsDecimal n, int digits, bool fRound)
145 throw new NotImplementedException ();
149 public static TdsDecimal Ceiling (TdsDecimal n)
151 throw new NotImplementedException();
154 public int CompareTo (object value)
158 else if (!(value is TdsDecimal))
159 throw new ArgumentException (Locale.GetText ("Value is not a System.Data.TdsTypes.TdsDecimal"));
160 else if (((TdsDecimal)value).IsNull)
163 return this.Value.CompareTo (((TdsDecimal)value).Value);
167 public static TdsDecimal ConvertToPrecScale (TdsDecimal n, int precision, int scale)
169 throw new NotImplementedException ();
172 public static TdsDecimal Divide (TdsDecimal x, TdsDecimal y)
177 public override bool Equals (object value)
179 if (!(value is TdsDecimal))
182 return (bool) (this == (TdsDecimal)value);
185 public static TdsBoolean Equals (TdsDecimal x, TdsDecimal y)
191 public static TdsDecimal Floor (TdsDecimal n)
193 throw new NotImplementedException ();
196 public override int GetHashCode ()
198 return (int)this.Value;
201 public static TdsBoolean GreaterThan (TdsDecimal x, TdsDecimal y)
206 public static TdsBoolean GreaterThanOrEqual (TdsDecimal x, TdsDecimal y)
211 public static TdsBoolean LessThan (TdsDecimal x, TdsDecimal y)
216 public static TdsBoolean LessThanOrEqual (TdsDecimal x, TdsDecimal y)
221 public static TdsDecimal Multiply (TdsDecimal x, TdsDecimal y)
226 public static TdsBoolean NotEquals (TdsDecimal x, TdsDecimal y)
232 public static TdsDecimal Parse (string s)
234 throw new NotImplementedException ();
238 public static TdsDecimal Power (TdsDecimal n, double exp)
240 throw new NotImplementedException ();
244 public static TdsDecimal Round (TdsDecimal n, int position)
246 throw new NotImplementedException ();
250 public static TdsInt32 Sign (TdsDecimal n)
252 throw new NotImplementedException ();
255 public static TdsDecimal Subtract (TdsDecimal x, TdsDecimal y)
260 public double ToDouble ()
262 return ((double)this.Value);
265 public TdsBoolean ToTdsBoolean ()
267 return ((TdsBoolean)this);
270 public TdsByte ToTdsByte ()
272 return ((TdsByte)this);
275 public TdsDouble ToTdsDouble ()
277 return ((TdsDouble)this);
280 public TdsInt16 ToTdsInt16 ()
282 return ((TdsInt16)this);
285 public TdsInt32 ToTdsInt32 ()
287 return ((TdsInt32)this);
290 public TdsInt64 ToTdsInt64 ()
292 return ((TdsInt64)this);
295 public TdsMoney ToTdsMoney ()
297 return ((TdsMoney)this);
300 public TdsSingle ToTdsSingle ()
302 return ((TdsSingle)this);
305 public TdsString ToTdsString ()
307 return ((TdsString)this);
310 public override string ToString ()
315 return value.ToString ();
319 public static TdsDecimal Truncate (TdsDecimal n, int position)
321 throw new NotImplementedException ();
324 public static TdsDecimal operator + (TdsDecimal x, TdsDecimal y)
326 // if one of them is negative, perform subtraction
327 if (x.IsPositive && !y.IsPositive) return x - y;
328 if (y.IsPositive && !x.IsPositive) return y - x;
330 // adjust the scale to the smaller of the two beforehand
331 if (x.Scale > y.Scale)
332 x = TdsDecimal.AdjustScale(x, y.Scale - x.Scale, true);
333 else if (y.Scale > x.Scale)
334 y = TdsDecimal.AdjustScale(y, x.Scale - y.Scale, true);
336 // set the precision to the greater of the two
337 byte resultPrecision;
338 if (x.Precision > y.Precision)
339 resultPrecision = x.Precision;
341 resultPrecision = y.Precision;
343 int[] xData = x.Data;
344 int[] yData = y.Data;
345 int[] resultBits = new int[4];
350 // add one at a time, and carry the results over to the next
351 for (int i = 0; i < 4; i +=1)
354 res = (ulong)(xData[i]) + (ulong)(yData[i]) + carry;
355 if (res > Int32.MaxValue)
357 carry = res - Int32.MaxValue;
358 res = Int32.MaxValue;
360 resultBits [i] = (int)res;
363 // if we have carry left, then throw an exception
365 throw new OverflowException ();
367 return new TdsDecimal (resultPrecision, x.Scale, x.IsPositive, resultBits);
371 public static TdsDecimal operator / (TdsDecimal x, TdsDecimal y)
373 throw new NotImplementedException ();
376 public static TdsBoolean operator == (TdsDecimal x, TdsDecimal y)
378 if (x.IsNull || y.IsNull)
379 return TdsBoolean.Null;
381 if (x.Scale > y.Scale)
382 x = TdsDecimal.AdjustScale(x, y.Scale - x.Scale, true);
383 else if (y.Scale > x.Scale)
384 y = TdsDecimal.AdjustScale(y, x.Scale - y.Scale, true);
386 for (int i = 0; i < 4; i += 1)
388 if (x.Data[i] != y.Data[i])
389 return new TdsBoolean (false);
391 return new TdsBoolean (true);
394 public static TdsBoolean operator > (TdsDecimal x, TdsDecimal y)
396 if (x.IsNull || y.IsNull)
397 return TdsBoolean.Null;
399 if (x.Scale > y.Scale)
400 x = TdsDecimal.AdjustScale(x, y.Scale - x.Scale, true);
401 else if (y.Scale > x.Scale)
402 y = TdsDecimal.AdjustScale(y, x.Scale - y.Scale, true);
404 for (int i = 3; i >= 0; i -= 1)
406 if (x.Data[i] == 0 && y.Data[i] == 0)
409 return new TdsBoolean (x.Data[i] > y.Data[i]);
411 return new TdsBoolean (false);
414 public static TdsBoolean operator >= (TdsDecimal x, TdsDecimal y)
416 if (x.IsNull || y.IsNull)
417 return TdsBoolean.Null;
419 if (x.Scale > y.Scale)
420 x = TdsDecimal.AdjustScale(x, y.Scale - x.Scale, true);
421 else if (y.Scale > x.Scale)
422 y = TdsDecimal.AdjustScale(y, x.Scale - y.Scale, true);
424 for (int i = 3; i >= 0; i -= 1)
426 if (x.Data[i] == 0 && y.Data[i] == 0)
429 return new TdsBoolean (x.Data[i] >= y.Data[i]);
431 return new TdsBoolean (true);
434 public static TdsBoolean operator != (TdsDecimal x, TdsDecimal y)
436 if (x.IsNull || y.IsNull)
437 return TdsBoolean.Null;
439 if (x.Scale > y.Scale)
440 x = TdsDecimal.AdjustScale(x, y.Scale - x.Scale, true);
441 else if (y.Scale > x.Scale)
442 y = TdsDecimal.AdjustScale(y, x.Scale - y.Scale, true);
444 for (int i = 0; i < 4; i += 1)
446 if (x.Data[i] != y.Data[i])
447 return new TdsBoolean (true);
449 return new TdsBoolean (false);
452 public static TdsBoolean operator < (TdsDecimal x, TdsDecimal y)
454 if (x.IsNull || y.IsNull)
455 return TdsBoolean.Null;
457 if (x.Scale > y.Scale)
458 x = TdsDecimal.AdjustScale(x, y.Scale - x.Scale, true);
459 else if (y.Scale > x.Scale)
460 y = TdsDecimal.AdjustScale(y, x.Scale - y.Scale, true);
462 for (int i = 3; i >= 0; i -= 1)
464 if (x.Data[i] == 0 && y.Data[i] == 0)
467 return new TdsBoolean (x.Data[i] < y.Data[i]);
469 return new TdsBoolean (false);
472 public static TdsBoolean operator <= (TdsDecimal x, TdsDecimal y)
474 if (x.IsNull || y.IsNull)
475 return TdsBoolean.Null;
477 if (x.Scale > y.Scale)
478 x = TdsDecimal.AdjustScale(x, y.Scale - x.Scale, true);
479 else if (y.Scale > x.Scale)
480 y = TdsDecimal.AdjustScale(y, x.Scale - y.Scale, true);
482 for (int i = 3; i >= 0; i -= 1)
484 if (x.Data[i] == 0 && y.Data[i] == 0)
487 return new TdsBoolean (x.Data[i] <= y.Data[i]);
489 return new TdsBoolean (true);
492 public static TdsDecimal operator * (TdsDecimal x, TdsDecimal y)
494 // adjust the scale to the smaller of the two beforehand
495 if (x.Scale > y.Scale)
496 x = TdsDecimal.AdjustScale(x, y.Scale - x.Scale, true);
497 else if (y.Scale > x.Scale)
498 y = TdsDecimal.AdjustScale(y, x.Scale - y.Scale, true);
500 // set the precision to the greater of the two
501 byte resultPrecision;
502 if (x.Precision > y.Precision)
503 resultPrecision = x.Precision;
505 resultPrecision = y.Precision;
507 int[] xData = x.Data;
508 int[] yData = y.Data;
509 int[] resultBits = new int[4];
514 // multiply one at a time, and carry the results over to the next
515 for (int i = 0; i < 4; i +=1)
518 res = (ulong)(xData[i]) * (ulong)(yData[i]) + carry;
519 if (res > Int32.MaxValue)
521 carry = res - Int32.MaxValue;
522 res = Int32.MaxValue;
524 resultBits [i] = (int)res;
527 // if we have carry left, then throw an exception
529 throw new OverflowException ();
531 return new TdsDecimal (resultPrecision, x.Scale, (x.IsPositive == y.IsPositive), resultBits);
535 public static TdsDecimal operator - (TdsDecimal x, TdsDecimal y)
537 if (x.IsPositive && !y.IsPositive) return x + y;
538 if (!x.IsPositive && y.IsPositive) return -(x + y);
539 if (!x.IsPositive && !y.IsPositive) return y - x;
541 // otherwise, x is positive and y is positive
542 bool resultPositive = (bool)(x > y);
543 int[] yData = y.Data;
545 for (int i = 0; i < 4; i += 1) yData[i] = -yData[i];
547 TdsDecimal yInverse = new TdsDecimal (y.Precision, y.Scale, y.IsPositive, yData);
552 return -(x + yInverse);
555 public static TdsDecimal operator - (TdsDecimal n)
557 return new TdsDecimal (n.Precision, n.Scale, !n.IsPositive, n.Data);
560 public static explicit operator TdsDecimal (TdsBoolean x)
565 return new TdsDecimal ((decimal)x.ByteValue);
568 public static explicit operator Decimal (TdsDecimal n)
573 public static explicit operator TdsDecimal (TdsDouble x)
578 return new TdsDecimal ((decimal)x.Value);
581 public static explicit operator TdsDecimal (TdsSingle x)
586 return new TdsDecimal ((decimal)x.Value);
590 public static explicit operator TdsDecimal (TdsString x)
592 throw new NotImplementedException ();
595 public static implicit operator TdsDecimal (decimal x)
597 return new TdsDecimal (x);
600 public static implicit operator TdsDecimal (TdsByte x)
605 return new TdsDecimal ((decimal)x.Value);
608 public static implicit operator TdsDecimal (TdsInt16 x)
613 return new TdsDecimal ((decimal)x.Value);
616 public static implicit operator TdsDecimal (TdsInt32 x)
621 return new TdsDecimal ((decimal)x.Value);
624 public static implicit operator TdsDecimal (TdsInt64 x)
629 return new TdsDecimal ((decimal)x.Value);
632 public static implicit operator TdsDecimal (TdsMoney x)
637 return new TdsDecimal ((decimal)x.Value);