2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.Data / Mono.Data.SqlExpressions / Numeric.cs
1
2 //
3 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 // 
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 // 
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 using System;
25 using System.Collections;
26
27 namespace Mono.Data.SqlExpressions {
28         internal class Numeric {
29                 internal static bool IsNumeric (object o) {
30                         if (o is IConvertible) {
31                                 TypeCode tc = ((IConvertible)o).GetTypeCode();
32                                 if(TypeCode.Char <= tc && tc <= TypeCode.Decimal)
33                                         return true;
34                         }
35                         return false;
36                 }
37
38                 //extends to Int32/Int64/Decimal/Double
39                 internal static IConvertible Unify (IConvertible o)
40                 {
41                         switch (o.GetTypeCode()) {
42                         case TypeCode.Char:
43                         case TypeCode.SByte:
44                         case TypeCode.Byte:
45                         case TypeCode.Int16:
46                         case TypeCode.UInt16:
47                                 return (IConvertible)Convert.ChangeType (o, TypeCode.Int32);
48                         
49                         case TypeCode.UInt32:
50                                 return (IConvertible)Convert.ChangeType (o, TypeCode.Int64);
51                                 
52                         case TypeCode.UInt64:
53                                 return (IConvertible)Convert.ChangeType (o, TypeCode.Decimal);
54                                 
55                         case TypeCode.Single:
56                                 return (IConvertible)Convert.ChangeType (o, TypeCode.Double);
57                         
58                         default:
59                                 return o;
60                         }
61                 }
62                 
63                 //(note: o1 and o2 must both be of type Int32/Int64/Decimal/Double)
64                 internal static void ToSameType (ref IConvertible o1, ref IConvertible o2)
65                 {
66                         TypeCode tc1 = o1.GetTypeCode();
67                         TypeCode tc2 = o2.GetTypeCode();
68                         
69                         if (tc1 == tc2)
70                                 return;
71
72                         // is it ok to make such assumptions about the order of an enum?
73                         if (tc1 < tc2)
74                                 o1 = (IConvertible) Convert.ChangeType (o1, tc2);
75                         else
76                                 o2 = (IConvertible) Convert.ChangeType (o2, tc1);
77                 }
78                 
79                 internal static IConvertible Add (IConvertible o1, IConvertible o2)
80                 {
81                         ToSameType (ref o1, ref o2);
82                         switch (o1.GetTypeCode()) {
83                         case TypeCode.Int32:
84                         default:
85                                 return (int)o1 + (int)o2;
86                         case TypeCode.Int64:
87                                 return (long)o1 + (long)o2;
88                         case TypeCode.Double:
89                                 return (double)o1 + (double)o2;
90                         case TypeCode.Decimal:
91                                 return (decimal)o1 + (decimal)o2;
92                         }
93                 }
94                 
95                 internal static IConvertible Subtract (IConvertible o1, IConvertible o2)
96                 {
97                         ToSameType (ref o1, ref o2);
98                         switch (o1.GetTypeCode()) {
99                         case TypeCode.Int32:
100                         default:
101                                 return (int)o1 - (int)o2;
102                         case TypeCode.Int64:
103                                 return (long)o1 - (long)o2;
104                         case TypeCode.Double:
105                                 return (double)o1 - (double)o2;
106                         case TypeCode.Decimal:
107                                 return (decimal)o1 - (decimal)o2;
108                         }
109                 }
110                 
111                 internal static IConvertible Multiply (IConvertible o1, IConvertible o2)
112                 {
113                         ToSameType (ref o1, ref o2);
114                         switch (o1.GetTypeCode()) {
115                         case TypeCode.Int32:
116                         default:
117                                 return (int)o1 * (int)o2;
118                         case TypeCode.Int64:
119                                 return (long)o1 * (long)o2;
120                         case TypeCode.Double:
121                                 return (double)o1 * (double)o2;
122                         case TypeCode.Decimal:
123                                 return (decimal)o1 * (decimal)o2;
124                         }
125                 }
126                 
127                 internal static IConvertible Divide (IConvertible o1, IConvertible o2)
128                 {
129                         ToSameType (ref o1, ref o2);
130                         switch (o1.GetTypeCode()) {
131                         case TypeCode.Int32:
132                         default:
133                                 return (int)o1 / (int)o2;
134                         case TypeCode.Int64:
135                                 return (long)o1 / (long)o2;
136                         case TypeCode.Double:
137                                 return (double)o1 / (double)o2;
138                         case TypeCode.Decimal:
139                                 return (decimal)o1 / (decimal)o2;
140                         }
141                 }
142                 
143                 internal static IConvertible Modulo (IConvertible o1, IConvertible o2)
144                 {
145                         ToSameType (ref o1, ref o2);
146                         switch (o1.GetTypeCode()) {
147                         case TypeCode.Int32:
148                         default:
149                                 return (int)o1 % (int)o2;
150                         case TypeCode.Int64:
151                                 return (long)o1 % (long)o2;
152                         case TypeCode.Double:
153                                 return (double)o1 % (double)o2;
154                         case TypeCode.Decimal:
155                                 return (decimal)o1 % (decimal)o2;
156                         }
157                 }
158                 
159                 internal static IConvertible Negative (IConvertible o)
160                 {
161                         switch (o.GetTypeCode()) {
162                         case TypeCode.Int32:
163                         default:
164                                 return -((int)o);
165                         case TypeCode.Int64:
166                                 return -((long)o);
167                         case TypeCode.Double:
168                                 return -((double)o);
169                         case TypeCode.Decimal:
170                                 return -((decimal)o);
171                         }
172                 }
173                 
174                 internal static IConvertible Min (IConvertible o1, IConvertible o2)
175                 {
176                         switch (o1.GetTypeCode()) {
177                         case TypeCode.Int32:
178                         default:
179                                 return System.Math.Min ((int)o1, (int)o2);
180                         case TypeCode.Int64:
181                                 return System.Math.Min ((long)o1, (long)o2);
182                         case TypeCode.Double:
183                                 return System.Math.Min ((double)o1, (double)o2);
184                         case TypeCode.Decimal:
185                                 return System.Math.Min ((decimal)o1, (decimal)o2);
186                         }
187                 }
188
189                 internal static IConvertible Max (IConvertible o1, IConvertible o2)
190                 {
191                         switch (o1.GetTypeCode()) {
192                         case TypeCode.Int32:
193                         default:
194                                 return System.Math.Max ((int)o1, (int)o2);
195                         case TypeCode.Int64:
196                                 return System.Math.Max ((long)o1, (long)o2);
197                         case TypeCode.Double:
198                                 return System.Math.Max ((double)o1, (double)o2);
199                         case TypeCode.Decimal:
200                                 return System.Math.Max ((decimal)o1, (decimal)o2);
201                         }
202                 }
203         }
204 }