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