//<script type="text/javascript">
//
// JavaScript STL
//
// Free Software Licence:
// This software is intended for free use for personal and comercial use.
// No Warranty:
// Because this software is licenced free of charge, there is no warranty
// expressed or implied for any code contained within this file.
// Guyon Roche

function STD()
{
	// Do nothing
}

STD.prototype.map = function(less)
{
	return new STDMap(less);
}
STD.prototype.multimap = function(less)
{
	return new STDMultiMap(less);
}
STD.prototype.set = function(less)
{
	return new STDSet(less);
}
STD.prototype.multiset = function(less)
{
	return new STDMultiSet(less);
}
STD.prototype.list = function()
{
	return new STDList();
}
STD.prototype.vector = function()
{
	return new STDVector();
}
STD.prototype.deque = function()
{
	return new STDDeque();
}
STD.prototype.equal_to = 
{
	// standard equal_to behaviour is to use == operator
	fn:function(a,b)
	{
		return a == b;
	} 
};
STD.prototype.greater = 
{
	// standard greater behaviour is to use > operator
	fn:function(a,b)
	{
		return a > b;
	} 
};
STD.prototype.greater_equal = 
{
	// standard greater_equal behaviour is to use >= operator
	fn:function(a,b)
	{
		return a >= b;
	} 
};
STD.prototype.less = 
{
	// standard less behaviour is to use < operator
	fn:function(a,b)
	{
		return a < b;
	} 
};
STD.prototype.less_equal = 
{
	// standard less_equal behaviour is to use <= operator
	fn:function(a,b)
	{
		return a <= b;
	} 
};
STD.prototype.hash = 
{
	// standard hash behaviour is to assume value is already an integer
	fn:function(a)
	{
		return a;
	} 
};
// create a reference object referencing a value
STD.prototype.ref = function(v)
{
	return {value:v};
}
// create a functor to operate on references
STD.prototype.deRef = function(ftor)
{
	return { functor:ftor, fn:function(a,b){return this.functor(a.value,b.value);}};
}

// useful function to test whether an object is an iterator
STD.prototype.isIterator = function(it,bMyType,bMine)
{
	// test whether it is an iterator, 
	// options: if it is also a list type, if it is for this list
	if ( !it ) return false;
	
	// assumes all iterators have the following property
	if ( !it.isIterator ) return false;
	
	// also that to be the same type, it has a type property
	if ( bMyType && (it.type != this.type) ) return false;
	
	// and to be contained in this, it has a container property
	if ( bMine && (it.container !== this) ) return false;
	
	return true;
}

var std = new STD();

//=============================================================================
// STDLinkIterator
// An iterator for linked nodes
function STDLinkIterator(container,node,bForward,type)
{
	this.container = container;
	this.node = node;
	this.bForward = bForward;
	this.type = type;
	
	this.item = node.item;
}
STDLinkIterator.prototype.clone = function()
{
	return new STDLinkIterator(this.container,this.node,this.bForward,this.type);
}
STDLinkIterator.prototype.isIterator = true;
STDLinkIterator.prototype.incImpl = function(pos, nIncrement, bF)
{
	if ( bF ) while ( nIncrement-- && pos.next ) pos = pos.next;
	else while ( nIncrement-- && pos.prev ) pos = pos.prev;
	return pos;
}
STDLinkIterator.prototype.increment = function(nIncrement)
{
	if ( arguments.length == 0 ) nIncrement = 1;
	this.node = this.incImpl(this.node, nIncrement, this.bForward);
	this.item = this.node.item;
}
STDLinkIterator.prototype.decrement = function(nDecrement)
{
	if ( arguments.length == 0 ) nDecrement = 1;
	this.node = this.incImpl(this.node, nDecrement, !this.bForward);
	this.item = this.node.item;
}
STDLinkIterator.prototype.minus = function(other)
{
	var n = 0;
	var pos = other.node;
	while ( (pos !== this.node) && !pos.bSentinel )
	{
		n++;
		pos = this.incImpl(pos, 1, this.bForward);
	}
	return n;
}
STDLinkIterator.prototype.equal_to = function(other)
{
	return (this.node === other.node);
}
STDLinkIterator.prototype.insert = function(value)
{
	var it = this.container.insert(this,value);
	this.node = it.node;
	this.item = it.item;
}

