2 // Mono.Data.SybaseTypes.SybaseDecimal
5 // Tim Coleman <tim@timcoleman.com>
7 // Based on System.Data.SqlTypes.SqlDecimal
9 // (C) Ximian, Inc. 2002-2003
10 // (C) Copyright Tim Coleman, 2002
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using Mono
.Data
.Tds
.Protocol
;
36 using System
.Data
.SqlTypes
;
37 using System
.Globalization
;
40 namespace Mono
.Data
.SybaseTypes
{
41 public struct SybaseDecimal
: INullable
, IComparable
53 // borrowed from System.Decimal
54 const int SCALE_SHIFT
= 16;
55 const int SIGN_SHIFT
= 31;
56 const int RESERVED_SS32_BITS
= 0x7F00FFFF;
57 const ulong LIT_GUINT64_HIGHBIT
= 0x8000000000000000;
58 const ulong LIT_GUINT32_HIGHBIT
= 0x80000000;
59 const byte DECIMAL_MAX_INTFACTORS
= 9;
60 static uint [] constantsDecadeInt32Factors
= new uint [10]
62 1u, 10u, 100u, 1000u, 10000u, 100000u, 1000000u,
63 10000000u, 100000000u, 1000000000u
66 public static readonly byte MaxPrecision
= 38;
67 public static readonly byte MaxScale
= 38;
69 public static readonly SybaseDecimal MaxValue
= new SybaseDecimal (MaxPrecision
, (byte)0, true, (int)716002642, Int32
.MaxValue
, (int)1518778966, (int)1262177448);
70 public static readonly SybaseDecimal MinValue
= new SybaseDecimal (MaxPrecision
, (byte)0, false, (int)716002642, Int32
.MaxValue
, (int)1518778966, (int)1262177448);
71 public static readonly SybaseDecimal Null
;
77 public SybaseDecimal (decimal value)
79 int[] binData
= Decimal
.GetBits (value);
81 this.scale
= (byte)(binData
[3] >> SCALE_SHIFT
);
82 if (this.scale
> MaxScale
|| (this.scale
& RESERVED_SS32_BITS
) != 0)
83 throw new ArgumentException(Locale
.GetText ("Invalid scale"));
85 this.value = new int[4];
86 this.value[0] = binData
[0];
87 this.value[1] = binData
[1];
88 this.value[2] = binData
[2];
92 positive
= (value >= 0);
93 precision
= GetPrecision (value);
96 public SybaseDecimal (double value) : this ((decimal)value) { }
97 public SybaseDecimal (int value) : this ((decimal)value) { }
98 public SybaseDecimal (long value) : this ((decimal)value) { }
100 public SybaseDecimal (byte bPrecision
, byte bScale
, bool fPositive
, int[] bits
) : this (bPrecision
, bScale
, fPositive
, bits
[0], bits
[1], bits
[2], bits
[3]) { }
102 public SybaseDecimal (byte bPrecision
, byte bScale
, bool fPositive
, int data1
, int data2
, int data3
, int data4
)
104 this.precision
= bPrecision
;
106 this.positive
= fPositive
;
107 this.value = new int[4];
108 this.value[0] = data1
;
109 this.value[1] = data2
;
110 this.value[2] = data3
;
111 this.value[3] = data4
;
114 if (precision
< scale
)
115 throw new ArgumentException ("Invalid scale");
116 if (this.ToDouble () > (System
.Math
.Pow (10, 38) -1) || this.ToDouble () < -(System
.Math
.Pow (10, 38)))
117 throw new SybaseTypeException ("Can't convert to SybaseDecimal.");
124 public byte[] BinData
{
126 byte[] b
= new byte [value.Length
* 4];
128 for (int i
= 0; i
< value.Length
; i
+= 1) {
129 b
[j
++] = (byte) (0xff & value [i
]);
130 b
[j
++] = (byte) (0xff & value [i
] >> 8);
131 b
[j
++] = (byte) (0xff & value [i
] >> 16);
132 b
[j
++] = (byte) (0xff & value [i
] >> 24);
141 throw new SybaseNullValueException ();
148 get { return !notNull; }
151 public bool IsPositive
{
152 get { return positive; }
155 public byte Precision
{
156 get { return precision; }
160 get { return scale; }
163 public decimal Value
{
166 throw new SybaseNullValueException ();
167 if (this.value[3] > 0)
168 throw new OverflowException ();
169 return new decimal (value[0], value[1], value[2], !positive
, scale
);
177 public static SybaseDecimal
Abs (SybaseDecimal n
)
179 return new SybaseDecimal (n
.Precision
, n
.Scale
, true, n
.BinData
[0], n
.BinData
[1], n
.BinData
[2], n
.BinData
[3]);
182 public static SybaseDecimal
Add (SybaseDecimal x
, SybaseDecimal y
)
187 public static SybaseDecimal
AdjustScale (SybaseDecimal n
, int digits
, bool fRound
)
189 byte prec
= n
.Precision
;
191 throw new SybaseNullValueException ();
193 prec
= (byte) (prec
+ digits
);
195 n
= Round (n
, digits
+ n
.Scale
);
196 return new SybaseDecimal (prec
, (byte) (n
.Scale
+ digits
), n
.IsPositive
, n
.Data
);
199 public static SybaseDecimal
Ceiling (SybaseDecimal n
)
201 return AdjustScale (n
, -(n
.Scale
), true);
204 public int CompareTo (object value)
208 else if (!(value is SybaseDecimal
))
209 throw new ArgumentException (Locale
.GetText ("Value is not a System.Data.SybaseTypes.SybaseDecimal"));
210 else if (((SybaseDecimal
)value).IsNull
)
213 return this.Value
.CompareTo (((SybaseDecimal
)value).Value
);
216 public static SybaseDecimal
ConvertToPrecScale (SybaseDecimal n
, int precision
, int scale
)
218 return new SybaseDecimal ((byte) precision
, (byte) scale
, n
.IsPositive
, n
.Data
);
221 public static SybaseDecimal
Divide (SybaseDecimal x
, SybaseDecimal y
)
226 public override bool Equals (object value)
228 if (!(value is SybaseDecimal
))
230 else if (this.IsNull
&& ((SybaseDecimal
) value).IsNull
)
232 else if (((SybaseDecimal
) value).IsNull
)
235 return (bool) (this == (SybaseDecimal
)value);
238 public static SybaseBoolean
Equals (SybaseDecimal x
, SybaseDecimal y
)
243 public static SybaseDecimal
Floor (SybaseDecimal n
)
245 return AdjustScale (n
, -(n
.Scale
), false);
248 internal static SybaseDecimal
FromTdsBigDecimal (TdsBigDecimal x
)
253 return new SybaseDecimal (x
.Precision
, x
.Scale
, !x
.IsNegative
, x
.Data
);
256 public override int GetHashCode ()
259 result
= 91 * result
+ this.Data
[0];
260 result
= 91 * result
+ this.Data
[1];
261 result
= 91 * result
+ this.Data
[2];
262 result
= 91 * result
+ this.Data
[3];
263 result
= 91 * result
+ (int) this.Scale
;
264 result
= 91 * result
+ (int) this.Precision
;
269 public static SybaseBoolean
GreaterThan (SybaseDecimal x
, SybaseDecimal y
)
274 public static SybaseBoolean
GreaterThanOrEqual (SybaseDecimal x
, SybaseDecimal y
)
279 public static SybaseBoolean
LessThan (SybaseDecimal x
, SybaseDecimal y
)
284 public static SybaseBoolean
LessThanOrEqual (SybaseDecimal x
, SybaseDecimal y
)
289 public static SybaseDecimal
Multiply (SybaseDecimal x
, SybaseDecimal y
)
294 public static SybaseBoolean
NotEquals (SybaseDecimal x
, SybaseDecimal y
)
299 public static SybaseDecimal
Parse (string s
)
302 throw new ArgumentNullException ();
304 return SybaseDouble
.Parse (s
).ToSybaseDecimal ();
307 public static SybaseDecimal
Power (SybaseDecimal n
, double exp
)
310 return SybaseDecimal
.Null
;
311 return new SybaseDecimal (System
.Math
.Pow (n
.ToDouble (), exp
));
314 public static SybaseDecimal
Round (SybaseDecimal n
, int position
)
317 throw new SybaseNullValueException ();
318 SybaseDecimal result
= new SybaseDecimal (System
.Math
.Round ((double) (n
.ToDouble () * System
.Math
.Pow (10, position
))));
319 result
= result
/ new SybaseDecimal (System
.Math
.Pow (10, position
));
323 public static SybaseInt32
Sign (SybaseDecimal n
)
325 SybaseInt32 result
= 0;
326 if (n
>= new SybaseDecimal (0))
333 public static SybaseDecimal
Subtract (SybaseDecimal x
, SybaseDecimal y
)
338 private static byte GetPrecision (decimal value)
340 string str
= value.ToString ();
342 foreach (char c
in str
)
343 if (c
>= '0' && c
<= '9')
348 public double ToDouble ()
350 // FIXME: This is the wrong way to do this
351 double d
= (uint) this.Data
[0];
352 d
+= ((uint) this.Data
[1]) * System
.Math
.Pow (2, 32);
353 d
+= ((uint) this.Data
[2]) * System
.Math
.Pow (2, 64);
354 d
+= ((uint) this.Data
[3]) * System
.Math
.Pow (2, 96);
355 d
/= System
.Math
.Pow (10, scale
);
359 public SybaseBoolean
ToSybaseBoolean ()
361 return ((SybaseBoolean
)this);
364 public SybaseByte
ToSybaseByte ()
366 return ((SybaseByte
)this);
369 public SybaseDouble
ToSybaseDouble ()
371 return ((SybaseDouble
)this);
374 public SybaseInt16
ToSybaseInt16 ()
376 return ((SybaseInt16
)this);
379 public SybaseInt32
ToSybaseInt32 ()
381 return ((SybaseInt32
)this);
384 public SybaseInt64
ToSybaseInt64 ()
386 return ((SybaseInt64
)this);
389 public SybaseMoney
ToSybaseMoney ()
391 return ((SybaseMoney
)this);
394 public SybaseSingle
ToSybaseSingle ()
396 return ((SybaseSingle
)this);
399 public SybaseString
ToSybaseString ()
401 return ((SybaseString
)this);
404 public override string ToString ()
409 // convert int [4] -> ulong [2]
410 ulong lo
= (uint) this.Data
[0] + (ulong) ((ulong) this.Data
[1] << 32);
411 ulong hi
= (uint) this.Data
[2] + (ulong) ((ulong) this.Data
[3] << 32);
414 StringBuilder result
= new StringBuilder ();
415 for (int i
= 0; lo
!= 0 || hi
!= 0; i
+= 1) {
416 Div128By32 (ref hi
, ref lo
, 10, ref rest
);
417 result
.Insert (0, rest
.ToString ());
419 while (result
.Length
< Precision
)
421 while (result
.Length
> Precision
)
422 result
.Remove (result
.Length
- 1, 1);
424 result
.Insert (result
.Length
- Scale
, ".");
425 return result
.ToString ();
429 private static int Div128By32 (ref ulong hi
, ref ulong lo
, uint divider
)
432 return Div128By32 (ref hi
, ref lo
, divider
, ref t
);
436 private static int Div128By32 (ref ulong hi
, ref ulong lo
, uint divider
, ref uint rest
)
442 a
= (uint) (hi
>> 32);
450 hi
= b
<< 32 | (uint) c
;
452 a
= (uint) (lo
>> 32);
460 lo
= b
<< 32 | (uint) c
;
465 return (a
> divider
|| (a
== divider
&& (c
& 1) == 1)) ? 1 : 0;
468 [MonoTODO ("Find out what is the right way to set scale and precision")]
469 private static SybaseDecimal
DecimalDiv (SybaseDecimal x
, SybaseDecimal y
)
477 prec
= x
.Precision
>= y
.Precision
? x
.Precision
: y
.Precision
;
478 DecimalDivSub (ref x
, ref y
, ref lo
, ref hi
, ref texp
);
480 sc
= x
.Scale
- y
.Scale
;
482 Rescale128 (ref lo
, ref hi
, ref sc
, texp
, 0, 38, 1);
486 Div128By32 (ref hi
, ref lo
, 10, ref r
);
493 while ((((double) hi
) * System
.Math
.Pow (2, 64) + lo
) - System
.Math
.Pow (10, prec
) > 0)
496 while ((prec
+ sc
) > MaxScale
) {
497 Div128By32 (ref hi
, ref lo
, 10, ref r
);
503 int resultLo
= (int) lo
;
504 int resultMi
= (int) (lo
>> 32);
505 int resultMi2
= (int) hi
;
506 int resultHi
= (int) (hi
>> 32);
508 return new SybaseDecimal (prec
, (byte) sc
, true, resultLo
, resultMi
, resultMi2
, resultHi
);
512 private static void Rescale128 (ref ulong clo
, ref ulong chi
, ref int scale
, int texp
, int minScale
, int maxScale
, int roundFlag
)
523 while (texp
> 0 && sc
<= maxScale
) {
524 overhang
= (uint) (chi
>> 64);
525 while (texp
> 0 && (((clo
& 1) == 0) || overhang
> 0)) {
527 roundBit
= (int) (clo
& 1);
528 RShift128 (ref clo
, ref chi
);
529 overhang
= (uint) (chi
>> 32);
532 if (texp
> DECIMAL_MAX_INTFACTORS
)
533 i
= DECIMAL_MAX_INTFACTORS
;
537 if (sc
+ i
> maxScale
)
546 factor
= constantsDecadeInt32Factors
[i
] >> i
;
547 Mult128By32 (ref clo
, ref chi
, factor
, 0);
552 roundBit
= (int) (clo
& 1);
553 RShift128 (ref clo
, ref chi
);
558 while (sc
> maxScale
) {
559 i
= scale
- maxScale
;
560 if (i
> DECIMAL_MAX_INTFACTORS
)
561 i
= DECIMAL_MAX_INTFACTORS
;
563 roundBit
= Div128By32 (ref clo
, ref chi
, constantsDecadeInt32Factors
[i
]);
566 while (sc
< minScale
) {
570 if (i
> DECIMAL_MAX_INTFACTORS
)
571 i
= DECIMAL_MAX_INTFACTORS
;
573 Mult128By32 (ref clo
, ref chi
, constantsDecadeInt32Factors
[i
], roundBit
);
577 Normalize128 (ref clo
, ref chi
, ref sc
, roundFlag
, roundBit
);
581 private static void Normalize128 (ref ulong clo
, ref ulong chi
, ref int scale
, int roundFlag
, int roundBit
)
583 if ((roundFlag
!= 0) && (roundBit
!= 0))
584 RoundUp128 (ref clo
, ref chi
);
588 private static void RoundUp128 (ref ulong lo
, ref ulong hi
)
595 private static void DecimalDivSub (ref SybaseDecimal x
, ref SybaseDecimal y
, ref ulong clo
, ref ulong chi
, ref int exp
)
609 xhi
= (ulong) ((ulong) x
.Data
[3] << 32) | (ulong) x
.Data
[2];
610 xmi
= (ulong) ((ulong) x
.Data
[1] << 32) | (ulong) x
.Data
[0];
612 ylo
= (uint) y
.Data
[0];
613 ymi
= (uint) y
.Data
[1];
614 ymi2
= (uint) y
.Data
[2];
615 yhi
= (uint) y
.Data
[3];
617 if (ylo
== 0 && ymi
== 0 && ymi2
== 0 && yhi
== 0)
618 throw new DivideByZeroException ();
619 if (xmi
== 0 && xhi
== 0) {
624 // enlarge dividend to get maximal precision
625 for (ashift
= 0; (xhi
& LIT_GUINT64_HIGHBIT
) == 0; ++ashift
)
626 LShift128 (ref xmi
, ref xhi
);
628 // ensure that divisor is at least 2^95
629 for (bshift
= 0; (yhi
& LIT_GUINT32_HIGHBIT
) == 0; ++bshift
)
630 LShift128 (ref ylo
, ref ymi
, ref ymi2
, ref yhi
);
632 thi
= ((ulong) yhi
) << 32 | (ulong) ymi2
;
633 tmi
= ((ulong) ymi
) << 32 | (ulong) ylo
;
636 if (xhi
> thi
|| (xhi
== thi
&& xmi
>= tmi
)) {
637 Sub192 (xlo
, xmi
, xhi
, tlo
, tmi
, thi
, ref xlo
, ref xmi
, ref xhi
);
643 Div192By128To128 (xlo
, xmi
, xhi
, ylo
, ymi
, ymi2
, yhi
, ref clo
, ref chi
);
645 exp
= 128 + ashift
- bshift
;
648 RShift128 (ref clo
, ref chi
);
649 chi
+= LIT_GUINT64_HIGHBIT
;
653 // try loss free right shift
654 while (exp
> 0 && (clo
& 1) == 0) {
655 RShift128 (ref clo
, ref chi
);
661 private static void RShift192 (ref ulong lo
, ref ulong mi
, ref ulong hi
)
665 lo
|= LIT_GUINT64_HIGHBIT
;
669 mi
|= LIT_GUINT64_HIGHBIT
;
675 private static void RShift128 (ref ulong lo
, ref ulong hi
)
679 lo
|= LIT_GUINT64_HIGHBIT
;
684 private static void LShift128 (ref ulong lo
, ref ulong hi
)
688 if ((lo
& LIT_GUINT64_HIGHBIT
) != 0)
695 private static void LShift128 (ref uint lo
, ref uint mi
, ref uint mi2
, ref uint hi
)
698 if ((mi2
& LIT_GUINT32_HIGHBIT
) != 0)
702 if ((mi
& LIT_GUINT32_HIGHBIT
) != 0)
706 if ((lo
& LIT_GUINT32_HIGHBIT
) != 0)
713 private static void Div192By128To128 (ulong xlo
, ulong xmi
, ulong xhi
, uint ylo
, uint ymi
, uint ymi2
, uint yhi
, ref ulong clo
, ref ulong chi
)
715 ulong rlo
, rmi
, rhi
; // remainders
722 h
= Div192By128To32WithRest (ref rlo
, ref rmi
, ref rhi
, ylo
, ymi
, ymi2
, yhi
);
725 rhi
= (rhi
<< 32) | (rmi
>> 32);
726 rmi
= (rmi
<< 32) | (rlo
>> 32);
729 chi
= (((ulong)h
) << 32) | Div192By128To32WithRest (ref rlo
, ref rmi
, ref rhi
, ylo
, ymi
, ymi2
, yhi
);
732 rhi
= (rhi
<< 32) | (rmi
>> 32);
733 rmi
= (rmi
<< 32) | (rlo
>> 32);
736 h
= Div192By128To32WithRest (ref rlo
, ref rmi
, ref rhi
, ylo
, ymi
, ymi2
, yhi
);
738 // estimate lowest 32 bit (two last bits may be wrong)
743 c
= (uint)(rhi
/ yhi
);
746 clo
= (((ulong)h
) << 32) | c
;
750 private static uint Div192By128To32WithRest (ref ulong xlo
, ref ulong xmi
, ref ulong xhi
, uint ylo
, uint ymi
, uint ymi2
, uint yhi
)
752 ulong rlo
, rmi
, rhi
; // remainder
761 if (rhi
>= (((ulong)yhi
<< 32)))
764 c
= (uint) (rhi
/ yhi
);
766 Mult128By32To128 (ylo
, ymi
, ymi2
, yhi
, c
, ref tlo
, ref thi
);
767 Sub192 (rlo
, rmi
, rhi
, 0, tlo
, thi
, ref rlo
, ref rmi
, ref rhi
);
769 while (((long)rhi
) < 0) {
771 Add192 (rlo
, rmi
, rhi
, 0, (((ulong)ymi
) << 32) | ylo
, yhi
| ymi2
, ref rlo
, ref rmi
, ref rhi
);
781 private static void Mult192By32 (ref ulong clo
, ref ulong cmi
, ref ulong chi
, ulong factor
, int roundBit
)
787 a
= ((ulong)(uint)clo
) * factor
;
794 a
+= (clo
>> 32) * factor
;
797 clo
= ((ulong)h1
) << 32 | h0
;
800 a
+= ((ulong)(uint)cmi
) * factor
;
804 a
+= (cmi
>> 32) * factor
;
807 cmi
= ((ulong)h1
) << 32 | h0
;
809 a
+= ((ulong)(uint)chi
) * factor
;
813 a
+= (chi
>> 32) * factor
;
815 chi
= ((ulong)h1
) << 32 | h0
;
819 private static void Mult128By32 (ref ulong clo
, ref ulong chi
, uint factor
, int roundBit
)
825 a
= ((ulong)(uint)clo
) * factor
;
833 a
+= (clo
>> 32) * factor
;
836 clo
= ((ulong)h1
) << 32 | h0
;
839 a
+= ((ulong)(uint)chi
) * factor
;
843 a
+= (chi
>> 32) * factor
;
846 chi
= ((ulong)h1
) << 32 | h0
;
850 private static void Mult128By32To128 (uint xlo
, uint xmi
, uint xmi2
, uint xhi
, uint factor
, ref ulong clo
, ref ulong chi
)
855 a
= ((ulong)xlo
) * factor
;
859 a
+= ((ulong)xmi
) * factor
;
863 a
+= ((ulong)xmi2
) * factor
;
867 a
+= ((ulong)xhi
) * factor
;
869 clo
= ((ulong)h1
) << 32 | h0
;
874 private static void Add192 (ulong xlo
, ulong xmi
, ulong xhi
, ulong ylo
, ulong ymi
, ulong yhi
, ref ulong clo
, ref ulong cmi
, ref ulong chi
)
895 private static void Sub192 (ulong xlo
, ulong xmi
, ulong xhi
, ulong ylo
, ulong ymi
, ulong yhi
, ref ulong lo
, ref ulong mi
, ref ulong hi
)
919 public static SybaseDecimal
Truncate (SybaseDecimal n
, int position
)
921 return new SybaseDecimal ((byte) n
.Precision
, (byte) position
, n
.IsPositive
, n
.Data
);
924 public static SybaseDecimal
operator + (SybaseDecimal x
, SybaseDecimal y
)
926 // if one of them is negative, perform subtraction
927 if (x
.IsPositive
&& !y
.IsPositive
) return x
- y
;
928 if (y
.IsPositive
&& !x
.IsPositive
) return y
- x
;
930 // adjust the scale to the smaller of the two beforehand
931 if (x
.Scale
> y
.Scale
)
932 x
= SybaseDecimal
.AdjustScale(x
, y
.Scale
- x
.Scale
, true);
933 else if (y
.Scale
> x
.Scale
)
934 y
= SybaseDecimal
.AdjustScale(y
, x
.Scale
- y
.Scale
, true);
936 // set the precision to the greater of the two
937 byte resultPrecision
;
938 if (x
.Precision
> y
.Precision
)
939 resultPrecision
= x
.Precision
;
941 resultPrecision
= y
.Precision
;
943 int[] xData
= x
.Data
;
944 int[] yData
= y
.Data
;
945 int[] resultBits
= new int[4];
950 // add one at a time, and carry the results over to the next
951 for (int i
= 0; i
< 4; i
+=1)
954 res
= (ulong)(xData
[i
]) + (ulong)(yData
[i
]) + carry
;
955 if (res
> Int32
.MaxValue
)
957 carry
= res
- Int32
.MaxValue
;
958 res
= Int32
.MaxValue
;
960 resultBits
[i
] = (int)res
;
963 // if we have carry left, then throw an exception
965 throw new OverflowException ();
967 return new SybaseDecimal (resultPrecision
, x
.Scale
, x
.IsPositive
, resultBits
);
970 public static SybaseDecimal
operator / (SybaseDecimal x
, SybaseDecimal y
)
972 return DecimalDiv (x
, y
);
975 public static SybaseBoolean
operator == (SybaseDecimal x
, SybaseDecimal y
)
977 if (x
.IsNull
|| y
.IsNull
)
978 return SybaseBoolean
.Null
;
980 if (x
.Scale
> y
.Scale
)
981 x
= SybaseDecimal
.AdjustScale(x
, y
.Scale
- x
.Scale
, true);
982 else if (y
.Scale
> x
.Scale
)
983 y
= SybaseDecimal
.AdjustScale(y
, x
.Scale
- y
.Scale
, true);
985 for (int i
= 0; i
< 4; i
+= 1)
987 if (x
.Data
[i
] != y
.Data
[i
])
988 return new SybaseBoolean (false);
990 return new SybaseBoolean (true);
993 public static SybaseBoolean
operator > (SybaseDecimal x
, SybaseDecimal y
)
995 if (x
.IsNull
|| y
.IsNull
)
996 return SybaseBoolean
.Null
;
998 if (x
.Scale
> y
.Scale
)
999 x
= SybaseDecimal
.AdjustScale(x
, y
.Scale
- x
.Scale
, true);
1000 else if (y
.Scale
> x
.Scale
)
1001 y
= SybaseDecimal
.AdjustScale(y
, x
.Scale
- y
.Scale
, true);
1003 for (int i
= 3; i
>= 0; i
-= 1)
1005 if (x
.Data
[i
] == 0 && y
.Data
[i
] == 0)
1008 return new SybaseBoolean (x
.Data
[i
] > y
.Data
[i
]);
1010 return new SybaseBoolean (false);
1013 public static SybaseBoolean
operator >= (SybaseDecimal x
, SybaseDecimal y
)
1015 if (x
.IsNull
|| y
.IsNull
)
1016 return SybaseBoolean
.Null
;
1018 if (x
.Scale
> y
.Scale
)
1019 x
= SybaseDecimal
.AdjustScale(x
, y
.Scale
- x
.Scale
, true);
1020 else if (y
.Scale
> x
.Scale
)
1021 y
= SybaseDecimal
.AdjustScale(y
, x
.Scale
- y
.Scale
, true);
1023 for (int i
= 3; i
>= 0; i
-= 1)
1025 if (x
.Data
[i
] == 0 && y
.Data
[i
] == 0)
1028 return new SybaseBoolean (x
.Data
[i
] >= y
.Data
[i
]);
1030 return new SybaseBoolean (true);
1033 public static SybaseBoolean
operator != (SybaseDecimal x
, SybaseDecimal y
)
1035 if (x
.IsNull
|| y
.IsNull
)
1036 return SybaseBoolean
.Null
;
1038 if (x
.Scale
> y
.Scale
)
1039 x
= SybaseDecimal
.AdjustScale(x
, y
.Scale
- x
.Scale
, true);
1040 else if (y
.Scale
> x
.Scale
)
1041 y
= SybaseDecimal
.AdjustScale(y
, x
.Scale
- y
.Scale
, true);
1043 for (int i
= 0; i
< 4; i
+= 1)
1045 if (x
.Data
[i
] != y
.Data
[i
])
1046 return new SybaseBoolean (true);
1048 return new SybaseBoolean (false);
1051 public static SybaseBoolean
operator < (SybaseDecimal x
, SybaseDecimal y
)
1053 if (x
.IsNull
|| y
.IsNull
)
1054 return SybaseBoolean
.Null
;
1056 if (x
.Scale
> y
.Scale
)
1057 x
= SybaseDecimal
.AdjustScale(x
, y
.Scale
- x
.Scale
, true);
1058 else if (y
.Scale
> x
.Scale
)
1059 y
= SybaseDecimal
.AdjustScale(y
, x
.Scale
- y
.Scale
, true);
1061 for (int i
= 3; i
>= 0; i
-= 1)
1063 if (x
.Data
[i
] == 0 && y
.Data
[i
] == 0)
1066 return new SybaseBoolean (x
.Data
[i
] < y
.Data
[i
]);
1068 return new SybaseBoolean (false);
1071 public static SybaseBoolean
operator <= (SybaseDecimal x
, SybaseDecimal y
)
1073 if (x
.IsNull
|| y
.IsNull
)
1074 return SybaseBoolean
.Null
;
1076 if (x
.Scale
> y
.Scale
)
1077 x
= SybaseDecimal
.AdjustScale(x
, y
.Scale
- x
.Scale
, true);
1078 else if (y
.Scale
> x
.Scale
)
1079 y
= SybaseDecimal
.AdjustScale(y
, x
.Scale
- y
.Scale
, true);
1081 for (int i
= 3; i
>= 0; i
-= 1)
1083 if (x
.Data
[i
] == 0 && y
.Data
[i
] == 0)
1086 return new SybaseBoolean (x
.Data
[i
] <= y
.Data
[i
]);
1088 return new SybaseBoolean (true);
1091 public static SybaseDecimal
operator * (SybaseDecimal x
, SybaseDecimal y
)
1093 // adjust the scale to the smaller of the two beforehand
1094 if (x
.Scale
> y
.Scale
)
1095 x
= SybaseDecimal
.AdjustScale(x
, y
.Scale
- x
.Scale
, true);
1096 else if (y
.Scale
> x
.Scale
)
1097 y
= SybaseDecimal
.AdjustScale(y
, x
.Scale
- y
.Scale
, true);
1099 // set the precision to the greater of the two
1100 byte resultPrecision
;
1101 if (x
.Precision
> y
.Precision
)
1102 resultPrecision
= x
.Precision
;
1104 resultPrecision
= y
.Precision
;
1106 int[] xData
= x
.Data
;
1107 int[] yData
= y
.Data
;
1108 int[] resultBits
= new int[4];
1113 // multiply one at a time, and carry the results over to the next
1114 for (int i
= 0; i
< 4; i
+=1)
1117 res
= (ulong)(xData
[i
]) * (ulong)(yData
[i
]) + carry
;
1118 if (res
> Int32
.MaxValue
)
1120 carry
= res
- Int32
.MaxValue
;
1121 res
= Int32
.MaxValue
;
1123 resultBits
[i
] = (int)res
;
1126 // if we have carry left, then throw an exception
1128 throw new OverflowException ();
1130 return new SybaseDecimal (resultPrecision
, x
.Scale
, (x
.IsPositive
== y
.IsPositive
), resultBits
);
1134 public static SybaseDecimal
operator - (SybaseDecimal x
, SybaseDecimal y
)
1136 if (x
.IsPositive
&& !y
.IsPositive
) return x
+ y
;
1137 if (!x
.IsPositive
&& y
.IsPositive
) return -(x
+ y
);
1138 if (!x
.IsPositive
&& !y
.IsPositive
) return y
- x
;
1140 // otherwise, x is positive and y is positive
1141 bool resultPositive
= (bool)(x
> y
);
1142 int[] yData
= y
.Data
;
1144 for (int i
= 0; i
< 4; i
+= 1) yData
[i
] = -yData
[i
];
1146 SybaseDecimal yInverse
= new SybaseDecimal (y
.Precision
, y
.Scale
, y
.IsPositive
, yData
);
1149 return x
+ yInverse
;
1151 return -(x
+ yInverse
);
1154 public static SybaseDecimal
operator - (SybaseDecimal n
)
1156 return new SybaseDecimal (n
.Precision
, n
.Scale
, !n
.IsPositive
, n
.Data
);
1159 public static explicit operator SybaseDecimal (SybaseBoolean x
)
1164 return new SybaseDecimal ((decimal)x
.ByteValue
);
1167 public static explicit operator Decimal (SybaseDecimal n
)
1172 public static explicit operator SybaseDecimal (SybaseDouble x
)
1177 return new SybaseDecimal ((decimal)x
.Value
);
1180 public static explicit operator SybaseDecimal (SybaseSingle x
)
1185 return new SybaseDecimal ((decimal)x
.Value
);
1189 public static explicit operator SybaseDecimal (SybaseString x
)
1191 throw new NotImplementedException ();
1194 public static implicit operator SybaseDecimal (decimal x
)
1196 return new SybaseDecimal (x
);
1199 public static implicit operator SybaseDecimal (SybaseByte x
)
1204 return new SybaseDecimal ((decimal)x
.Value
);
1207 public static implicit operator SybaseDecimal (SybaseInt16 x
)
1212 return new SybaseDecimal ((decimal)x
.Value
);
1215 public static implicit operator SybaseDecimal (SybaseInt32 x
)
1220 return new SybaseDecimal ((decimal)x
.Value
);
1223 public static implicit operator SybaseDecimal (SybaseInt64 x
)
1228 return new SybaseDecimal ((decimal)x
.Value
);
1231 public static implicit operator SybaseDecimal (SybaseMoney x
)
1236 return new SybaseDecimal ((decimal)x
.Value
);