1 //------------------------------------------------------------------------------
2 // <copyright file="DecimalStorage.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
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 //------------------------------------------------------------------------------
10 namespace System.Data.Common {
13 using System.Data.SqlTypes;
14 using System.Collections;
16 internal sealed class DecimalStorage : DataStorage {
18 private static readonly Decimal defaultValue = Decimal.Zero;
20 private Decimal[] values;
22 internal DecimalStorage(DataColumn column)
23 : base(column, typeof(Decimal), defaultValue, StorageType.Decimal) {
26 override public Object Aggregate(int[] records, AggregateType kind) {
30 case AggregateType.Sum:
31 Decimal sum = defaultValue;
32 foreach (int record in records) {
33 if (HasValue(record)) {
34 checked { sum += values[record];}
43 case AggregateType.Mean:
44 Decimal meanSum = (Decimal)defaultValue;
46 foreach (int record in records) {
47 if (HasValue(record)) {
48 checked { meanSum += (Decimal)values[record];}
55 checked {mean = (meanSum /(Decimal) meanCount);}
60 case AggregateType.Var:
61 case AggregateType.StDev:
63 double var = (double)defaultValue;
64 double prec = (double)defaultValue;
65 double dsum = (double)defaultValue;
66 double sqrsum = (double)defaultValue;
68 foreach (int record in records) {
69 if (HasValue(record)) {
70 dsum += (double)values[record];
71 sqrsum += (double)values[record]*(double)values[record];
77 var = ((double)count * sqrsum - (dsum * dsum));
78 prec = var / (dsum * dsum);
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
84 if ((prec < 1e-15) || (var <0))
87 var = var / (count * (count -1));
89 if (kind == AggregateType.StDev) {
90 return Math.Sqrt(var);
96 case AggregateType.Min:
97 Decimal min = Decimal.MaxValue;
98 for (int i = 0; i < records.Length; i++) {
99 int record = records[i];
100 if (HasValue(record)) {
101 min=Math.Min(values[record], min);
110 case AggregateType.Max:
111 Decimal max = Decimal.MinValue;
112 for (int i = 0; i < records.Length; i++) {
113 int record = records[i];
114 if (HasValue(record)) {
115 max=Math.Max(values[record], max);
124 case AggregateType.First:
125 if (records.Length > 0) {
126 return values[records[0]];
130 case AggregateType.Count:
131 return base.Aggregate(records, kind);
135 catch (OverflowException) {
136 throw ExprException.Overflow(typeof(Decimal));
138 throw ExceptionBuilder.AggregateException(kind, DataType);
141 override public int Compare(int recordNo1, int recordNo2) {
142 Decimal valueNo1 = values[recordNo1];
143 Decimal valueNo2 = values[recordNo2];
145 if (valueNo1 == defaultValue || valueNo2 == defaultValue) {
146 int bitCheck = CompareBits(recordNo1, recordNo2);
150 return Decimal.Compare(valueNo1, valueNo2); // InternalCall
153 public override int CompareValueTo(int recordNo, object value) {
154 System.Diagnostics.Debug.Assert(0 <= recordNo, "Invalid record");
155 System.Diagnostics.Debug.Assert(null != value, "null value");
157 if (NullValue == value) {
158 return (HasValue(recordNo) ? 1 : 0);
161 Decimal valueNo1 = values[recordNo];
162 if ((defaultValue == valueNo1) && !HasValue(recordNo)) {
165 return Decimal.Compare(valueNo1, (Decimal)value);
168 public override object ConvertValue(object value) {
169 if (NullValue != value) {
171 value = ((IConvertible)value).ToDecimal(FormatProvider);
180 override public void Copy(int recordNo1, int recordNo2) {
181 CopyBits(recordNo1, recordNo2);
182 values[recordNo2] = values[recordNo1];
185 override public Object Get(int record) {
186 return (HasValue(record) ? values[record] : NullValue);
189 override public void Set(int record, Object value) {
190 System.Diagnostics.Debug.Assert(null != value, "null value");
191 if (NullValue == value) {
192 values[record] = defaultValue;
193 SetNullBit(record, true);
196 values[record] = ((IConvertible)value).ToDecimal(FormatProvider);
197 SetNullBit(record, false);
201 override public void SetCapacity(int capacity) {
202 Decimal[] newValues = new Decimal[capacity];
203 if (null != values) {
204 Array.Copy(values, 0, newValues, 0, Math.Min(capacity, values.Length));
207 base.SetCapacity(capacity);
210 override public object ConvertXmlToObject(string s) {
211 return XmlConvert.ToDecimal(s);
214 override public string ConvertObjectToXml(object value) {
215 return XmlConvert.ToString((Decimal)value);
218 override protected object GetEmptyStorage(int recordCount) {
219 return new Decimal[recordCount];
222 override protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex) {
223 Decimal[] typedStore = (Decimal[]) store;
224 typedStore[storeIndex] = values[record];
225 nullbits.Set(storeIndex, !HasValue(record));
228 override protected void SetStorage(object store, BitArray nullbits) {
229 values = (Decimal[]) store;
230 SetNullStorage(nullbits);