public void insert(int pos, T obj)
	{
		if (count == arr.length) {
			// time to grow the array
			if (increment == 0) throw new UnsupportedOperationException(getClass().getName()+"/"+clss.getName()+" has max capacity="+arr.length);
			grow(increment);
		}

		if (pos == count) {
			// append at tail - checking for this first means we take care of incrementing tail on first element (when it might be -1)
			if (++tail == arr.length) tail = 0;
			arr[tail] = obj;
		} else if (pos == 0) {
			// prepend - the Head pointer simply retreats, to avoid any copying or shifting
			if (head-- == 0) head = arr.length - 1;
			arr[head] = obj;
		} else {
			// yes, if we grew the array above, we will do yet another copy here, but Grows are presumed infrequent
			int physpos = physicalIndex(pos);
			if (head == 0 || physpos < head) {
				// shift tail segment up - physpos<head means list has already wrapped, and either way, above grow() means tail has room to advance
				tail++;
				System.arraycopy(arr, physpos, arr, physpos + 1, tail - physpos);
			} else {
				// list is a single segment, offset from start of array - shift down the leading elements to make room for the new one
				System.arraycopy(arr, head, arr, head - 1, physpos - head);
				head--;
				physpos--;
			}
			arr[physpos] = obj;
		}
		count++;
	}