//<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>