1 //------------------------------------------------------------------------------
2 // <copyright file="DoubleStorage.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 DoubleStorage
: DataStorage
{
18 private const Double defaultValue
= 0.0d
;
20 private Double
[] values
;
22 internal DoubleStorage(DataColumn column
)
23 : base(column
, typeof(Double
), defaultValue
, StorageType
.Double
) {
26 override public Object
Aggregate(int[] records
, AggregateType kind
) {
30 case AggregateType
.Sum
:
31 Double sum
= defaultValue
;
32 foreach (int record
in records
) {
35 checked { sum += values[record];}
43 case AggregateType
.Mean
:
44 Double meanSum
= (Double
)defaultValue
;
46 foreach (int record
in records
) {
49 checked { meanSum += (Double)values[record];}
55 checked {mean = (Double)(meanSum / 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
) {
71 dsum
+= (double)values
[record
];
72 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 Double min
= Double
.MaxValue
;
98 for (int i
= 0; i
< records
.Length
; i
++) {
99 int record
= records
[i
];
102 min
=Math
.Min(values
[record
], min
);
110 case AggregateType
.Max
:
111 Double max
= Double
.MinValue
;
112 for (int i
= 0; i
< records
.Length
; i
++) {
113 int record
= records
[i
];
116 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(Double
));
138 throw ExceptionBuilder
.AggregateException(kind
, DataType
);
141 override public int Compare(int recordNo1
, int recordNo2
) {
142 Double valueNo1
= values
[recordNo1
];
143 Double valueNo2
= values
[recordNo2
];
145 if (valueNo1
== defaultValue
|| valueNo2
== defaultValue
) {
146 int bitCheck
= CompareBits(recordNo1
, recordNo2
);
150 return valueNo1
.CompareTo(valueNo2
); // not simple, checks Nan
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 if (IsNull(recordNo
)) {
164 Double valueNo1
= values
[recordNo
];
165 if ((defaultValue
== valueNo1
) && IsNull(recordNo
)) {
168 return valueNo1
.CompareTo((Double
)value);
171 public override object ConvertValue(object value) {
172 if (NullValue
!= value) {
174 value = ((IConvertible
)value).ToDouble(FormatProvider
);
183 override public void Copy(int recordNo1
, int recordNo2
) {
184 CopyBits(recordNo1
, recordNo2
);
185 values
[recordNo2
] = values
[recordNo1
];
188 override public Object
Get(int record
) {
189 Double
value = values
[record
];
190 if (value != defaultValue
) {
193 return GetBits(record
);
196 override public void Set(int record
, Object
value) {
197 System
.Diagnostics
.Debug
.Assert(null != value, "null value");
198 if (NullValue
== value) {
199 values
[record
] = defaultValue
;
200 SetNullBit(record
, true);
203 values
[record
] = ((IConvertible
)value).ToDouble(FormatProvider
);
204 SetNullBit(record
, false);
208 override public void SetCapacity(int capacity
) {
209 Double
[] newValues
= new Double
[capacity
];
210 if (null != values
) {
211 Array
.Copy(values
, 0, newValues
, 0, Math
.Min(capacity
, values
.Length
));
214 base.SetCapacity(capacity
);
217 override public object ConvertXmlToObject(string s
) {
218 return XmlConvert
.ToDouble(s
);
221 override public string ConvertObjectToXml(object value) {
222 return XmlConvert
.ToString((Double
) value);
225 override protected object GetEmptyStorage(int recordCount
) {
226 return new Double
[recordCount
];
229 override protected void CopyValue(int record
, object store
, BitArray nullbits
, int storeIndex
) {
230 Double
[] typedStore
= (Double
[]) store
;
231 typedStore
[storeIndex
] = values
[record
];
232 nullbits
.Set(storeIndex
, IsNull(record
));
235 override protected void SetStorage(object store
, BitArray nullbits
) {
236 values
= (Double
[]) store
;
237 SetNullStorage(nullbits
);