//=============================================================================
// STDTree
// basic associative container.
// wraps RBTree to provide more STL type interface

function STDTree()
{
}
STDTree.prototype.initialise = function()
{
	// initialise the tree.
	this.tree = new RBTree(this.less);
}
STDTree.prototype.iterator = function(node,bForward)
{
	if ( arguments.length == 1 ) bForward = true;
	return new STDLinkIterator(this,node,bForward,this.type);	
}
STDTree.prototype.isIterator = STD.prototype.isIterator;
STDTree.prototype.createItem = function(key)
{
	return key;
}
STDTree.prototype.begin = function()
{
	// return iterator at start of collection
	return this.iterator(this.tree.head.next);
}
STDTree.prototype.clear = function()
{
	// remove all items from collection
	this.tree = new RBTree(this.less);
}
STDTree.prototype.count = function(key)
{
	// count the number of items that match key
	var lb = this.lower_bound(key);
	var ub = this.upper_bound(key);
	return ub.minus(lb);
}
STDTree.prototype.empty = function()
{
	// return true if no items contained.
	return this.tree.nSize == 0;
}
STDTree.prototype.end = function()
{
	// return iterator one step beyond the last item
	return this.iterator(this.tree.tail);
}
STDTree.prototype.equal_range = function(key)
{
	// return lower and upper bounds of key
	var lb = this.lower_bound(key);
	var ub = this.upper_bound(key);
	return {first:lb,second:ub};
}
STDTree.prototype.eraseImpl = function(nBegin, nEnd)
{
	while ( nBegin !== nEnd )
	{
		nBegin = this.tree.remove(nBegin);
	}
	return nBegin;
}
STDTree.prototype.erase = function(a,b)
{
	// erase items from the collection
	if ( arguments.length == 0 ) return;

	if ( !this.isIterator(a,true,true) )
	{
		// a is a key
		var value = this.createItem(a);
		var lb = this.tree.lower_bound(value);
		var ub = this.tree.upper_bound(value);
		return this.iterator(this.eraseImpl(lb,ub));
	}
	
	// if b not specified, set it to one past a
	if ( arguments.length == 1 )
	{
		if ( !a.node.bSentinel ) return this.iterator(this.eraseImpl(a.node, a.node.next));
		else return this.end();
	}
	else
	{
		return this.iterator(this.eraseImpl(a.node, b.node));
	}
}
STDTree.prototype.find = function(key)
{
	// return iterator pointing to matching item, or end() if not found
	var item = this.createItem(key);
	var lb = this.tree.lower_bound(item);
	if ( this.less.fn(item,lb.item) ) return this.end();
	else return this.iterator(lb);
}
STDTree.prototype.insertReturn = function(item, bIterator, bPair, bSecond)
{
	// private function to return the correct type of object for 
	// insert(). This can be either the item, an iterator to the
	// item, or a pair containing the item and a boolean value.
	if ( bIterator == undefined ) bIterator = false;
	if ( bPair == undefined ) bPair = false;
	if ( bSecond == undefined ) bSecond = false;
	if ( bIterator && bPair ) return {first:this.iterator(item),second:bSecond};
	else if ( bIterator ) return this.iterator(item);
	else return item;
}
STDTree.prototype.insertImpl = function(hint, value, bIterator, bPair)
{
	// private function to insert a value will an optionally supplied
	// hint position.

	// test hint
	if ( hint && this.less.fn(value,hint.item) ) hint = null;
	else if ( hint && !hint.next.bSentinel && this.less.fn(hint.next.item,value) ) hint = null;
	
	if ( this.bMultiContainer )
	{
		// always insert into multi container
		return this.insertReturn(this.tree.insert(value,hint),bIterator);
	}
	else
	{
		// test whether item or key is unique
		if ( !hint )
		{
			hint = this.tree.lower_bound(value);
			if ( !hint.bSentinel && !this.less.fn(value,hint.item) )
			{
				return this.insertReturn(hint, bIterator, bPair, false);
			}
			
			// by preference, chose the node just before the insertion point
			if ( !hint.bSentinel && !hint.prev.bSentinel ) hint = hint.prev;
		}
		else
		{
			if ( !this.less.fn(hint.item,value) )
			{
				return this.insertReturn(hint, bIterator, bPair, false);
			}
			if ( !hint.next.bSentinel && !this.less.fn(value,hint.next.item) )
			{
				return this.insertReturn(hint.next, bIterator, bPair, false);
			}
		}
		var node = this.tree.insert(value,hint);
		return this.insertReturn(node, bIterator, bPair, true);
	}
}
STDTree.prototype.insert = function(a,b)
{
	// insert item(s) into collection
	if ( arguments.length == 0 ) return;
	
	var node = null;
	var hint;
	if ( arguments.length == 1 )
	{
		// case 1: a is value type
		return this.insertImpl(null, a, true, true);
	}
	
	if ( this.isIterator(a) && this.isIterator(b) )
	{
		// case 2: a and b are input iterators. Insert [a,b)
		hint = null;
		a = a.clone();
		while ( !a.equal_to(b) )
		{
			hint = this.insertImpl(hint,a.item, false);
			a.increment();
		}
	}
	
	if ( this.isIterator(a,true,true) )
	{
		// case 3: a is a hint. Test and insert,
		return this.insertImpl(a.node,b,true, false);
	}
}
STDTree.prototype.key_comp = function()
{
	return this.less;
}
STDTree.prototype.lower_bound = function(key)
{
	var node = this.tree.lower_bound(this.createItem(key));
	return this.iterator(node);
}
STDTree.prototype.rbegin = function()
{
	return this.iterator(this.tree.tail.prev,false);
}
STDTree.prototype.rend = function()
{
	return this.iterator(this.tree.head,false);
}
STDTree.prototype.size = function()
{
	return this.tree.nSize;
}
STDTree.prototype.swap = function(other)
{
	var tree = this.tree;
	this.tree = other.tree;
	other.tree = tree;
	
	var less = this.less;
	this.less = other.less;
	other.less = less;
}
STDTree.prototype.upper_bound = function(key)
{
	var node = this.tree.upper_bound(this.createItem(key));
	return this.iterator(node);
}
STDTree.prototype.value_comp = function()
{
	return this.less;
}

