Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data / System / Data / SQLTypes / SQLDouble.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="SqlDouble.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 //  </copyright>
5 // <owner current="true" primary="true">junfang</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 // <owner current="true" primary="false">Microsoft</owner>
8 //------------------------------------------------------------------------------
9
10 //**************************************************************************
11 // @File: SqlDouble.cs
12 //
13 // Create by:    JunFang
14 //
15 // Purpose: Implementation of SqlDouble which is equivalent to
16 //            data type "float" in SQL Server
17 //
18 // Notes:
19 //
20 // History:
21 //
22 //   09/17/99  JunFang    Created and implemented as first drop.
23 //
24 // @EndHeader@
25 //**************************************************************************
26
27 using System;
28 using System.Data.Common;
29 using System.Runtime.InteropServices;
30 using System.Globalization;
31 using System.Xml;
32 using System.Xml.Schema;
33 using System.Xml.Serialization;
34
35 namespace System.Data.SqlTypes {
36
37     /// <devdoc>
38     ///    <para>
39     ///       Represents a floating-point number within the range of
40     ///       -1.79E
41     ///       +308 through 1.79E +308 to be stored in or retrieved from
42     ///       a database.
43     ///    </para>
44     /// </devdoc>
45     [Serializable]
46     [StructLayout(LayoutKind.Sequential)]
47     [XmlSchemaProvider("GetXsdType")]
48     public struct SqlDouble : INullable, IComparable, IXmlSerializable {
49
50         private bool m_fNotNull; // false if null
51         private double m_value;
52
53         // constructor
54         // construct a Null
55         private SqlDouble(bool fNull) {
56             m_fNotNull = false;
57             m_value = 0.0;
58         }
59
60         /// <devdoc>
61         ///    <para>[To be supplied.]</para>
62         /// </devdoc>
63         public SqlDouble(double value) {
64             if (Double.IsInfinity(value) || Double.IsNaN(value))
65                 throw new OverflowException(SQLResource.ArithOverflowMessage);
66             else {
67                 m_value = value;
68                 m_fNotNull = true;
69             }
70         }
71
72         // INullable
73         /// <devdoc>
74         ///    <para>[To be supplied.]</para>
75         /// </devdoc>
76         public bool IsNull {
77             get { return !m_fNotNull;}
78         }
79
80         // property: Value
81         /// <devdoc>
82         ///    <para>[To be supplied.]</para>
83         /// </devdoc>
84         public double Value {
85             get {
86                 if (m_fNotNull)
87                     return m_value;
88                 else
89                     throw new SqlNullValueException();
90             }
91         }
92
93         // Implicit conversion from double to SqlDouble
94         /// <devdoc>
95         ///    <para>[To be supplied.]</para>
96         /// </devdoc>
97         public static implicit operator SqlDouble(double x) {
98             return new SqlDouble(x);
99         }
100
101         // Explicit conversion from SqlDouble to double. Throw exception if x is Null.
102         /// <devdoc>
103         ///    <para>[To be supplied.]</para>
104         /// </devdoc>
105         public static explicit operator double(SqlDouble x) {
106             return x.Value;
107         }
108
109         /// <devdoc>
110         ///    <para>[To be supplied.]</para>
111         /// </devdoc>
112         public override String ToString() {
113             return IsNull ? SQLResource.NullString : m_value.ToString((IFormatProvider)null);
114         }
115
116         /// <devdoc>
117         ///    <para>[To be supplied.]</para>
118         /// </devdoc>
119         public static SqlDouble Parse(String s) {
120             if (s == SQLResource.NullString)
121                 return SqlDouble.Null;
122             else
123                 return new SqlDouble(Double.Parse(s, CultureInfo.InvariantCulture));
124         }
125
126
127         // Unary operators
128         /// <devdoc>
129         ///    <para>[To be supplied.]</para>
130         /// </devdoc>
131         public static SqlDouble operator -(SqlDouble x) {
132             return x.IsNull ? Null : new SqlDouble(-x.m_value);
133         }
134
135
136         // Binary operators
137
138         // Arithmetic operators
139         /// <devdoc>
140         ///    <para>[To be supplied.]</para>
141         /// </devdoc>
142         public static SqlDouble operator +(SqlDouble x, SqlDouble y) {
143             if (x.IsNull || y.IsNull)
144                 return Null;
145
146             double value = x.m_value + y.m_value;
147
148             if (Double.IsInfinity(value))
149                 throw new OverflowException(SQLResource.ArithOverflowMessage);
150
151             return new SqlDouble(value);
152         }
153
154         /// <devdoc>
155         ///    <para>[To be supplied.]</para>
156         /// </devdoc>
157         public static SqlDouble operator -(SqlDouble x, SqlDouble y) {
158             if (x.IsNull || y.IsNull)
159                 return Null;
160
161             double value = x.m_value - y.m_value;
162
163             if (Double.IsInfinity(value))
164                 throw new OverflowException(SQLResource.ArithOverflowMessage);
165
166             return new SqlDouble(value);
167         }
168
169         /// <devdoc>
170         ///    <para>[To be supplied.]</para>
171         /// </devdoc>
172         public static SqlDouble operator *(SqlDouble x, SqlDouble y) {
173             if (x.IsNull || y.IsNull)
174                 return Null;
175
176             double value = x.m_value * y.m_value;
177
178             if (Double.IsInfinity(value))
179                 throw new OverflowException(SQLResource.ArithOverflowMessage);
180
181             return new SqlDouble(value);
182         }
183
184         /// <devdoc>
185         ///    <para>[To be supplied.]</para>
186         /// </devdoc>
187         public static SqlDouble operator /(SqlDouble x, SqlDouble y) {
188             if (x.IsNull || y.IsNull)
189                 return Null;
190
191             if (y.m_value == (double)0.0)
192                 throw new DivideByZeroException(SQLResource.DivideByZeroMessage);
193
194             double value = x.m_value / y.m_value;
195
196             if (Double.IsInfinity(value))
197                 throw new OverflowException(SQLResource.ArithOverflowMessage);
198
199             return new SqlDouble(value);
200         }
201
202
203
204         // Implicit conversions
205
206         // Implicit conversion from SqlBoolean to SqlDouble
207         /// <devdoc>
208         ///    <para>[To be supplied.]</para>
209         /// </devdoc>
210         public static explicit operator SqlDouble(SqlBoolean x) {
211             return x.IsNull ? Null : new SqlDouble((double)(x.ByteValue));
212         }
213
214         // Implicit conversion from SqlByte to SqlDouble
215         /// <devdoc>
216         ///    <para>[To be supplied.]</para>
217         /// </devdoc>
218         public static implicit operator SqlDouble(SqlByte x) {
219             return x.IsNull ? Null : new SqlDouble((double)(x.Value));
220         }
221
222         // Implicit conversion from SqlInt16 to SqlDouble
223         /// <devdoc>
224         ///    <para>[To be supplied.]</para>
225         /// </devdoc>
226         public static implicit operator SqlDouble(SqlInt16 x) {
227             return x.IsNull ? Null : new SqlDouble((double)(x.Value));
228         }
229
230         // Implicit conversion from SqlInt32 to SqlDouble
231         /// <devdoc>
232         ///    <para>[To be supplied.]</para>
233         /// </devdoc>
234         public static implicit operator SqlDouble(SqlInt32 x) {
235             return x.IsNull ? Null : new SqlDouble((double)(x.Value));
236         }
237
238         // Implicit conversion from SqlInt64 to SqlDouble
239         /// <devdoc>
240         ///    <para>[To be supplied.]</para>
241         /// </devdoc>
242         public static implicit operator SqlDouble(SqlInt64 x) {
243             return x.IsNull ? Null : new SqlDouble((double)(x.Value));
244         }
245
246         // Implicit conversion from SqlSingle to SqlDouble
247         /// <devdoc>
248         ///    <para>[To be supplied.]</para>
249         /// </devdoc>
250         public static implicit operator SqlDouble(SqlSingle x) {
251             return x.IsNull ? Null : new SqlDouble((double)(x.Value));
252         }
253
254         // Implicit conversion from SqlMoney to SqlDouble
255         /// <devdoc>
256         ///    <para>[To be supplied.]</para>
257         /// </devdoc>
258         public static implicit operator SqlDouble(SqlMoney x) {
259             return x.IsNull ? Null : new SqlDouble(x.ToDouble());
260         }
261
262         // Implicit conversion from SqlDecimal to SqlDouble
263         /// <devdoc>
264         ///    <para>[To be supplied.]</para>
265         /// </devdoc>
266         public static implicit operator SqlDouble(SqlDecimal x) {
267             return x.IsNull ? Null : new SqlDouble(x.ToDouble());
268         }
269
270
271         // Explicit conversions
272
273
274
275         // Explicit conversion from SqlString to SqlDouble
276         // Throws FormatException or OverflowException if necessary.
277         /// <devdoc>
278         ///    <para>[To be supplied.]</para>
279         /// </devdoc>
280         public static explicit operator SqlDouble(SqlString x) {
281             if (x.IsNull)
282                 return SqlDouble.Null;
283
284             return Parse(x.Value);
285         }
286
287         // Overloading comparison operators
288         /// <devdoc>
289         ///    <para>[To be supplied.]</para>
290         /// </devdoc>
291         public static SqlBoolean operator==(SqlDouble x, SqlDouble y) {
292             return(x.IsNull || y.IsNull) ? SqlBoolean.Null : new SqlBoolean(x.m_value == y.m_value);
293         }
294
295         /// <devdoc>
296         ///    <para>[To be supplied.]</para>
297         /// </devdoc>
298         public static SqlBoolean operator!=(SqlDouble x, SqlDouble y) {
299             return ! (x == y);
300         }
301
302         /// <devdoc>
303         ///    <para>[To be supplied.]</para>
304         /// </devdoc>
305         public static SqlBoolean operator<(SqlDouble x, SqlDouble y) {
306             return(x.IsNull || y.IsNull) ? SqlBoolean.Null : new SqlBoolean(x.m_value < y.m_value);
307         }
308
309         /// <devdoc>
310         ///    <para>[To be supplied.]</para>
311         /// </devdoc>
312         public static SqlBoolean operator>(SqlDouble x, SqlDouble y) {
313             return(x.IsNull || y.IsNull) ? SqlBoolean.Null : new SqlBoolean(x.m_value > y.m_value);
314         }
315
316         /// <devdoc>
317         ///    <para>[To be supplied.]</para>
318         /// </devdoc>
319         public static SqlBoolean operator<=(SqlDouble x, SqlDouble y) {
320             return(x.IsNull || y.IsNull) ? SqlBoolean.Null : new SqlBoolean(x.m_value <= y.m_value);
321         }
322
323         /// <devdoc>
324         ///    <para>[To be supplied.]</para>
325         /// </devdoc>
326         public static SqlBoolean operator>=(SqlDouble x, SqlDouble y) {
327             return(x.IsNull || y.IsNull) ? SqlBoolean.Null : new SqlBoolean(x.m_value >= y.m_value);
328         }
329
330         //--------------------------------------------------
331         // Alternative methods for overloaded operators
332         //--------------------------------------------------
333
334         // Alternative method for operator +
335         public static SqlDouble Add(SqlDouble x, SqlDouble y) {
336             return x + y;
337         }
338         // Alternative method for operator -
339         public static SqlDouble Subtract(SqlDouble x, SqlDouble y) {
340             return x - y;
341         }
342
343         // Alternative method for operator *
344         public static SqlDouble Multiply(SqlDouble x, SqlDouble y) {
345             return x * y;
346         }
347
348         // Alternative method for operator /
349         public static SqlDouble Divide(SqlDouble x, SqlDouble y) {
350             return x / y;
351         }
352
353         // Alternative method for operator ==
354         public static SqlBoolean Equals(SqlDouble x, SqlDouble y) {
355             return (x == y);
356         }
357
358         // Alternative method for operator !=
359         public static SqlBoolean NotEquals(SqlDouble x, SqlDouble y) {
360             return (x != y);
361         }
362
363         // Alternative method for operator <
364         public static SqlBoolean LessThan(SqlDouble x, SqlDouble y) {
365             return (x < y);
366         }
367
368         // Alternative method for operator >
369         public static SqlBoolean GreaterThan(SqlDouble x, SqlDouble y) {
370             return (x > y);
371         }
372
373         // Alternative method for operator <=
374         public static SqlBoolean LessThanOrEqual(SqlDouble x, SqlDouble y) {
375             return (x <= y);
376         }
377
378         // Alternative method for operator >=
379         public static SqlBoolean GreaterThanOrEqual(SqlDouble x, SqlDouble y) {
380             return (x >= y);
381         }
382
383         // Alternative method for conversions.
384
385         public SqlBoolean ToSqlBoolean() {
386             return (SqlBoolean)this;
387         }
388
389         public SqlByte ToSqlByte() {
390             return (SqlByte)this;
391         }
392
393         public SqlInt16 ToSqlInt16() {
394             return (SqlInt16)this;
395         }
396
397         public SqlInt32 ToSqlInt32() {
398             return (SqlInt32)this;
399         }
400
401         public SqlInt64 ToSqlInt64() {
402             return (SqlInt64)this;
403         }
404
405         public SqlMoney ToSqlMoney() {
406             return (SqlMoney)this;
407         }
408
409         public SqlDecimal ToSqlDecimal() {
410             return (SqlDecimal)this;
411         }
412
413         public SqlSingle ToSqlSingle() {
414             return (SqlSingle)this;
415         }
416
417         public SqlString ToSqlString() {
418             return (SqlString)this;
419         }
420
421
422
423         // IComparable
424         // Compares this object to another object, returning an integer that
425         // indicates the relationship.
426         // Returns a value less than zero if this < object, zero if this = object,
427         // or a value greater than zero if this > object.
428         // null is considered to be less than any instance.
429         // If object is not of same type, this method throws an ArgumentException.
430         /// <devdoc>
431         ///    <para>[To be supplied.]</para>
432         /// </devdoc>
433         public int CompareTo(Object value) {
434             if (value is SqlDouble) {
435                 SqlDouble i = (SqlDouble)value;
436
437                 return CompareTo(i);
438             }
439             throw ADP.WrongType(value.GetType(), typeof(SqlDouble));
440         }
441
442         public int CompareTo(SqlDouble value) {
443             // If both Null, consider them equal.
444             // Otherwise, Null is less than anything.
445             if (IsNull)
446                 return value.IsNull ? 0  : -1;
447             else if (value.IsNull)
448                 return 1;
449
450             if (this < value) return -1;
451             if (this > value) return 1;
452             return 0;
453         }
454
455         // Compares this instance with a specified object
456         /// <devdoc>
457         ///    <para>[To be supplied.]</para>
458         /// </devdoc>
459         public override bool Equals(Object value) {
460             if (!(value is SqlDouble)) {
461                 return false;
462             }
463
464             SqlDouble i = (SqlDouble)value;
465
466             if (i.IsNull || IsNull)
467                 return (i.IsNull && IsNull);
468             else
469                 return (this == i).Value;
470         }
471
472         // For hashing purpose
473         /// <devdoc>
474         ///    <para>[To be supplied.]</para>
475         /// </devdoc>
476         public override int GetHashCode() {
477             return IsNull ? 0 : Value.GetHashCode();
478         }
479
480         /// <devdoc>
481         ///    <para>[To be supplied.]</para>
482         /// </devdoc>
483         XmlSchema IXmlSerializable.GetSchema() { return null; }
484
485         /// <devdoc>
486         ///    <para>[To be supplied.]</para>
487         /// </devdoc>
488         void IXmlSerializable.ReadXml(XmlReader reader) {
489             string isNull = reader.GetAttribute("nil", XmlSchema.InstanceNamespace);
490             if (isNull != null && XmlConvert.ToBoolean(isNull)) {
491                 // VSTFDevDiv# 479603 - SqlTypes read null value infinitely and never read the next value. Fix - Read the next value.
492                 reader.ReadElementString();
493                 m_fNotNull = false;
494             }
495             else {
496                 m_value = XmlConvert.ToDouble(reader.ReadElementString());
497                 m_fNotNull = true;
498             }
499         }
500
501         /// <devdoc>
502         ///    <para>[To be supplied.]</para>
503         /// </devdoc>
504         void IXmlSerializable.WriteXml(XmlWriter writer) {
505             if (IsNull) {
506                 writer.WriteAttributeString("xsi", "nil", XmlSchema.InstanceNamespace, "true");
507             }
508             else {
509                 writer.WriteString(XmlConvert.ToString(m_value));
510             }
511         }
512
513         /// <devdoc>
514         ///    <para>[To be supplied.]</para>
515         /// </devdoc>
516         public static XmlQualifiedName GetXsdType(XmlSchemaSet schemaSet) {
517             return new XmlQualifiedName("double", XmlSchema.Namespace);
518         }
519
520         /// <devdoc>
521         ///    <para>[To be supplied.]</para>
522         /// </devdoc>
523         public static readonly SqlDouble Null       = new SqlDouble(true);
524         /// <devdoc>
525         ///    <para>[To be supplied.]</para>
526         /// </devdoc>
527         public static readonly SqlDouble Zero       = new SqlDouble(0.0);
528         /// <devdoc>
529         ///    <para>[To be supplied.]</para>
530         /// </devdoc>
531         public static readonly SqlDouble MinValue   = new SqlDouble(Double.MinValue);
532         /// <devdoc>
533         ///    <para>[To be supplied.]</para>
534         /// </devdoc>
535         public static readonly SqlDouble MaxValue   = new SqlDouble(Double.MaxValue);
536
537     } // SqlDouble
538
539 } // namespace System.Data.SqlTypes