/** {@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 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 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;
  }
 /** {@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;
 }
  /**
   * 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);
  }
  /** {@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 sum() {
    float sum = 0;

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

    return sum;
  }
  /** {@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 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 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;
  }
  /** {@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;
  }
  /**
   * 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 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 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 boolean forEach(TFloatProcedure procedure) {
   for (TFloatLink l = head; got(l); l = l.getNext()) {
     if (!procedure.execute(l.getValue())) return false;
   }
   return true;
 }