Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Core / System / Linq / Parallel / QueryOperators / Inlined / FloatSumAggregationOperator.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
7 //
8 // FloatSumAggregationOperator.cs
9 //
10 // <OWNER>[....]</OWNER>
11 //
12 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
13
14 using System.Collections.Generic;
15 using System.Diagnostics.Contracts;
16 using System.Threading;
17 #if SILVERLIGHT
18 using System.Core; // for System.Core.SR
19 #endif
20
21 namespace System.Linq.Parallel
22 {
23     /// <summary>
24     /// An inlined sum aggregation and its enumerator, for floats. 
25     /// </summary>
26     internal sealed class FloatSumAggregationOperator : InlinedAggregationOperator<float, double, float>
27     {
28
29         //---------------------------------------------------------------------------------------
30         // Constructs a new instance of a sum associative operator.
31         //
32
33         internal FloatSumAggregationOperator(IEnumerable<float> child) : base(child)
34         {
35         }
36
37         //---------------------------------------------------------------------------------------
38         // Executes the entire query tree, and aggregates the intermediate results into the
39         // final result based on the binary operators and final reduction.
40         //
41         // Return Value:
42         //     The single result of aggregation.
43         //
44
45         protected override float InternalAggregate(ref Exception singularExceptionToThrow)
46         {
47             // Because the final reduction is typically much cheaper than the intermediate 
48             // reductions over the individual partitions, and because each parallel partition
49             // will do a lot of work to produce a single output element, we prefer to turn off
50             // pipelining, and process the final reductions serially.
51             using (IEnumerator<double> enumerator = GetEnumerator(ParallelMergeOptions.FullyBuffered, true))
52             {
53                 // We just reduce the elements in each output partition.
54                 double sum = 0.0;
55                 while (enumerator.MoveNext())
56                 {
57                     checked
58                     {
59                         sum += enumerator.Current;
60                     }
61                 }
62
63                 return (float)sum;
64             }
65         }
66
67         //---------------------------------------------------------------------------------------
68         // Creates an enumerator that is used internally for the final aggregation step.
69         //
70
71         protected override QueryOperatorEnumerator<double,int> CreateEnumerator<TKey>(
72             int index, int count, QueryOperatorEnumerator<float, TKey> source, object sharedData,
73             CancellationToken cancellationToken)
74         {
75             return new FloatSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
76         }
77
78         //---------------------------------------------------------------------------------------
79         // This enumerator type encapsulates the intermediary aggregation over the underlying
80         // (possibly partitioned) data source.
81         //
82
83         private class FloatSumAggregationOperatorEnumerator<TKey> : InlinedAggregationOperatorEnumerator<double>
84         {
85             private readonly QueryOperatorEnumerator<float, TKey> m_source; // The source data.
86
87             //---------------------------------------------------------------------------------------
88             // Instantiates a new aggregation operator.
89             //
90
91             internal FloatSumAggregationOperatorEnumerator(QueryOperatorEnumerator<float, TKey> source, int partitionIndex,
92                 CancellationToken cancellationToken) :
93                 base(partitionIndex, cancellationToken)
94             {
95                 Contract.Assert(source != null);
96                 m_source = source;
97             }
98
99             //---------------------------------------------------------------------------------------
100             // Tallies up the sum of the underlying data source, walking the entire thing the first
101             // time MoveNext is called on this object.
102             //
103
104             protected override bool MoveNextCore(ref double currentElement)
105             {
106                 float element = default(float);
107                 TKey keyUnused = default(TKey);
108
109                 QueryOperatorEnumerator<float, TKey> source = m_source;
110                 if (source.MoveNext(ref element, ref keyUnused))
111                 {
112                     // We just scroll through the enumerator and accumulate the sum.
113                     double tempSum = 0.0f;
114                     int i = 0;
115                     do
116                     {
117                         if ((i++ & CancellationState.POLL_INTERVAL) == 0)
118                             CancellationState.ThrowIfCanceled(m_cancellationToken);
119
120                         tempSum += element;
121                     }
122                     while (source.MoveNext(ref element, ref keyUnused));
123
124                     // The sum has been calculated. Now just return.
125                     currentElement = tempSum;
126                     return true;
127                 }
128
129                 return false;
130             }
131
132             //---------------------------------------------------------------------------------------
133             // Dispose of resources associated with the underlying enumerator.
134             //
135
136             protected override void Dispose(bool disposing)
137             {
138                 Contract.Assert(m_source != null);
139                 m_source.Dispose();
140             }
141         }
142     }
143 }