/// <summary> /// Collapses the specified full buffers (must not include partial buffer). /// </summary> /// <param name="buffers">the buffers to be collapsed (all of them must be full or partially full)</param> /// <returns>a full buffer containing the collapsed values. The buffer has accumulated weight.</returns> public DoubleBuffer Collapse(DoubleBuffer[] buffers) { //determine W int W = 0; //sum of all weights for (int i = 0; i < buffers.Length; i++) { W += buffers[i].Weight; } //determine outputTriggerPositions int k = this.NumberOfElements; long[] triggerPositions = new long[k]; for (int j = 0; j < k; j++) { triggerPositions[j] = this.NextTriggerPosition(j, W); } //do the main work: determine values at given positions in sorted sequence double[] outputValues = this.GetValuesAtPositions(buffers, triggerPositions); //mark all full buffers as empty, except the first, which will contain the output for (int b = 1; b < buffers.Length; b++) { buffers[b].Clear(); } DoubleBuffer outputBuffer = buffers[0]; outputBuffer.Values.Clear(); outputBuffer.Values.SetElements(outputValues); outputBuffer.Weight = W; return(outputBuffer); }
protected void RemoveInfinitiesFrom(int infinities, DoubleBuffer buffer) { int plusInf = 0; int minusInf = 0; // count them (this is not very clever but it's safe) Boolean even = true; for (int i = 0; i < infinities; i++) { if (even) { plusInf++; } else { minusInf++; } even = !even; } buffer.Values.RemoveFromTo(buffer.Size - plusInf, buffer.Size - 1); buffer.Values.RemoveFromTo(0, minusInf - 1); //this.totalElementsFilled -= infinities; }
/// <summary> /// Determines all values of the specified buffers positioned at the specified triggerPositions within the sorted sequence and fills them into outputValues. /// </summary> /// <param name="buffers">the buffers to be searched (all must be full or partial) </param> /// <param name="triggerPositions">the positions of elements within the sorted sequence to be retrieved</param> /// <returns>outputValues a list filled with the values at triggerPositions</returns> internal double[] GetValuesAtPositions(DoubleBuffer[] buffers, long[] triggerPositions) { //if (buffers.Length==0) //{ // throw new ArgumentException("Oops! buffer.Length==0."); //} //System.out.println("triggers="+cern.it.util.Arrays.ToString(positions)); //new List<Double>(outputValues).FillFromToWith(0, outputValues.Length-1, 0.0f); //delte the above line, it is only for testing //cern.it.util.Log.println("\nEntering getValuesAtPositions..."); //cern.it.util.Log.println("hitPositions="+cern.it.util.Arrays.ToString(positions)); // sort buffers. for (int i = buffers.Length; --i >= 0;) { buffers[i].Sort(); } // collect some infos into fast cache; for tuning purposes only. int[] bufferSizes = new int[buffers.Length]; double[][] bufferValues = new double[buffers.Length][]; int totalBuffersSize = 0; for (int i = buffers.Length; --i >= 0;) { bufferSizes[i] = buffers[i].Size; bufferValues[i] = buffers[i].Values.ToArray(); totalBuffersSize += bufferSizes[i]; //cern.it.util.Log.println("buffer["+i+"]="+buffers[i].Values); } // prepare merge of equi-distant elements within buffers into output values // first collect some infos into fast cache; for tuning purposes only. int buffersSize = buffers.Length; int triggerPositionsLength = triggerPositions.Length; // now prepare the important things. int j = 0; //current position in collapsed values int[] cursors = new int[buffers.Length]; //current position in each buffer; init with zeroes long counter = 0; //current position in sorted sequence long nextHit = triggerPositions[j]; //next position in sorted sequence to trigger output population double[] outputValues = new double[triggerPositionsLength]; if (totalBuffersSize == 0) { // nothing to output, because no elements have been filled (we are empty). // return meaningless values for (int i = 0; i < triggerPositions.Length; i++) { outputValues[i] = Double.NaN; } return(outputValues); } // fill all output values with equi-distant elements. while (j < triggerPositionsLength) { //System.out.println("\nj="+j); //System.out.println("counter="+counter); //System.out.println("nextHit="+nextHit); // determine buffer with smallest value at cursor position. double minValue = Double.PositiveInfinity; int minBufferIndex = -1; for (int b = buffersSize; --b >= 0;) { //DoubleBuffer buffer = buffers[b]; //if (cursors[b] < buffer.Length) { if (cursors[b] < bufferSizes[b]) { ///double value = buffer.Values[cursors[b]]; double value = bufferValues[b][cursors[b]]; if (value <= minValue) { minValue = value; minBufferIndex = b; } } } DoubleBuffer minBuffer = buffers[minBufferIndex]; // trigger copies into output sequence, if necessary. counter += minBuffer.Weight; while (counter > nextHit && j < triggerPositionsLength) { outputValues[j++] = minValue; //System.out.println("adding to output="+minValue); if (j < triggerPositionsLength) { nextHit = triggerPositions[j]; } } // that element has now been treated, move further. cursors[minBufferIndex]++; //System.out.println("cursors="+cern.it.util.Arrays.ToString(cursors)); } //end while (j<k) //cern.it.util.Log.println("returning output="+cern.it.util.Arrays.ToString(outputValues)); return(outputValues); }