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