/** {@inheritDoc} */
 public TFloatList inverseGrep(TFloatProcedure condition) {
   TFloatList ret = new TFloatLinkedList();
   for (TFloatLink l = head; got(l); l = l.getNext()) {
     if (!condition.execute(l.getValue())) ret.add(l.getValue());
   }
   return ret;
 }
 /** {@inheritDoc} */
 public void shuffle(Random rand) {
   for (int i = 0; i < size; i++) {
     TFloatLink l = getLinkAt(rand.nextInt(size()));
     removeLink(l);
     add(l.getValue());
   }
 }
  /** {@inheritDoc} */
  public int binarySearch(float value, int fromIndex, int toIndex) {
    if (fromIndex < 0) {
      throw new IndexOutOfBoundsException("begin index can not be < 0");
    }

    if (toIndex > size) {
      throw new IndexOutOfBoundsException("end index > size: " + toIndex + " > " + size);
    }

    if (toIndex < fromIndex) {
      return -(fromIndex + 1);
    }

    TFloatLink middle;
    int mid;
    int from = fromIndex;
    TFloatLink fromLink = getLinkAt(fromIndex);
    int to = toIndex;

    while (from < to) {
      mid = (from + to) >>> 1;
      middle = getLink(fromLink, from, mid);
      if (middle.getValue() == value) return mid;

      if (middle.getValue() < value) {
        from = mid + 1;
        fromLink = middle.next;
      } else {
        to = mid - 1;
      }
    }

    return -(from + 1);
  }
  /** {@inheritDoc} */
  public boolean contains(float value) {
    if (isEmpty()) return false;

    for (TFloatLink l = head; got(l); l = l.getNext()) {
      if (l.getValue() == value) return true;
    }
    return false;
  }
 /** {@inheritDoc} */
 public void transformValues(TFloatFunction function) {
   for (TFloatLink l = head; got(l); ) {
     //
     l.setValue(function.execute(l.getValue()));
     //
     l = l.getNext();
   }
 }
  /** {@inheritDoc} */
  public float removeAt(int offset) {
    TFloatLink l = getLinkAt(offset);
    if (no(l)) throw new ArrayIndexOutOfBoundsException("no elemenet at " + offset);

    float prev = l.getValue();
    removeLink(l);
    return prev;
  }
  /** {@inheritDoc} */
  public float sum() {
    float sum = 0;

    for (TFloatLink l = head; got(l); l = l.getNext()) {
      sum += l.getValue();
    }

    return sum;
  }
  /** {@inheritDoc} */
  public float get(int offset) {
    if (offset > size)
      throw new IndexOutOfBoundsException("index " + offset + " exceeds size " + size);

    TFloatLink l = getLinkAt(offset);
    //
    if (no(l)) return no_entry_value;

    return l.getValue();
  }
  /** {@inheritDoc} */
  public float min() {
    float ret = Float.POSITIVE_INFINITY;

    if (isEmpty()) throw new IllegalStateException();

    for (TFloatLink l = head; got(l); l = l.getNext()) {
      if (ret > l.getValue()) ret = l.getValue();
    }

    return ret;
  }
  /** {@inheritDoc} */
  public float set(int offset, float val) {
    if (offset > size)
      throw new IndexOutOfBoundsException("index " + offset + " exceeds size " + size);

    TFloatLink l = getLinkAt(offset);
    //
    if (no(l)) throw new IndexOutOfBoundsException("at offset " + offset);

    float prev = l.getValue();
    l.setValue(val);
    return prev;
  }
  /** {@inheritDoc} */
  public int lastIndexOf(int offset, float value) {
    if (isEmpty()) return -1;

    int last = -1;
    int count = offset;
    for (TFloatLink l = getLinkAt(offset); got(l.getNext()); l = l.getNext()) {
      if (l.getValue() == value) last = count;

      count++;
    }

    return last;
  }
  /** {@inheritDoc} */
  public boolean remove(float value) {
    boolean changed = false;
    for (TFloatLink l = head; got(l); l = l.getNext()) {
      //
      if (l.getValue() == value) {
        changed = true;
        //
        removeLink(l);
      }
    }

    return changed;
  }
  /** {@inheritDoc} */
  public int indexOf(int offset, float value) {
    int count = offset;

    TFloatLink l;
    for (l = getLinkAt(offset); got(l.getNext()); l = l.getNext()) {
      if (l.getValue() == value) return count;

      count++;
    }

    if (l != null && l.getValue() == value) return count;

    return -1;
  }
  /**
   * unlinks the give TFloatLink from the list
   *
   * @param l
   */
  private void removeLink(TFloatLink l) {
    if (no(l)) return;

    size--;

    TFloatLink prev = l.getPrevious();
    TFloatLink next = l.getNext();

    if (got(prev)) {
      prev.setNext(next);
    } else {
      // No previous we must be head
      head = next;
    }

    if (got(next)) {
      next.setPrevious(prev);
    } else {
      // No next so me must be tail
      tail = prev;
    }
    // Unlink
    l.setNext(null);
    l.setPrevious(null);
  }
  /**
   * Returns link at given absolute offset starting from link 'l' at index 'idx'
   *
   * @param l
   * @param idx
   * @param offset
   * @param next
   * @return
   */
  private static TFloatLink getLink(TFloatLink l, int idx, int offset, boolean next) {
    int i = idx;
    //
    while (got(l)) {
      if (i == offset) {
        return l;
      }

      i = i + (next ? 1 : -1);
      l = next ? l.getNext() : l.getPrevious();
    }

    return null;
  }
  /** {@inheritDoc} */
  public boolean add(float val) {
    TFloatLink l = new TFloatLink(val);
    if (no(head)) {
      head = l;
      tail = l;
    } else {
      l.setPrevious(tail);
      tail.setNext(l);
      //
      tail = l;
    }

    size++;
    return true;
  }
  /** {@inheritDoc} */
  public float[] toArray(float[] dest, int source_pos, int dest_pos, int len) {
    if (len == 0) {
      return dest; // nothing to copy
    }
    if (source_pos < 0 || source_pos >= size()) {
      throw new ArrayIndexOutOfBoundsException(source_pos);
    }

    TFloatLink tmp = getLinkAt(source_pos);
    for (int i = 0; i < len; i++) {
      dest[dest_pos + i] = tmp.getValue(); // copy
      tmp = tmp.getNext();
    }

    return dest;
  }
  /** {@inheritDoc} */
  public void fill(int fromIndex, int toIndex, float val) {
    if (fromIndex < 0) {
      throw new IndexOutOfBoundsException("begin index can not be < 0");
    }

    TFloatLink l = getLinkAt(fromIndex);
    if (toIndex > size) {
      for (int i = fromIndex; i < size; i++) {
        l.setValue(val);
        l = l.getNext();
      }
      for (int i = size; i < toIndex; i++) {
        add(val);
      }
    } else {
      for (int i = fromIndex; i < toIndex; i++) {
        l.setValue(val);
        l = l.getNext();
      }
    }
  }
  /** {@inheritDoc} */
  public TFloatList subList(int begin, int end) {
    if (end < begin) {
      throw new IllegalArgumentException("begin index " + begin + " greater than end index " + end);
    }
    if (size < begin) {
      throw new IllegalArgumentException(
          "begin index " + begin + " greater than last index " + size);
    }
    if (begin < 0) {
      throw new IndexOutOfBoundsException("begin index can not be < 0");
    }
    if (end > size) {
      throw new IndexOutOfBoundsException("end index < " + size);
    }

    TFloatLinkedList ret = new TFloatLinkedList();
    TFloatLink tmp = getLinkAt(begin);
    for (int i = begin; i < end; i++) {
      ret.add(tmp.getValue()); // copy
      tmp = tmp.getNext();
    }

    return ret;
  }
  /** {@inheritDoc} */
  public void reverse() {
    TFloatLink h = head;
    TFloatLink t = tail;
    TFloatLink prev, next, tmp;

    //
    TFloatLink l = head;
    while (got(l)) {
      next = l.getNext();
      prev = l.getPrevious();
      //
      tmp = l;
      l = l.getNext();
      //
      tmp.setNext(prev);
      tmp.setPrevious(next);
    }

    //
    head = t;
    tail = h;
  }
  void insert(int offset, TFloatLinkedList tmp) {
    TFloatLink l = getLinkAt(offset);

    size = size + tmp.size;
    //
    if (l == head) {
      // Add in front
      tmp.tail.setNext(head);
      head.setPrevious(tmp.tail);
      head = tmp.head;

      return;
    }

    if (no(l)) {
      if (size == 0) {
        // New empty list
        head = tmp.head;
        tail = tmp.tail;
      } else {
        // append
        tail.setNext(tmp.head);
        tmp.head.setPrevious(tail);
        tail = tmp.tail;
      }
    } else {
      TFloatLink prev = l.getPrevious();
      l.getPrevious().setNext(tmp.head);

      // Link by behind tmp
      tmp.tail.setNext(l);
      l.setPrevious(tmp.tail);

      tmp.head.setPrevious(prev);
    }
  }
  /** {@inheritDoc} */
  public void reverse(int from, int to) {
    if (from > to) throw new IllegalArgumentException("from > to : " + from + ">" + to);

    TFloatLink start = getLinkAt(from);
    TFloatLink stop = getLinkAt(to);
    TFloatLink prev, next;
    TFloatLink tmp = null;

    TFloatLink tmpHead = start.getPrevious();

    //
    TFloatLink l = start;
    while (l != stop) {
      next = l.getNext();
      prev = l.getPrevious();
      //
      tmp = l;
      l = l.getNext();
      //
      tmp.setNext(prev);
      tmp.setPrevious(next);
    }

    // At this point l == stop and tmp is the but last element {
    if (got(tmp)) {
      tmpHead.setNext(tmp);
      stop.setPrevious(tmpHead);
    }
    start.setNext(stop);
    stop.setPrevious(start);
  }
 /** {@inheritDoc} */
 public boolean forEach(TFloatProcedure procedure) {
   for (TFloatLink l = head; got(l); l = l.getNext()) {
     if (!procedure.execute(l.getValue())) return false;
   }
   return true;
 }
 /** {@inheritDoc} */
 public boolean forEachDescending(TFloatProcedure procedure) {
   for (TFloatLink l = tail; got(l); l = l.getPrevious()) {
     if (!procedure.execute(l.getValue())) return false;
   }
   return true;
 }