Ejemplo n.º 1
0
        public void Evaluate(int spreadMax)
        {
            // Check if any inputs changed (important for string)
            if (!StreamUtils.AnyChanged(FDataIn, FSelectIn))
            {
                return;
            }
            spreadMax = StreamUtils.GetSpreadMax(FDataIn, FSelectIn);

            // Early exit
            if (spreadMax == 0)
            {
                FDataOut.Length        = 0;
                FFormerSliceOut.Length = 0;
                return;
            }

            // In case nothing changed also do an early exit - important if T is a string or a reference type
            if (!FDataIn.IsChanged && !FSelectIn.IsChanged)
            {
                return;
            }

            // Fetch readers and writers
            using (var dataReader = FDataIn.GetCyclicReader())
                using (var selectReader = FSelectIn.GetCyclicReader())
                    using (var dataWriter = FDataOut.GetDynamicWriter())
                        using (var formerSliceWriter = FFormerSliceOut.GetDynamicWriter())
                        {
                            // Grab buffers from pool
                            var dataInBuffer = MemoryPool <T> .GetArray();

                            var dataOutBuffer = MemoryPool <T> .GetArray();

                            var selectBuffer = MemoryPool <int> .GetArray();

                            var sliceBuffer = MemoryPool <int> .GetArray();

                            try
                            {
                                var numSlicesToRead = spreadMax;
                                var offset          = 0;
                                var formerSlice     = 0;
                                while (numSlicesToRead > 0)
                                {
                                    var blockSize = Math.Min(StreamUtils.BUFFER_SIZE, numSlicesToRead);
                                    dataReader.Read(dataInBuffer, 0, blockSize);
                                    selectReader.Read(selectBuffer, 0, blockSize);

                                    // This loop iterates through the input data
                                    for (int i = 0; i < blockSize; i++)
                                    {
                                        var data   = dataInBuffer[i];
                                        var select = selectBuffer[i];

                                        // This loop replicates the input data on the output select times
                                        for (int j = 0; j < select; j++)
                                        {
                                            // Buffer result data
                                            dataOutBuffer[offset] = data;
                                            sliceBuffer[offset]   = formerSlice;
                                            offset++;

                                            // Write data out if buffer is full
                                            if (offset == StreamUtils.BUFFER_SIZE)
                                            {
                                                dataWriter.Write(dataOutBuffer, 0, StreamUtils.BUFFER_SIZE);
                                                formerSliceWriter.Write(sliceBuffer, 0, StreamUtils.BUFFER_SIZE);
                                                offset = 0;
                                            }
                                        }

                                        formerSlice++;
                                    }

                                    numSlicesToRead -= blockSize;
                                }
                                // Write any buffered output data left
                                if (offset > 0)
                                {
                                    dataWriter.Write(dataOutBuffer, 0, offset);
                                    formerSliceWriter.Write(sliceBuffer, 0, offset);
                                }
                            }
                            finally
                            {
                                MemoryPool <T> .PutArray(dataInBuffer);

                                MemoryPool <T> .PutArray(dataOutBuffer);

                                MemoryPool <int> .PutArray(selectBuffer);

                                MemoryPool <int> .PutArray(sliceBuffer);
                            }
                        }
        }