//=============================================================================
// STDSet
// - an associative container
// - reversible
// - sorted
// - unique
function STDSet(less)
{
	// initialise map settings
	this.type = "set";
	if ( less ) this.less = less;
	else this.less = STD.prototype.less;
	this.bMultiContainer = false;

	// initialise STDTree settings
	this.initialise();
}

// inherit behaviour from STDTree
STDSet.prototype = STDTree.prototype;

//=============================================================================
// STDMultiSet
function STDMultiSet(less)
{
	// initialise map settings
	this.type = "multiset";
	if ( less ) this.less = less;
	else this.less = STD.prototype.less;
	this.bMultiContainer = true;

	// initialise STDTree settings
	this.initialise();
}

// inherit behaviour from STDTree
STDMultiSet.prototype = STDTree.prototype;


//=============================================================================
// STDMapLess
// helper class to STDMap
function STDMapLess(less)
{
	if ( less ) this.less = less;
}
STDMapLess.prototype.fn = function(a,b)
{
	return this.less.fn(a.first,b.first);
}
STDMapLess.prototype.less = STD.prototype.less;

//=============================================================================
// STDMap
// - a pair associative container (key and value)
// - reversible
// - sorted
// - unique
function STDMap(less)
{
	// add special map behaviour
	this.createItem = STDMap_createItem;
	this.key_comp = STDMap_key_comp;
	this.value_comp = STDMap_key_comp;
	
	// initialise map settings
	this.type = "map";
	this.less = new STDMapLess(less);
	this.bMultiContainer = false;

	// initialise STDTree settings
	this.initialise();
}

