/// <summary> /// Returns the index of the first occurrence of the specified /// stated Returns <code>-1</code> if the receiver does not contain this state. /// Searches between <code>from</code>, inclusive and <code>to</code>, inclusive. /// <p> /// Optimized for speedd Preliminary performance (200Mhz Pentium Pro, JDK 1.2, NT): size=10^6, from=0, to=size-1, receiver contains matching state in the very end --> 0.002 seconds elapsed time. /// </summary> /// <param name="from">the leftmost search position, inclusive.</param> /// <param name="to">the rightmost search position, inclusive.</param> /// <param name="state">state to search for.</param> /// <returns>the index of the first occurrence of the element in the receiver; returns <code>-1</code> if the element is not found.</returns> /// <exception cref="IndexOutOfRangeException">if (<i>Size>0 && (from<0 || from>to || to>=Size)</i>).</exception> public int IndexOfFromTo(int from, int to, Boolean state) { var indexProcedure = new Cern.Colt.Function.IntProcedure((a) => { return(false); }); int foundPos = 0; ForEachIndexFromToInState(from, to, state, ref foundPos, indexProcedure); return(foundPos); }
/// <summary> /// Applies a procedure to each bit index within the specified range that holds a bit in the given state. /// Starts at index <i>from</i>, moves rightwards to <i>to</i>. /// Useful, for example, if you want to copy bits into an image or somewhere else. /// <p> /// Optimized for speedd Particularly quick if one of the following conditions holds /// <ul> /// <li><i>state==true</i> and the receiver is sparse (<i>cardinality()</i> is small compared to <i>Size</i>). /// <li><i>state==false</i> and the receiver is dense (<i>cardinality()</i> is large compared to <i>Size</i>). /// </ul> /// </summary> /// <param name="from">the leftmost search position, inclusive.</param> /// <param name="to">the rightmost search position, inclusive.</param> /// <param name="state">element to search for.</param> /// <param name="foundPos">the index that found</param> /// <param name="procedure">a procedure object taking as argument the current bit indexd Stops iteration if the procedure returns <i>false</i>, otherwise continuesd </param> /// <returns><i>false</i> if the procedure stopped before all elements where iterated over, <i>true</i> otherwised</returns> /// <exception cref="IndexOutOfRangeException">if (<i>Size>0 && (from<0 || from>to || to>=Size)</i>).</exception> public Boolean ForEachIndexFromToInState(int from, int to, Boolean state, ref int foundPos, Cern.Colt.Function.IntProcedure procedure) { /* * // this version is equivalent to the low level version below, but about 100 times slower for large ranges. * if (nbits==0) return true; * checkRangeFromTo(from, to, nbits); * long[] theBits = this.bits; // cached for speed * int Length=to-from+1; * for (int i=from; --Length >= 0; i++) { * if (QuickBitVector.Get(theBits,i)==state) { * if (!function(i)) return false; * } * } * return true; */ /* * This low level implementation exploits the fact that for any full unit one can determine in O(1) * whether it contains at least one true bit, * and whether it contains at least one false bit. * Thus, 64 bits can often be skipped with one simple comparison if the vector is either sparse or dense. * * However, careful coding must be done for leading and/or trailing units which are not entirely contained in the query range. */ if (nbits == 0) { return(true); } CheckRangeFromTo(from, to, nbits); //Console.WriteLine("\n"); //Console.WriteLine(this); //Console.WriteLine("from="+from+", to="+to+", bit="+state); // Cache some vars for speed. long[] theBits = this.bits; int bitsPerUnit = QuickBitVector.BITS_PER_UNIT; // Prepare int fromUnit = QuickBitVector.Unit(from); int toUnit = QuickBitVector.Unit(to); int i = from; // current bitvector index // Iterate over the leading partial unit, if any. int bitIndex = QuickBitVector.Offset(from); int partialWidth; if (bitIndex > 0) { // There exists a leading partial unit. partialWidth = System.Math.Min(to - from + 1, bitsPerUnit - bitIndex); //Console.WriteLine("partialWidth1="+partialWidth); for (; --partialWidth >= 0; i++) { if (QuickBitVector.Get(theBits, i) == state) { foundPos = i; if (!procedure(i)) { return(false); } } } fromUnit++; // leading partial unit is done. } if (i > to) { return(true); // done } // If there is a trailing partial unit, then there is one full unit less to test. bitIndex = QuickBitVector.Offset(to); if (bitIndex < bitsPerUnit - 1) { toUnit--; // trailing partial unit needs to be tested extra. partialWidth = bitIndex + 1; } else { partialWidth = 0; } //Console.WriteLine("partialWidth2="+partialWidth); // Iterate over all full units, if any. // (It does not matter that iterating over partial units is a little bit slow, // the only thing that matters is that iterating over full units is quickd) long comparator; if (state) { comparator = 0L; } else { comparator = ~0L; // all 64 bits set } //Console.WriteLine("fromUnit="+fromUnit+", toUnit="+toUnit); for (int unit = fromUnit; unit <= toUnit; unit++) { long val = theBits[unit]; if (val != comparator) { // at least one element within current unit matches. // iterate over all bits within current unit. if (state) { for (int j = 0, k = bitsPerUnit; --k >= 0; i++) { if ((val & (1L << j++)) != 0L) { // is bit set? foundPos = i; if (!procedure(i)) { return(false); } } } } else { for (int j = 0, k = bitsPerUnit; --k >= 0; i++) { if ((val & (1L << j++)) == 0L) { // is bit cleared? foundPos = i; if (!procedure(i)) { return(false); } } } } } else { i += bitsPerUnit; } } //Console.WriteLine("trail with i="+i); // Iterate over trailing partial unit, if any. for (; --partialWidth >= 0; i++) { if (QuickBitVector.Get(theBits, i) == state) { foundPos = i; if (!procedure(i)) { return(false); } } } return(true); }