Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data / System / Data / Common / SQLTypes / SQLSingleStorage.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="SQLSingleStorage.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 // <owner current="false" primary="false">[....]</owner>
8 //------------------------------------------------------------------------------
9
10 namespace System.Data.Common {
11     using System;
12     using System.Xml;
13     using System.Data.SqlTypes;
14     using System.Diagnostics;
15     using System.Globalization;
16     using System.IO;
17     using System.Xml.Serialization;
18     using System.Collections;
19
20     internal sealed class SqlSingleStorage : DataStorage {
21
22         private SqlSingle[] values;
23
24         public SqlSingleStorage(DataColumn column)
25         : base(column, typeof(SqlSingle), SqlSingle.Null, SqlSingle.Null, StorageType.SqlSingle) {
26         }
27
28         override public Object Aggregate(int[] records, AggregateType kind) {
29             bool hasData = false;
30             try {
31                 switch (kind) {
32                     case AggregateType.Sum:
33                         SqlSingle sum =  0.0f;
34                         foreach (int record in records) {
35                             if (IsNull(record))
36                                 continue;
37                             checked { sum += values[record];}
38                             hasData = true;
39                         }
40                         if (hasData)
41                             return sum;
42                         
43                         return NullValue;
44
45                     case AggregateType.Mean:
46                         SqlDouble meanSum = (SqlDouble) 0.0f;
47                         int meanCount = 0;
48                         foreach (int record in records) {
49                             if (IsNull(record))
50                                 continue;
51
52                             checked { meanSum += values[record].ToSqlDouble();}
53                             meanCount++;
54                             hasData = true;
55                         }
56                         if (hasData) {
57                             SqlSingle mean = 0;
58                             checked {mean = (meanSum /(SqlDouble) meanCount).ToSqlSingle();}
59                             return mean;
60                         }
61                         return NullValue;
62
63                     case AggregateType.Var:
64                     case AggregateType.StDev:
65                         int count = 0;
66                         SqlDouble var = (SqlDouble)0;
67                         SqlDouble prec = (SqlDouble)0;
68                         SqlDouble dsum = (SqlDouble)0;
69                         SqlDouble sqrsum = (SqlDouble)0;
70
71                         foreach (int record in records) {
72                             if (IsNull(record))
73                                 continue;
74                             dsum += values[record].ToSqlDouble();
75                             sqrsum += (values[record]).ToSqlDouble() * (values[record]).ToSqlDouble();
76                             count++;
77                         }
78
79                         if (count > 1) {
80                             var = ((SqlDouble)count * sqrsum - (dsum * dsum));
81                             prec = var / (dsum * dsum);
82                             
83                             // we are dealing with the risk of a cancellation error
84                             // double is guaranteed only for 15 digits so a difference 
85                             // with a result less than 1e-15 should be considered as zero
86
87                             if ((prec < 1e-15) || (var <0))
88                                 var = 0;
89                             else
90                                 var = var / (count * (count -1));
91                             
92                             if (kind == AggregateType.StDev) {
93                                return  Math.Sqrt(var.Value);
94                             }
95                             return var;
96                         }
97                         return NullValue;
98
99                     case AggregateType.Min:
100                         SqlSingle min = SqlSingle.MaxValue;
101                         for (int i = 0; i < records.Length; i++) {
102                             int record = records[i];
103                             if (IsNull(record))
104                                 continue;
105
106                             if ((SqlSingle.LessThan(values[record], min)).IsTrue)
107                                 min = values[record];                        
108                             hasData = true;
109                         }
110                         if (hasData)
111                             return min;
112                         return NullValue;
113
114                     case AggregateType.Max:
115                         SqlSingle max = SqlSingle.MinValue;
116                         for (int i = 0; i < records.Length; i++) {
117                             int record = records[i];
118                             if (IsNull(record))
119                                 continue;
120
121                             if ((SqlSingle.GreaterThan(values[record], max)).IsTrue)
122                                 max = values[record];
123                             hasData = true;
124                         }
125                         if (hasData)
126                             return max;
127                         return NullValue;
128
129                     case AggregateType.First:
130                         if (records.Length > 0) {
131                             return values[records[0]];
132                         }
133                         return null;
134
135                     case AggregateType.Count:
136                         count = 0;
137                         for (int i = 0; i < records.Length; i++) {
138                             if (!IsNull(records[i]))
139                                 count++;
140                         }
141                         return count;
142                 }
143             }
144             catch (OverflowException) {
145                 throw ExprException.Overflow(typeof(SqlSingle));
146             }
147             throw ExceptionBuilder.AggregateException(kind, DataType);
148         }
149
150         override public int Compare(int recordNo1, int recordNo2) {
151             return values[recordNo1].CompareTo(values[recordNo2]);
152         }
153
154         override public int CompareValueTo(int recordNo, Object value) {
155             return values[recordNo].CompareTo((SqlSingle)value);
156         }
157
158         override public object ConvertValue(object value) {
159             if (null != value) {
160                 return SqlConvert.ConvertToSqlSingle(value);
161             }
162             return NullValue;
163         }
164
165         override public void Copy(int recordNo1, int recordNo2) {
166             values[recordNo2] = values[recordNo1];
167         }
168
169         override public Object Get(int record) {
170             return values[record];
171         }
172
173         override public bool IsNull(int record) {
174             return (values[record].IsNull);
175         }
176
177         override public void Set(int record, Object value) {
178             values[record] = SqlConvert.ConvertToSqlSingle(value);
179         }
180
181         override public void SetCapacity(int capacity) {
182             SqlSingle[] newValues = new SqlSingle[capacity];
183             if (null != values) {
184                 Array.Copy(values, 0, newValues, 0, Math.Min(capacity, values.Length));
185             }
186             values = newValues;
187         }
188
189         override public object ConvertXmlToObject(string s) {
190             SqlSingle newValue = new SqlSingle();
191             string tempStr =string.Concat("<col>", s, "</col>"); // this is done since you can give fragmet to reader, bug 98767
192             StringReader strReader = new  StringReader(tempStr);
193
194             IXmlSerializable tmp = newValue;
195             
196             using (XmlTextReader xmlTextReader = new XmlTextReader(strReader)) {
197                 tmp.ReadXml(xmlTextReader);
198             }
199             return ((SqlSingle)tmp);
200         }
201
202         override public string ConvertObjectToXml(object value) {
203             Debug.Assert(!DataStorage.IsObjectNull(value), "we should have null here");
204             Debug.Assert((value.GetType() == typeof(SqlSingle)), "wrong input type");
205
206             StringWriter strwriter = new StringWriter(FormatProvider);
207
208             using (XmlTextWriter xmlTextWriter = new XmlTextWriter (strwriter)) {
209                 ((IXmlSerializable)value).WriteXml(xmlTextWriter);
210             }
211             return (strwriter.ToString ());
212         }
213         
214         override protected object GetEmptyStorage(int recordCount) {
215             return new SqlSingle[recordCount];
216         }
217         
218         override protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex) {
219             SqlSingle[] typedStore = (SqlSingle[]) store; 
220             typedStore[storeIndex] = values[record];
221             nullbits.Set(storeIndex, IsNull(record));
222         }
223         
224         override protected void SetStorage(object store, BitArray nullbits) {
225             values = (SqlSingle[]) store; 
226             //SetNullStorage(nullbits);
227         }        
228     }
229 }