// inherit behaviour from STDTree
STDMap.prototype = STDTree.prototype;

STDMap_createItem = function(key,value)
{
	return {first:key,second:value};
}
STDMap_key_comp = function()
{
	return this.less.less;
}

//=============================================================================
// STDMultiMap
// - a pair associative container (key and value)
// - reversible
// - sorted
function STDMultiMap(less)
{	
	// add special map behaviour
	this.createItem = STDMap_createItem;
	this.key_comp = STDMap_key_comp;
	this.value_comp = STDMap_key_comp;
	
	// initialise map settings
	this.type = "multimap";
	this.less = new STDMapLess(less);
	this.bMultiContainer = true;

	// initialise STDTree settings
	this.initialise();
}

// inherit behaviour from STDTree
STDMultiMap.prototype = STDTree.prototype;

//=============================================================================
// STDList
// - an ordered container
// - reversible
function STDList()
{
	this.head = {item:"head",prev:null,bSentinel:true};
	this.tail = {item:"tail",tail:null,bSentinel:true};
	this.clear();
}
STDList.prototype.type = "list";
STDList.prototype.createNode = function(item)
{
	// create a leaf node containing the item
	return {item:item,prev:null,next:null};
}
STDList.prototype.insertNode = function(node,prev,next)
{
	// insert a node between prev and next nodes
	prev.next = node;
	node.prev = prev;
	next.prev = node;
	node.next = next;
	this.nSize++;
}
STDList.prototype.removeNode = function(node)
{
	// remove a node from its current position
	node.prev.next = node.next;
	node.next.prev = node.prev;
	this.nSize--;
}
STDList.prototype.iterator = function(node,bForward)
{
	if ( arguments.length == 1 ) bForward = true;
	return new STDLinkIterator(this,node,bForward,this.type);
}
STDList.prototype.isIterator = STD.prototype.isIterator;
STDList.prototype.assign = function(a,b)
{
	// replace list contents with inputs
	this.clear();
	
	var i = this.head;
	var node;
	if ( this.isIterator(a) && this.isIterator(b) )
	{
		// insert range [a,b)
		while ( !a.equal_to(b) )
		{
			node = this.createNode(a.item);
			i.next = node;
			node.prev = i;
			i = node;	
			this.nSize++;
			a.increment();
		}
	}
	else
	{
		// insert value b, a times
		while ( a > 0 )
		{
			node = this.createNode(b);
			i.next = node;
			node.prev = i;
			i = node;	
			this.nSize++;	
		}
	}
	this.tail.prev = i;
	i.next = this.tail;
}
STDList.prototype.back = function()
{
	// return the last element (or undefined if there isn't one)
	return (this.nSize > 0) ? this.tail.prev.item : undefined;
}
STDList.prototype.begin = function()
{
	// return iterator at start of list
	return this.iterator(this.head.next);
}
STDList.prototype.clear = function()
{
	// remove all elements from list
	this.head.next = this.tail;
	this.tail.prev = this.head;
	this.nSize = 0;
}
STDList.prototype.empty = function()
{
	return this.nSize == 0;
}
STDList.prototype.end = function()
{
	return this.iterator(this.tail);
}
STDList.prototype.erase = function(begin,end)
{
	var a,b;
	a = begin.node;
	if ( this.isIterator(end) ) b = end.node;
	else b = a.next;

	var prev = a.prev;
	while ( a !== b )
	{
		this.nSize--;
		a = a.next;
	}
	prev.next = b;
	b.prev = prev;
}
STDList.prototype.front = function()
{
	// return value at start of list (or undefined if there isn't one)
	return (this.nSize > 0) ? this.head.next.item : undefined;
}
STDList.prototype.insert = function(where,a,b)
{
	var next = where.node;
	var prev = next.prev;
	// insert an item or items into the list
	if ( arguments.length == 2 )
	{
		node = this.createNode(a);
		this.insertNode(node,where.node.prev,where.node);
	}
	else
	{
		if ( this.isIterator(a) && this.isIterator(b) )
		{
			while ( !a.equal_to(b) )
			{
				node = this.createNode(a.item);
				this.insertNode(node,prev,null);
				a.increment();
			}
		}
		else
		{
			while ( a > 0 )
			{
				node = this.createNode(b);
				this.insertNode(node,prev,null);
				a--;
			}
		}
		next.prev = prev;
		prev.next = next;
	}
}
STDList.prototype.merge = function(right,less)
{
	// merge items from another list
	// both lists must already be ordered by less
	this.mergeItems(this.head,this.tail,
					this.head.next,this.tail,false,
					right.head.next,right.tail,true,
					less ? less : STD.prototype.less);
	
}
STDList.prototype.pop_back = function()
{
	// removes last element from list
	this.removeNode(this.tail.prev);
}
STDList.prototype.pop_front = function()
{
	// removes first element from list
	this.removeNode(this.head.next);
}
STDList.prototype.push_back = function(value)
{
	// add item to end of list
	var node = this.createNode(value);
	this.insertNode(node,this.tail.prev,this.tail);
}
STDList.prototype.push_front = function(value)
{
	// add item to front of list
	var node = this.createNode(value);
	this.insertNode(node,this.head,this.head.next);
}
STDList.prototype.rbegin = function()
{
	// return reverse iterator at end of list
	return this.iterator(this.tail.prev,false);
}
STDList.prototype.remove = function(value)
{
	// remove all elements that match a value
	var next;
	for ( var i = this.head.next; i != this.tail; i = next )
	{
		next = i.next;
		if ( this.equal_to.fn(i.item,value) ) this.removeNode(i);
	}
}
STDList.prototype.remove_if = function(pred)
{
	// remove all elements for which pred.fn(value) is true
	var next;
	for ( var i = this.head.next; i != this.tail; i = next )
	{
		next = i.next;
		if ( pred.fn(i.item,value) ) this.removeNode(i);
	}	
}
STDList.prototype.rend = function()
{
	// return reverse iterator at head of list
	return this.iterator(this.head,false);
}
STDList.prototype.resize = function(nSize, value)
{
	while ( nSize < this.nSize ) this.pop_back();
	while ( nSize > this.nSize ) this.push_back(value);
}
STDList.prototype.reverse = function()
{
	// swap items around
	var n = Math.floor(this.nSize / 2);
	var h = this.head.next;
	var t = this.tail.prev;
	while ( n > 0 )
	{
		var tmp = h.item;
		h.item = t.item;
		t.item = tmp;
		n--;
	}
}
STDList.prototype.size = function()
{
	return this.nSize;
}
STDList.prototype.mergeItems = function(wBefore,wAfter,aBegin,aEnd,bCountA,bBegin,bEnd,bCountB,less)
{
	var i = wBefore;
	var a = aBegin;
	var b = bBegin;
	while ( (a !== aEnd) || (b !== bEnd) )
	{	
		var bA;
		if ( a === aEnd ) bA = false;
		else if ( b === bEnd ) bA = true;
		else bA = less.fn(a,b);

		if ( bA )
		{
			i.next = a;
			a.prev = i;
			i = a;
			a = a.next;
			if ( bCountA ) this.nSize++;
		}
		else 
		{
			i.next = b;
			b.prev = i;
			i = b;
			b = b.next;
			if ( bCountB ) this.nSize++;
		}
	}
	i.next = wAfter;
	wAfter.prev = i;
}
STDList.prototype.mergeSort = function(begin,end,nCount,less)
{
	// nothing to do if zero or one items
	if ( nCount < 2 ) return;
	
	// if just two items, swap them
	if ( nCount == 2 )
	{
		var other = begin.next;
		if ( less.fn(other, begin) )
		{
			var temp = begin.item;
			begin.item = other.item;
			other.item = temp;
		}
		return;
	}
	
	// else find the mid point and recurse
	var nHalf = Math.floor(nCount/2);
	var mid = begin;
	for ( var i = 0; i < nHalf; i++ ) mid = mid.next;
	this.mergeSort(begin,mid,nHalf,less);
	this.mergeSort(mid,end,nCount-nHalf,less);
	
	// now merge the two
	this.mergeItems(begin.prev,end,begin,mid,false,mid,end,false,less);
}
STDList.prototype.sort = function(less)
{
	this.mergeSort(this.head.next,this.tail,this.nSize,less?less:STD.prototype.less);
}
STDList.prototype.splice = function(where,right,begin,end)
{
	switch ( arguments.length )
	{
	case 2:
		begin = right.begin();
		end = right.end();
		break;
	case 3:
		end = right.end();
		break;
	case 4:
		break;
	}
	var lBegin = begin.node;
	var lEnd = end.node;
	var lPrev = lBegin.prev;
	
	var wNext = where.node;
	var wPrev = wNext.prev;
	while ( lBegin !== lEnd )
	{
		var node = lBegin;
		lBegin = lBegin.next;
		this.insertNode(node,wPrev);
		wPrev = node;
		right.nSize--;
	}
	wNext.prev = wPrev;
	pPrev.next = wNext;

	lPrev.next = lEnd;
	lEnd.prev = lPrev;
}
STDList.prototype.swap = function(right)
{
	// swap contents with right
	var head = this.head;
	var tail = this.tail;
	var nSize = this.nSize;
	this.head = right.head;
	this.tail = right.tail;
	this.nSize = right.nSize;
	right.head = head;
	right.tail = tail;
	right.nSize = nSize;
}
STDList.prototype.unique = function(equal_to)
{
	if ( equal_to == undefined ) equal_to = STD.prototype.equal_to;
	// remove adjacent duplicate items
	for ( var i = this.head.next; i !== this.tail; i = i.next )
	{
		var iNext = i.next;
		while ( (iNext!==this.tail) && equal_to.fn(i.item,iNext.item) )
		{
			iNext = iNext.next;
			i.next = iNext;
			iNext.prev = i;
		}
	}
}
//=============================================================================
// STDVectorIterator
function STDVectorIterator(container, nIndex, bForward, type)
{
	this.container = container;
	this.data = container.data;
	this.bForward = bForward;
	this.type = type;

	this.setPos(nIndex);	
}
STDVectorIterator.prototype.clone = function()
{
	return new STDVectorIterator(this.container,this.getPos(),this.bForward,this.type);
}
STDVectorIterator.prototype.setPos = function(nIndex)
{
	delete this.item;
	this.nIndex = nIndex;
	if ( this.nIndex >= this.container.nEnd ) return;
	if ( this.nIndex < this.container.nBegin ) return;
	this.item = this.data[nIndex];
}
STDVectorIterator.prototype.getPos = function()
{
	return this.nIndex = Math.min(
		Math.max(this.nIndex,this.container.nBegin-1),
		this.container.nEnd);
}
STDVectorIterator.prototype.increment = function(value)
{
	if ( arguments.length == 0 ) value = 1;
	this.setPos(this.nIndex + (this.bForward ? value : -value));
}
STDVectorIterator.prototype.decrement = function(value)
{
	if ( arguments.length == 0 ) value = 1;
	this.setPos(this.nIndex + this.bForward ? -value : value);
}
STDVectorIterator.prototype.equal_to = function(it)
{
	return (this.container === it.container) &&
			(this.getPos() == it.getPos());
}
STDVectorIterator.prototype.isIterator = true;
STDVectorIterator.assign = function(value)
{
	if ( (this.nIndex < this.container.nEnd) &&
		 (this.nIndex >= this.container.nBegin) ) this.data[this.nIndex] = value;
}
STDVectorIterator.prototype.minus = function(other)
{
	return this.getPos() - other.getPos();
}
STDLinkIterator.prototype.insert = function(value)
{
	this.container.insert(this,value);
}

