/// <summary>
        /// Retains (keeps) only the elements in the receiver that are contained in the specified other list.
        /// In other words, removes from the receiver all of its elements that are not contained in the
        /// specified other listd
        /// <summary>
        /// <param name="other">the other list to test against.</param>
        /// <returns><code>true</code> if the receiver changed as a result of the call.</returns>
        public virtual Boolean RetainAll(AbstractBooleanList other)
        {
            if (other.Size == 0)
            {
                if (_size == 0)
                {
                    return(false);
                }
                SetSizeRaw(0);
                return(true);
            }

            int limit = other.Size - 1;
            int j     = 0;

            for (int i = 0; i < _size; i++)
            {
                if (other.IndexOfFromTo(GetQuick(i), 0, limit) >= 0)
                {
                    SetQuick(j++, GetQuick(i));
                }
            }

            Boolean modified = (j != _size);

            SetSizeRaw(j);
            return(modified);
        }
        /// <summary>
        /// Retains (keeps) only the _elements in the receiver that are contained in the specified other list.
        /// In other words, removes from the receiver all of its _elements that are not contained in the
        /// specified other listd
        /// <summary>
        /// <param name="other">the other list to test against.</param>
        /// <returns><code>true</code> if the receiver changed as a result of the call.</returns>
        public override Boolean RetainAll(AbstractBooleanList other)
        {
            // overridden for performance only.
            if (!(other is BooleanArrayList))
            {
                return(base.RetainAll(other));
            }

            /* There are two possibilities to do the thing
             * a) use other.IndexOf(..d)
             * b) sort other, then use other.BinarySearch(..d)
             *
             * Let's try to figure out which one is fasterd Let M=Size, N=other.Size, then
             * a) takes O(M*N) steps
             * b) takes O(N*logN + M*logN) steps (sorting is O(N*logN) and binarySearch is O(logN))
             *
             * Hence, if N*logN + M*logN < M*N, we use b) otherwise we use a).
             */
            int limit = other.Size - 1;
            int j     = 0;

            Boolean[] the_elements = _elements;
            int       mySize       = Size;

            double N = (double)other.Size;
            double M = (double)mySize;

            if ((N + M) * Cern.Jet.Math.Arithmetic.Log2(N) < M * N)
            {
                // it is faster to sort other before searching in it
                BooleanArrayList sortedList = (BooleanArrayList)other.Clone();
                sortedList.QuickSort();

                for (int i = 0; i < mySize; i++)
                {
                    if (sortedList.BinarySearchFromTo(the_elements[i], 0, limit) >= 0)
                    {
                        the_elements[j++] = the_elements[i];
                    }
                }
            }
            else
            {
                // it is faster to search in other without sorting
                for (int i = 0; i < mySize; i++)
                {
                    if (other.IndexOfFromTo(the_elements[i], 0, limit) >= 0)
                    {
                        the_elements[j++] = the_elements[i];
                    }
                }
            }

            Boolean modified = (j != mySize);

            SetSize(j);
            return(modified);
        }