//=============================================================================
// STDVector
function STDVector()
{
	this.data = new Array();
	this.nBegin = 0;
	this.nEnd = 0;
	this.type = "vector";
}
STDVector.prototype.iterator = function(nPos,bForward)
{
	bForward = arguments.length == 1 ? true : bForward;
	return new STDVectorIterator(this,nPos,bForward,this.type);
}
STDVector.prototype.isIterator = STD.prototype.isIterator;
STDVector.prototype.assign = function(a,b)
{
	// replace list contents with inputs
	if ( this.isIterator(a) && this.isIterator(b) )
	{
		this.clear();
		while ( !a.equal_to(b) )
		{
			this.data.push(a.item);
			a.increment();
			this.nEnd++;
		}
	}
	else
	{
		this.data = new Array(a);
		this.nBegin = 0;
		this.nEnd = a;
		for ( var i = 0; i < a; i++ ) this.data[i] = b;
	}
}
STDVector.prototype.at = function(pos)
{
	return this.data[pos+this.nBegin];
}
STDVector.prototype.back = function()
{
	return this.data[this.nEnd-1];
}
STDVector.prototype.begin = function()
{
	return this.iterator(this.nBegin);
}
STDVector.prototype.capacity = function()
{
	return this.data.length;
}
STDVector.prototype.clear = function()
{
	this.data = new Array();
	this.nBegin = 0;
	this.nEnd = 0;
}
STDVector.prototype.empty = function()
{
	return this.data.length == 0;
}
STDVector.prototype.end = function()
{
	return this.iterator(this.nEnd);
}
STDVector.prototype.erase = function(first, last)
{
	var nFirst = first.getPos();
	if ( nFirst == this.nEnd ) return;
	var nLast;
	if ( arguments.length == 1 ) nLast = nFirst + 1;
	else nLast = last.getPos();
	
	var nCount = nLast - nFirst;
	this.data.splice(nFirst, nCount);
	this.nEnd -= nCount;
}
STDVector.prototype.front = function()
{
	return this.data[this.nBegin];
}
STDVector.prototype.insert = function(where,a,b)
{
	var nWhere = where.getPos();
	if ( arguments.length == 2 )
	{
		this.data.splice(nWhere,0,a);
		this.nEnd++;
		where.item = a;
		return where;
	}

	var aTail = this.data.splice(nWhere,this.nEnd-nWhere);	
	if ( this.isIterator(a) && this.isIterator(b) )
	{
		while ( !a.equal_to(b) )
		{
			this.data.push(a);
			this.nEnd++;
		}
	}
	else
	{
		for ( var i = 0; i < a; i++ ) this.data.push(b);
		this.nEnd += a;
	}
	for ( i in aTail ) this.data.push(aTail[i]);
}

STDVector.prototype.pop_back = function()
{
	if ( this.nEnd > this.nBegin ) delete this.data[--this.nEnd];
}
STDVector.prototype.push_back = function(value)
{
	this.data[this.nEnd++] = value;
}
STDVector.prototype.rbegin = function()
{
	return this.iterator(this.nEnd-1, false);
}
STDVector.prototype.rend = function()
{
	return this.iterator(this.nBegin-1,false);
}
STDVector.prototype.size = function()
{
	return this.nEnd - this.nBegin;
}
STDVector.prototype.swap = function(right)
{
	var data = this.data;
	var nBegin = this.nBegin;
	var nEnd = this.nEnd;
	
	this.data = right.data;
	this.nBegin = right.nBegin;
	this.nEnd = right.nEnd;
	
	right.data = data;
	right.nBegin = nBegin;
	right.nEnd = nEnd;
}

//=============================================================================
// STDDeque
function STDDeque()
{
	this.data = new Array();
	this.nBegin = 0;
	this.nEnd = 0;
	
	this.type = "deque";
	
	// add a few specialisations...
	this.push_front = STDDeque_push_front;
	this.pop_front = STDDeque_pop_front;
}

// inherit methods from STDVector
STDDeque.prototype = STDVector.prototype;

STDDeque_push_front = function(value)
{
	this.data[--this.nBegin] = value;
}
STDDeque_pop_front = function()
{
	if ( this.nEnd > this.nBegin ) delete this.data[this.nBegin++];
}

//=============================================================================
// STDQueue

//=============================================================================
// STDStack

//=============================================================================
// STDPriorityQueue



//</script>

