// deque standard header -*-c++-*-
// Copyright 2009-2017 IAR Systems AB.
#ifndef _DEQUE_
#define _DEQUE_

#ifndef _SYSTEM_BUILD
  #pragma system_include
#endif

#include <xmemory>
#include <stdexcept>

namespace std {

// DEQUE PARAMETERS
#define _DEQUEMAPSIZ    8       /* minimum map size, at least 1 */
#define _DEQUESIZ       (  sizeof (value_type) <= 1 ? 16                \
                         : sizeof (value_type) <= 2 ? 8                 \
                         : sizeof (value_type) <= 4 ? 4                 \
                         : sizeof (value_type) <= 8 ? 2                 \
                         : 1)    /* elements per block (a power of 2) */

// TEMPLATE CLASS _Deque_unchecked_const_iterator
template<class _Mydeque>
class _Deque_unchecked_const_iterator
{       // iterator for nonmutable deque
public:
  typedef _Deque_unchecked_const_iterator<_Mydeque> _Myiter;
  typedef random_access_iterator_tag iterator_category;

  typedef typename _Mydeque::value_type value_type;
  typedef typename _Mydeque::size_type size_type;
  typedef typename _Mydeque::difference_type difference_type;
  typedef typename _Mydeque::const_pointer pointer;
  typedef typename _Mydeque::const_reference reference;

  _Deque_unchecked_const_iterator()
  {       // construct with null pointer
    _Mycont = 0;
    _Myoff = 0;
  }

  _Deque_unchecked_const_iterator(size_type _Off,
                                  const _Container_base12 *_Pdeque)
  {       // construct with offset _Off
    _Mycont = (_Mydeque *)_Pdeque;
    _Myoff = _Off;
  }

  reference operator*() const
  {       // return designated object
    size_type _Block = _Mycont->_Getblock(_Myoff);
    size_type _Off = _Myoff % _DEQUESIZ;
    return _Mycont->_Map[_Block][_Off];
  }

  pointer operator->() const
  {       // return pointer to class object
    return _POINTER_TO(**this);
  }

  _Myiter& operator++()
  {       // preincrement
    ++_Myoff;
    return *this;
  }

  _Myiter operator++(int)
  {       // postincrement
    _Myiter _Tmp = *this;
    ++*this;
    return _Tmp;
  }

  _Myiter& operator--()
  {       // predecrement
    --_Myoff;
    return *this;
  }

  _Myiter operator--(int)
  {       // postdecrement
    _Myiter _Tmp = *this;
    --*this;
    return _Tmp;
  }

  _Myiter& operator+=(difference_type _Off)
  {       // increment by integer
    _Myoff += _Off;
    return *this;
  }

  _Myiter operator+(difference_type _Off) const
  {       // return this + integer
    _Myiter _Tmp = *this;
    return _Tmp += _Off;
  }

  _Myiter& operator-=(difference_type _Off)
  {       // decrement by integer
    return *this += -_Off;
  }

  _Myiter operator-(difference_type _Off) const
  {       // return this - integer
    _Myiter _Tmp = *this;
    return _Tmp -= _Off;
  }

  difference_type operator-(const _Myiter& _Right) const
  {       // return difference of iterators
    return _Right._Myoff <= _Myoff
             ? _Myoff - _Right._Myoff
             : -(difference_type)(_Right._Myoff - _Myoff);
  }

  reference operator[](difference_type _Off) const
  {       // subscript
    return *(*this + _Off);
  }

  bool operator==(const _Myiter& _Right) const
  {       // test for iterator equality
    return _Myoff == _Right._Myoff;
  }

  bool operator!=(const _Myiter& _Right) const
  {       // test for iterator inequality
    return !(*this == _Right);
  }

  bool operator<(const _Myiter& _Right) const
  {       // test if this < _Right
    return _Myoff < _Right._Myoff;
  }

  bool operator>(const _Myiter& _Right) const
  {       // test if this > _Right
    return _Right < *this;
  }

  bool operator<=(const _Myiter& _Right) const
  {       // test if this <= _Right
    return !(_Right < *this);
  }

  bool operator>=(const _Myiter& _Right) const
  {       // test if this >= _Right
    return !(*this < _Right);
  }

  const _Container_base12 *_Getcont() const
  {       // get container pointer
    return _Mycont;
  }

  const _Mydeque *_Mycont;        // pointer to deque
  size_type _Myoff;       // offset of element in deque
};

template<class _Mydeque> inline
_Deque_unchecked_const_iterator<_Mydeque> operator+(
  typename _Deque_unchecked_const_iterator<_Mydeque>
  ::difference_type _Off,
  _Deque_unchecked_const_iterator<_Mydeque> _Next)
{       // add offset to iterator
  return _Next += _Off;
}

// TEMPLATE CLASS _Deque_unchecked_iterator
template<class _Mydeque>
class _Deque_unchecked_iterator
  : public _Deque_unchecked_const_iterator<_Mydeque>
{       // iterator for mutable deque
public:
  typedef _Deque_unchecked_iterator<_Mydeque> _Myiter;
  typedef _Deque_unchecked_const_iterator<_Mydeque> _Mybase;
  typedef random_access_iterator_tag iterator_category;

  typedef typename _Mydeque::value_type value_type;
  typedef typename _Mydeque::size_type size_type;
  typedef typename _Mydeque::difference_type difference_type;
  typedef typename _Mydeque::pointer pointer;
  typedef typename _Mydeque::reference reference;

  _Deque_unchecked_iterator()
  {       // construct with null pointer
  }

  _Deque_unchecked_iterator(size_type _Off,
                            const _Container_base12 *_Pdeque)
    : _Mybase(_Off, _Pdeque)
  {       // construct with offset _Off
  }

  reference operator*() const
  {       // return designated object
    return (reference)**(_Mybase *)this;
  }

  pointer operator->() const
  {       // return pointer to class object
    return _POINTER_TO(**this);
  }

  _Myiter& operator++()
  {       // preincrement
    ++*(_Mybase *)this;
    return *this;
  }

  _Myiter operator++(int)
  {       // postincrement
    _Myiter _Tmp = *this;
    ++*this;
    return _Tmp;
  }

  _Myiter& operator--()
  {       // predecrement
    --*(_Mybase *)this;
    return *this;
  }

  _Myiter operator--(int)
  {       // postdecrement
    _Myiter _Tmp = *this;
    --*this;
    return _Tmp;
  }

  _Myiter& operator+=(difference_type _Off)
  {       // increment by integer
    *(_Mybase *)this += _Off;
    return *this;
  }

  _Myiter operator+(difference_type _Off) const
  {       // return this + integer
    _Myiter _Tmp = *this;
    return _Tmp += _Off;
  }

  _Myiter& operator-=(difference_type _Off)
  {       // decrement by integer
    return *this += -_Off;
  }

  _Myiter operator-(difference_type _Off) const
  {       // return this - integer
    _Myiter _Tmp = *this;
    return _Tmp -= _Off;
  }

  difference_type operator-(const _Mybase& _Right) const
  {       // return difference of iterators
    return *(_Mybase *)this - _Right;
  }

  reference operator[](difference_type _Off) const
  {       // subscript
    return *(*this + _Off);
  }
};

template<class _Mydeque> inline
_Deque_unchecked_iterator<_Mydeque> operator+(
  typename _Deque_unchecked_iterator<_Mydeque>
  ::difference_type _Off,
  _Deque_unchecked_iterator<_Mydeque> _Next)
{       // add offset to iterator
  return _Next += _Off;
}

// TEMPLATE CLASS _Deque_const_iterator
template<class _Mydeque>
class _Deque_const_iterator
  : public _Iterator_base12
{       // iterator for nonmutable deque
public:
  typedef _Deque_const_iterator<_Mydeque> _Myiter;
  typedef random_access_iterator_tag iterator_category;

  typedef typename _Mydeque::value_type value_type;
  typedef typename _Mydeque::size_type size_type;
  typedef typename _Mydeque::difference_type difference_type;
  typedef typename _Mydeque::const_pointer pointer;
  typedef typename _Mydeque::const_reference reference;

  _Deque_const_iterator()
  {       // construct with null pointer
    _Setcont(0);
    _Myoff = 0;
  }

  _Deque_const_iterator(size_type _Off, const _Container_base12 *_Pdeque)
  {       // construct with offset _Off in *_Pdeque
    _Setcont((_Mydeque *)_Pdeque);
    _Myoff = _Off;
  }

  typedef _Deque_unchecked_const_iterator<_Mydeque> _Unchecked_type;

  _Myiter& _Rechecked(_Unchecked_type _Right)
  {       // reset from unchecked iterator
    this->_Myoff = _Right._Myoff;
    return *this;
  }

  _Unchecked_type _Unchecked() const
  {       // make an unchecked iterator
    return _Unchecked_type(_Myoff, this->_Getcont());
  }

  reference operator*() const
  {       // return designated object
    _Mydeque *_Mycont = ((_Mydeque *)this->_Getcont());

    #if _ITERATOR_DEBUG_LEVEL == 2
      if (   _Mycont == 0
          || this->_Myoff < _Mycont->_Myoff
          || _Mycont->_Myoff + _Mycont->_Mysize <= this->_Myoff)
      {       // report error
        _DEBUG_ERROR("deque iterator not dereferencable");
        _SCL_SECURE_OUT_OF_RANGE;
      }
    #elif _ITERATOR_DEBUG_LEVEL == 1
      _SCL_SECURE_VALIDATE(_Mycont != 0);
      _SCL_SECURE_VALIDATE_RANGE(   _Mycont->_Myoff <= this->_Myoff
                                 &&   this->_Myoff < _Mycont->_Myoff
                                    + _Mycont->_Mysize);
    #endif /* _ITERATOR_DEBUG_LEVEL */

    size_type _Block = _Mycont->_Getblock(_Myoff);
    size_type _Off = _Myoff % _DEQUESIZ;
    return _Mycont->_Map[_Block][_Off];
  }

  pointer operator->() const
  {       // return pointer to class object
    return _POINTER_TO(**this);
  }

  _Myiter& operator++()
  {       // preincrement
    #if _ITERATOR_DEBUG_LEVEL == 2
      _Mydeque *_Mycont = ((_Mydeque *)this->_Getcont());
      if (   _Mycont == 0
          || _Mycont->_Myoff + _Mycont->_Mysize <= this->_Myoff)
      {       // report error
        _DEBUG_ERROR("deque iterator not incrementable");
        _SCL_SECURE_OUT_OF_RANGE;
      }
    #elif _ITERATOR_DEBUG_LEVEL == 1
      _Mydeque *_Mycont = ((_Mydeque *)this->_Getcont());
      _SCL_SECURE_VALIDATE(_Mycont != 0);
      _SCL_SECURE_VALIDATE_RANGE(
        this->_Myoff < _Mycont->_Myoff + _Mycont->_Mysize);
    #endif /* _ITERATOR_DEBUG_LEVEL */

    ++_Myoff;
    return *this;
  }

  _Myiter operator++(int)
  {       // postincrement
    _Myiter _Tmp = *this;
    ++*this;
    return _Tmp;
  }

  #pragma no_arith_checks
  _Myiter& operator--()
  {       // predecrement
    #if _ITERATOR_DEBUG_LEVEL == 2
      _Mydeque *_Mycont = ((_Mydeque *)this->_Getcont());
      if (   _Mycont == 0
          || this->_Myoff <= _Mycont->_Myoff)
      {       // report error
        _DEBUG_ERROR("deque iterator not decrementable");
        _SCL_SECURE_OUT_OF_RANGE;
      }
    #elif _ITERATOR_DEBUG_LEVEL == 1
      _Mydeque *_Mycont = ((_Mydeque *)this->_Getcont());
      _SCL_SECURE_VALIDATE(_Mycont != 0);
      _SCL_SECURE_VALIDATE_RANGE(_Mycont->_Myoff < this->_Myoff);
    #endif /* _ITERATOR_DEBUG_LEVEL */

    --_Myoff;
    return *this;
  }

  _Myiter operator--(int)
  {       // postdecrement
    _Myiter _Tmp = *this;
    --*this;
    return _Tmp;
  }

  _Myiter& operator+=(difference_type _Off)
  {       // increment by integer
    #if _ITERATOR_DEBUG_LEVEL == 2
      _Mydeque *_Mycont = ((_Mydeque *)this->_Getcont());
      if (   _Mycont == 0
          || this->_Myoff + _Off < _Mycont->_Myoff
          || _Mycont->_Myoff + _Mycont->_Mysize < this->_Myoff + _Off)
      {       // report error
        _DEBUG_ERROR("deque iterator + offset out of range");
        _SCL_SECURE_OUT_OF_RANGE;
      }
    #elif _ITERATOR_DEBUG_LEVEL == 1
      _Mydeque *_Mycont = ((_Mydeque *)this->_Getcont());
      _SCL_SECURE_VALIDATE(_Mycont != 0);
      _SCL_SECURE_VALIDATE_RANGE(   _Mycont->_Myoff <= this->_Myoff + _Off
                                 &&   this->_Myoff
                                    + _Off <= _Mycont->_Myoff
                                    + _Mycont->_Mysize);
    #endif /* _ITERATOR_DEBUG_LEVEL */

    _Myoff += _Off;
    return *this;
  }

  _Myiter operator+(difference_type _Off) const
  {       // return this + integer
    _Myiter _Tmp = *this;
    return _Tmp += _Off;
  }

  _Myiter& operator-=(difference_type _Off)
  {       // decrement by integer
    return *this += -_Off;
  }

  _Myiter operator-(difference_type _Off) const
  {       // return this - integer
    _Myiter _Tmp = *this;
    return _Tmp -= _Off;
  }

  #pragma no_arith_checks
  difference_type operator-(const _Myiter& _Right) const
  {       // return difference of iterators
    _Compat(_Right);
    return _Right._Myoff <= this->_Myoff
             ? this->_Myoff - _Right._Myoff
             : -(difference_type)(_Right._Myoff - this->_Myoff);
  }

  reference operator[](difference_type _Off) const
  {       // subscript
    return *(*this + _Off);
  }

  bool operator==(const _Myiter& _Right) const
  {       // test for iterator equality
    #if 0 < _ITERATOR_DEBUG_LEVEL
      if (this->_Getcont() != _Right._Getcont())
        _Compat(_Right);
    #endif /* 0 < _ITERATOR_DEBUG_LEVEL */

    return this->_Myoff == _Right._Myoff;
  }

  bool operator!=(const _Myiter& _Right) const
  {       // test for iterator inequality
    return !(*this == _Right);
  }

  bool operator<(const _Myiter& _Right) const
  {       // test if this < _Right
    _Compat(_Right);
    return this->_Myoff < _Right._Myoff;
  }

  bool operator>(const _Myiter& _Right) const
  {       // test if this > _Right
    return _Right < *this;
  }

  bool operator<=(const _Myiter& _Right) const
  {       // test if this <= _Right
    return !(_Right < *this);
  }

  bool operator>=(const _Myiter& _Right) const
  {       // test if this >= _Right
    return !(*this < _Right);
  }

  #if _ITERATOR_DEBUG_LEVEL == 2
    void _Compat(const _Myiter& _Right) const
    {       // test for compatible iterator pair
      _Mydeque *_Mycont = ((_Mydeque *)this->_Getcont());
      if (   _Mycont == 0
          || _Mycont != _Right._Getcont())
      {       // report error
        _DEBUG_ERROR("deque iterators incompatible");
        _SCL_SECURE_INVALID_ARGUMENT;
      }
    }

    void _Setcont(const _Mydeque *_Pdeque)
    {       // set container pointer
      this->_Adopt(_Pdeque);
    }
  #elif _ITERATOR_DEBUG_LEVEL == 1
    void _Compat(const _Myiter& _Right) const
    {       // test for compatible iterator pair
      _Mydeque *_Mycont = ((_Mydeque *)this->_Getcont());
      _SCL_SECURE_VALIDATE(_Mycont != 0);
      _SCL_SECURE_VALIDATE_RANGE(_Mycont == _Right._Getcont());
    }

    void _Setcont(const _Mydeque *_Pdeque)
    {       // set container pointer
      this->_Adopt(_Pdeque);
    }
  #else /* _ITERATOR_DEBUG_LEVEL == 0 */
    void _Compat(const _Myiter&) const
    {       // test for compatible iterator pair
    }

    void _Setcont(const _Mydeque *_Pdeque)
    {       // set container pointer
      this->_Adopt(_Pdeque);
    }
  #endif /* _ITERATOR_DEBUG_LEVEL */

  size_type _Myoff;       // offset of element in deque
#pragma important_typedef // For C-Spy
  typedef _Mydeque _MYDEQUE;
};

template<class _Mydeque> inline
typename _Deque_const_iterator<_Mydeque>::_Unchecked_type
_Unchecked(_Deque_const_iterator<_Mydeque> _Iter)
{       // convert to unchecked
  return _Iter._Unchecked();
}

template<class _Mydeque> inline
_Deque_const_iterator<_Mydeque>&
_Rechecked(_Deque_const_iterator<_Mydeque>& _Iter,
           typename _Deque_const_iterator<_Mydeque>::_Unchecked_type _Right)
{       // convert to checked
  return _Iter._Rechecked(_Right);
}

template<class _Mydeque> inline
_Deque_const_iterator<_Mydeque> operator+(
  typename _Deque_const_iterator<_Mydeque>::difference_type _Off,
  _Deque_const_iterator<_Mydeque> _Next)
{       // add offset to iterator
  return _Next += _Off;
}

// TEMPLATE CLASS _Deque_iterator
template<class _Mydeque>
class _Deque_iterator
  : public _Deque_const_iterator<_Mydeque>
{       // iterator for mutable deque
public:
  typedef _Deque_iterator<_Mydeque> _Myiter;
  typedef _Deque_const_iterator<_Mydeque> _Mybase;
  typedef _Deque_unchecked_iterator<_Mydeque> _Deque_unchecked_type;
  typedef random_access_iterator_tag iterator_category;

  typedef typename _Mydeque::value_type value_type;
  typedef typename _Mydeque::size_type size_type;
  typedef typename _Mydeque::difference_type difference_type;
  typedef typename _Mydeque::pointer pointer;
  typedef typename _Mydeque::reference reference;

  _Deque_iterator()
  {       // construct with null deque pointer
  }

  _Deque_iterator(size_type _Off, const _Container_base12 *_Pdeque)
    : _Mybase(_Off, _Pdeque)
  {       // construct with offset _Off in *_Pdeque
  }

  typedef _Deque_unchecked_iterator<_Mydeque> _Unchecked_type;

  _Myiter& _Rechecked(_Unchecked_type _Right)
  {       // reset from unchecked iterator
    this->_Myoff = _Right._Myoff;
    return *this;
  }

  _Unchecked_type _Unchecked() const
  {       // make an unchecked iterator
    return _Unchecked_type(this->_Myoff, this->_Getcont());
  }

  reference operator*() const
  {       // return designated object
    return (reference)**(_Mybase *)this;
  }

  pointer operator->() const
  {       // return pointer to class object
    return _POINTER_TO(**this);
  }

  _Myiter& operator++()
  {       // preincrement
    ++*(_Mybase *)this;
    return *this;
  }

  _Myiter operator++(int)
  {       // postincrement
    _Myiter _Tmp = *this;
    ++*this;
    return _Tmp;
  }

  _Myiter& operator--()
  {       // predecrement
    --*(_Mybase *)this;
    return *this;
  }

  _Myiter operator--(int)
  {       // postdecrement
    _Myiter _Tmp = *this;
    --*this;
    return _Tmp;
  }

  _Myiter& operator+=(difference_type _Off)
  {       // increment by integer
    this->_Myoff += _Off;
    return *this;
  }

  _Myiter operator+(difference_type _Off) const
  {       // return this + integer
    _Myiter _Tmp = *this;
    return _Tmp += _Off;
  }

  _Myiter& operator-=(difference_type _Off)
  {       // decrement by integer
    return *this += -_Off;
  }

  _Myiter operator-(difference_type _Off) const
  {       // return this - integer
    _Myiter _Tmp = *this;
    return _Tmp -= _Off;
  }

  difference_type operator-(const _Mybase& _Right) const
  {       // return difference of iterators
    return *(_Mybase *)this - _Right;
  }

  reference operator[](difference_type _Off) const
  {       // subscript
    return *(*this + _Off);
  }

#pragma important_typedef // For C-Spy
  typedef _Mydeque _MYDEQUE;
};

template<class _Mydeque> inline
typename _Deque_iterator<_Mydeque>::_Unchecked_type
_Unchecked(_Deque_iterator<_Mydeque> _Iter)
{       // convert to unchecked
  return _Iter._Unchecked();
}

template<class _Mydeque> inline
_Deque_iterator<_Mydeque>&
_Rechecked(_Deque_iterator<_Mydeque>& _Iter,
           typename _Deque_iterator<_Mydeque>::_Unchecked_type _Right)
{       // convert to checked
  return _Iter._Rechecked(_Right);
}

template<class _Mydeque> inline
_Deque_iterator<_Mydeque> operator+(
  typename _Deque_iterator<_Mydeque>::difference_type _Off,
  _Deque_iterator<_Mydeque> _Next)
{       // add offset to iterator
  return _Next += _Off;
}

// deque TYPE WRAPPERS
template<class _Value_type,
         class _Size_type,
         class _Difference_type,
         class _Pointer,
         class _Const_pointer,
         class _Reference,
         class _Const_reference,
         class _Mapptr_type>
struct _Deque_iter_types
{       // wraps types needed by iterators
  typedef _Value_type value_type;
  typedef _Size_type size_type;
  typedef _Difference_type difference_type;
  typedef _Pointer pointer;
  typedef _Const_pointer const_pointer;
  typedef _Reference reference;
  typedef _Const_reference const_reference;
  typedef _Mapptr_type _Mapptr;
};

template<class _Ty>
struct _Deque_simple_types
  : public _Simple_types<_Ty>
{       // wraps types needed by iterators
  typedef _Ty **_Mapptr;
};

template<class _Ty,
         class _Alloc0>
struct _Deque_base_types
{       // types needed for a container base
  typedef _Alloc0 _Alloc;
  typedef _Deque_base_types<_Ty, _Alloc> _Myt;

  typedef _Wrap_alloc<_Alloc> _Alty0;
  typedef typename _Alty0::template rebind<_Ty>::other _Alty;

  typedef typename _Alty::pointer _Tptr;
  typedef typename _Alty::template rebind<_Tptr>::other _Alpty;
  typedef typename _Alpty::pointer _Mapptr;

  typedef typename _If<_Is_simple_alloc<_Alty>::value,
                       _Deque_simple_types<typename _Alty::value_type>,
                       _Deque_iter_types<typename _Alty::value_type,
                                         typename _Alty::size_type,
                                         typename _Alty::difference_type,
                                         typename _Alty::pointer,
                                         typename _Alty::const_pointer,
                                         typename _Alty::reference,
                                         typename _Alty::const_reference,
                                         _Mapptr> >::type
  _Val_types;
};

// TEMPLATE CLASS _Deque_val

template<class _Val_types>
class _Deque_val
  : public _Container_base12
{       // base class for deque to hold data
public:
  typedef _Deque_val<_Val_types> _Myt;

  typedef typename _Val_types::value_type value_type;
  typedef typename _Val_types::size_type size_type;
  typedef typename _Val_types::difference_type difference_type;
  typedef typename _Val_types::pointer pointer;
  typedef typename _Val_types::const_pointer const_pointer;
  typedef typename _Val_types::reference reference;
  typedef typename _Val_types::const_reference const_reference;
  typedef typename _Val_types::_Mapptr _Mapptr;

  typedef _Deque_iterator<_Myt> iterator;
  typedef _Deque_const_iterator<_Myt> const_iterator;

  _Deque_val()
  {       // initialize values
    _Map = _Mapptr();
    _Mapsize = 0;
    _Myoff = 0;
    _Mysize = 0;
  }

  size_type _Getblock(size_type _Off) const
  {       // determine block from offset
    // NB: _Mapsize and _DEQUESIZ are guaranteed to be powers of 2
    return (_Off / _DEQUESIZ) & (this->_Mapsize - 1);
  }

  _Mapptr _Map;           // pointer to array of pointers to blocks
  size_type _Mapsize;     // size of map array, zero or 2^N
  size_type _Myoff;       // offset of initial element
  size_type _Mysize;      // current length of sequence

  enum __iar_constants
  {       // deque parameters
    _IAR_DEQUEMAPSIZ = _DEQUEMAPSIZ,       /* minimum map size, at least 1 */
    _IAR_DEQUESIZ = _DEQUESIZ
  };   // elements per block
#pragma important_typedef        // To ensure enum constants in debug info
  typedef __iar_constants _Constants1;
};

// TEMPLATE CLASS _Deque_alloc
template <class _Opty>
struct _Container_proxy12 : _Container_proxy
{       // store pointer from allocator since it is  needed for deallocation
  _Container_proxy12()
    : _Container_proxy(), _Myptr()
  {
  }

  typedef typename pointer_traits<_Opty>::template rebind<_Container_proxy12<_Opty>> _Pty;

  _Pty _Myptr;
};

template<class _Alloc_types>
class _Deque_alloc
{ // base class for deque to hold allocator
public:
  typedef _Deque_alloc<_Alloc_types> _Myt;
  typedef typename _Alloc_types::_Alloc _Alloc;
  typedef typename _Alloc_types::_Alty _Alty;
  typedef typename _Alloc_types::_Alpty _Alpty;
  typedef typename _Alloc_types::_Val_types _Val_types;

  typedef typename _Val_types::value_type value_type;
  typedef typename _Val_types::size_type size_type;
  typedef typename _Val_types::difference_type difference_type;
  typedef typename _Val_types::pointer pointer;
  typedef typename _Val_types::const_pointer const_pointer;
  typedef typename _Val_types::reference reference;
  typedef typename _Val_types::const_reference const_reference;
  typedef typename _Val_types::_Mapptr _Mapptr;

  typedef _Deque_iterator<_Deque_val<_Val_types> > iterator;
  typedef _Deque_const_iterator<_Deque_val<_Val_types> > const_iterator;

  size_type _Getblock(size_type _Off) const
  { // determine block from offset
    return (_Get_data()._Getblock(_Off));
  }

  _Deque_alloc(const _Alloc& _Al = _Alloc())
    : _Mypair(_One_then_variadic_args_t(), _Al)
  {	// construct allocator from _Al
    _Alloc_proxy();
  }

  _Deque_alloc(_Alloc&& _Al)
    : _Mypair(_One_then_variadic_args_t(),
              std::forward<_Alloc>(_Al))
  {	// construct allocator from _Al
    _Alloc_proxy();
  }

  ~_Deque_alloc() _NOEXCEPT
  {	// destroy proxy
    _Free_proxy();
  }

  void _Copy_alloc(const _Alty& _Al)
  {	// replace old allocator
    _Free_proxy();
    _Pocca(_Getal(), _Al);
    _Alloc_proxy();
  }

  void _Move_alloc(_Alty& _Al)
  {	// replace old allocator
    _Free_proxy();
    _Pocma(_Getal(), _Al);
    _Alloc_proxy();
  }

  void _Swap_alloc(_Myt& _Right)
  {	// swap allocators
    _Pocs(_Getal(), _Right._Getal());
    _Swap_adl(_Myproxy(), _Right._Myproxy());
  }

  template <class T=pointer>
  typename enable_if<is_pointer<T>::value, void>::type
  _Alloc_proxy()
  {
    typename _Alty::template rebind<_Container_proxy>::other
      _Alproxy(_Getal());
    _Myproxy() = _Alproxy.allocate(1);
    _Alproxy.construct(_Myproxy(), _Container_proxy());
    _Myproxy()->_Mycont = &_Get_data();
  }

  template <class T=pointer>
  typename enable_if<!is_pointer<T>::value, void>::type
  _Alloc_proxy()
  {	// construct proxy

    typedef _Container_proxy12<pointer> _Proxy_type;
    typedef typename _Alty::template rebind<_Proxy_type>::other _Alproxyty;

    _Alproxyty _Alproxy(_Getal());

    typename _Proxy_type::_Pty _Proxyptr = _Alproxy.allocate(1);

    _Proxy_type *_Proxyaddr = std::addressof(*_Proxyptr);

    _Myproxy() = _Proxyaddr;
    _Alproxy.construct(_Proxyaddr, _Proxy_type());
    _Myproxy()->_Mycont = &_Get_data();
    _Proxyaddr->_Myptr = std::move(_Proxyptr);
  }

  template <class T=pointer>
  typename enable_if<is_pointer<T>::value, void>::type
  _Free_proxy()
   {	// destroy proxy
     typename _Alty::template rebind<_Container_proxy>::other
       _Alproxy(_Getal());
     _Orphan_all();
     _Alproxy.destroy(_Myproxy());
     _Alproxy.deallocate(_Myproxy(), 1);
     _Myproxy() = 0;
   }

  template <class T=pointer>
  typename enable_if<!is_pointer<T>::value, void>::type
  _Free_proxy()
  {	// destroy proxy
    typedef _Container_proxy12<pointer> _Proxy_type;
    typedef typename _Alty::template rebind<_Proxy_type>::other _Alproxyty;

    _Alproxyty _Alproxy(_Getal());

    _Orphan_all();

    _Proxy_type *_Proxyaddr = (_Proxy_type *)(_Myproxy());

    typename _Proxy_type::_Pty _Proxyptr(std::move(_Proxyaddr->_Myptr));

    _Alproxy.destroy(_Proxyaddr);
    _Alproxy.deallocate(_Proxyptr, 1);
    _Myproxy() = 0;
  }

  _Iterator_base12 **_Getpfirst() const
  {	// get address of iterator chain
    return _Get_data()._Getpfirst();
  }

  _Container_proxy * & _Myproxy() _NOEXCEPT
  {	// return reference to _Myproxy
    return _Get_data()._Myproxy;
  }

  _Container_proxy * const & _Myproxy() const _NOEXCEPT
  {	// return const reference to _Myproxy
    return _Get_data()._Myproxy;
  }

  void _Orphan_all()
  {	// orphan all iterators
    _Get_data()._Orphan_all();
  }

  void _Swap_all(_Myt& _Right)
  {	// swap all iterators
    _Get_data()._Swap_all(_Right._Get_data());
  }

  _Alty& _Getal() _NOEXCEPT
  {	// return reference to allocator
    return _Mypair._Get_first();
  }

  const _Alty& _Getal() const _NOEXCEPT
  {	// return const reference to allocator
    return _Mypair._Get_first();
  }

  _Deque_val<_Val_types>& _Get_data() _NOEXCEPT
  {	// return reference to _Deque_val
    return _Mypair._Get_second();
  }

  const _Deque_val<_Val_types>& _Get_data() const _NOEXCEPT
  {	// return const reference to _Deque_val
    return _Mypair._Get_second();
  }

  _Mapptr& _Map() _NOEXCEPT
  {	// return reference to _Map
    return _Get_data()._Map;
  }

  const _Mapptr& _Map() const _NOEXCEPT
  {	// return const reference to _Map
    return _Get_data()._Map;
  }

  size_type& _Mapsize() _NOEXCEPT
  {	// return reference to _Mapsize
    return _Get_data()._Mapsize;
  }

  const size_type& _Mapsize() const _NOEXCEPT
  {	// return const reference to _Mapsize
    return _Get_data()._Mapsize;
  }

  size_type& _Myoff() _NOEXCEPT
  {	// return reference to _Myoff
    return _Get_data()._Myoff;
  }

  const size_type& _Myoff() const _NOEXCEPT
  {	// return const reference to _Myoff
    return _Get_data()._Myoff;
  }

  size_type& _Mysize() _NOEXCEPT
  {	// return reference to _Mysize
    return _Get_data()._Mysize;
  }

  const size_type& _Mysize() const _NOEXCEPT
  {	// return const reference to _Mysize
    return _Get_data()._Mysize;
  }

private:
  _Compressed_pair<_Alty, _Deque_val<_Val_types> > _Mypair;
};

// TEMPLATE CLASS deque
template<class _Ty,
         class _Alloc = allocator<_Ty> >
class deque
  : public _Deque_alloc<_Deque_base_types<_Ty, _Alloc> >
{       // circular queue of pointers to blocks
public:
  typedef deque<_Ty, _Alloc> _Myt;
  typedef _Deque_alloc<_Deque_base_types<_Ty, _Alloc> > _Mybase;
  typedef _Alloc allocator_type;

  typedef typename _Mybase::_Alty _Alty;
  typedef typename _Mybase::_Alpty _Alpty;
  typedef typename _Mybase::_Mapptr _Mapptr;

  typedef typename _Mybase::value_type value_type;
  typedef typename _Mybase::size_type size_type;
  typedef typename _Mybase::difference_type difference_type;
  typedef typename _Mybase::pointer pointer;
  typedef typename _Mybase::const_pointer const_pointer;
  typedef typename _Mybase::reference reference;
  typedef typename _Mybase::const_reference const_reference;

  typedef typename _Mybase::iterator iterator;
  typedef typename _Mybase::const_iterator const_iterator;

  typedef std::reverse_iterator<iterator> reverse_iterator;
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

  static_assert(std::is_same<value_type,
                typename allocator_type::value_type>::value,
                "value_type of allocator must match container");

  deque()
    : _Mybase()
  {       // construct empty deque
  }

  explicit deque(const _Alloc& _Al)
    : _Mybase(_Al)
  {       // construct empty deque with allocator
  }

  explicit deque(size_type _Count, const _Alloc &_Al = _Alloc())
    : _Mybase(_Al)
  {       // construct from _Count * value_type()
    resize(_Count);
  }

  deque(size_type _Count, const value_type& _Val)
    : _Mybase()
  {       // construct from _Count * _Val
    _Construct_n(_Count, _Val);
  }

  deque(size_type _Count, const value_type& _Val, const _Alloc& _Al)
    : _Mybase(_Al)
  {       // construct from _Count * _Val with allocator
    _Construct_n(_Count, _Val);
  }

  deque(const _Myt& _Right)
    : _Mybase(_Right._Getal().select_on_container_copy_construction())
  {       // construct by copying _Right
    _Construct(_Right.begin(), _Right.end());
  }

  deque(const _Myt& _Right, const _Alloc& _Al)
    : _Mybase(_Al)
  {       // construct by copying _Right
    _Construct(_Right.begin(), _Right.end());
  }

  template<class _Iter,
           class = typename enable_if<_Is_iterator<_Iter>::value,
                                      void>::type>
  deque(_Iter _First, _Iter _Last)
    : _Mybase()
  {       // construct from [_First, _Last)
    _Construct(_First, _Last);
  }

  template<class _Iter,
           class = typename enable_if<_Is_iterator<_Iter>::value,
                                      void>::type>
  deque(_Iter _First, _Iter _Last, const _Alloc& _Al)
    : _Mybase(_Al)
  {       // construct from [_First, _Last) with allocator
    _Construct(_First, _Last);
  }

  template<class _Iter>
  _NOINLINE void _Construct(_Iter _First, _Iter _Last)
  {       // initialize from [_First, _Last), input iterators
    _TRY_BEGIN
      for (; _First != _Last; ++_First)
        emplace_back(*_First);
    _CATCH_ALL
      _Tidy();
      _RERAISE;
    _CATCH_END
  }

  _NOINLINE void _Construct_n(size_type _Count, const value_type& _Val)
  {       // construct from _Count * _Val
    _TRY_BEGIN
      for (; 0 < _Count; --_Count)
        push_back(_Val);
    _CATCH_ALL
      _Tidy();
      _RERAISE;
    _CATCH_END
  }

  #define _PUSH_FRONT_BEGIN                                                 \
    if (   this->_Myoff() % _DEQUESIZ == 0                                  \
        && this->_Mapsize() <= (this->_Mysize() + _DEQUESIZ) / _DEQUESIZ)   \
      _Growmap(1);                                                          \
    this->_Myoff() &= this->_Mapsize() * _DEQUESIZ - 1;                     \
    size_type _Newoff = this->_Myoff() != 0 ? this->_Myoff()                \
                                            : this->_Mapsize() * _DEQUESIZ; \
    size_type _Block = this->_Getblock(--_Newoff);                          \
    if (this->_Map()[_Block] == pointer())                                  \
      this->_Map()[_Block] = this->_Getal().allocate(_DEQUESIZ)

  #define _PUSH_FRONT_END                       \
    this->_Myoff() = _Newoff;                   \
    ++this->_Mysize()

  #define _PUSH_BACK_BEGIN                                                  \
    if (   (this->_Myoff() + this->_Mysize()) % _DEQUESIZ == 0              \
        && this->_Mapsize() <= (this->_Mysize() + _DEQUESIZ) / _DEQUESIZ)   \
      _Growmap(1);                                                          \
    this->_Myoff() &= this->_Mapsize() * _DEQUESIZ - 1;                     \
    size_type _Newoff = this->_Myoff() + this->_Mysize();                   \
    size_type _Block = this->_Getblock(_Newoff);                            \
    if (this->_Map()[_Block] == pointer())                                  \
      this->_Map()[_Block] = this->_Getal().allocate(_DEQUESIZ)

  #define _PUSH_BACK_END   ++this->_Mysize()

  deque(_Myt&& _Right)
    : _Mybase(std::move(_Right._Getal()))
  {       // construct by moving _Right
    _Assign_rv(std::forward<_Myt>(_Right), true_type());
  }

  deque(_Myt&& _Right, const _Alloc& _Al)
    : _Mybase(_Al)
  {       // construct by moving _Right
    _Assign_rv(std::forward<_Myt>(_Right));
  }

  _NOINLINE _Myt& operator=(_Myt&& _Right)
    _NOEXCEPT_OP(_Alty::is_always_equal::value)
  {       // assign by moving _Right
    if (this != &_Right)
    {       // different, assign it
      _Tidy();
      if (   _Alty::propagate_on_container_move_assignment::value
          && this->_Getal() != _Right._Getal())
        this->_Move_alloc(_Right._Getal());
      _Assign_rv(std::forward<_Myt>(_Right));
    }
    return *this;
  }

  _NOINLINE void _Assign_rv(_Myt&& _Right, true_type)
  {       // move from _Right, stealing its contents
    this->_Swap_all((_Myt&)_Right);
    this->_Map()      = _Right._Map();
    this->_Mapsize()  = _Right._Mapsize();
    this->_Myoff()    = _Right._Myoff();
    this->_Mysize()   = _Right._Mysize();

    _Right._Map()     = _Mapptr();
    _Right._Mapsize() = 0;
    _Right._Myoff()   = 0;
    _Right._Mysize()  = 0;
  }

  _NOINLINE void _Assign_rv(_Myt&& _Right, false_type)
  {       // move from _Right, possibly moving its contents
    if (get_allocator() == _Right.get_allocator())
      _Assign_rv(std::forward<_Myt>(_Right), true_type());
    else
      _Construct(make_move_iterator(_Right.begin()),
                 make_move_iterator(_Right.end()));
  }

  void _Assign_rv(_Myt&& _Right)
  {       // assign by moving _Right
    _Assign_rv(std::forward<_Myt>(_Right),
               typename _Alty::propagate_on_container_move_assignment());
  }

  _NOINLINE void push_front(value_type&& _Val)
  {       // insert element at beginning
    this->_Orphan_all();
    _PUSH_FRONT_BEGIN;
    this->_Getal().construct(
      std::addressof(*this->_Map()[_Block]) + _Newoff % _DEQUESIZ,
      std::forward<value_type>(_Val));
    _PUSH_FRONT_END;
  }

  _NOINLINE void push_back(value_type&& _Val)
  {       // insert element at end
    this->_Orphan_all();
    _PUSH_BACK_BEGIN;
    this->_Getal().construct(
      std::addressof(*this->_Map()[_Block]) + _Newoff % _DEQUESIZ,
      std::forward<value_type>(_Val));
    _PUSH_BACK_END;
  }

  iterator insert(const_iterator _Where, _Ty&& _Val)
  {       // insert _Val at _Where
    return emplace(_Where, move(_Val));
  }

  template<class... _Valty>
  _NOINLINE reference emplace_front(_Valty&&... _Val)
  {       // insert element at beginning
    this->_Orphan_all();
    _PUSH_FRONT_BEGIN;
    this->_Getal().construct(std::addressof(*this->_Map()[_Block]) + _Newoff % _DEQUESIZ,
                             std::forward<_Valty>(_Val)...);
    _PUSH_FRONT_END;
    return front();
  }

  template<class... _Valty>
  _NOINLINE reference emplace_back(_Valty&&... _Val)
  {       // insert element at end
    this->_Orphan_all();
    _PUSH_BACK_BEGIN;
    this->_Getal().construct(std::addressof(*this->_Map()[_Block]) + _Newoff % _DEQUESIZ,
                             std::forward<_Valty>(_Val)...);
    _PUSH_BACK_END;
    return back();
  }

  template<class... _Valty>
  _NOINLINE iterator emplace(const_iterator _Where, _Valty&&... _Val)
  {       // insert element at _Where
    size_type _Off = _Where - begin();

    #if _ITERATOR_DEBUG_LEVEL == 2
      if (this->_Mysize() < _Off)
        _DEBUG_ERROR("deque emplace iterator outside range");
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    if (_Off <= this->_Mysize() / 2)
    {       // closer to front, push to front then rotate
      emplace_front(std::forward<_Valty>(_Val)...);
      std::rotate(begin(), begin() + 1, begin() + 1 + _Off);
    }
    else
    {       // closer to back, push to back then rotate
      emplace_back(std::forward<_Valty>(_Val)...);
      std::rotate(begin() + _Off, end() - 1, end());
    }
    return begin() + _Off;
  }

  deque(::std::initializer_list<value_type> _Ilist,
        const _Alloc& _Al = allocator_type())
    : _Mybase(_Al)
  {       // construct from initializer_list
    _Construct(_Ilist.begin(), _Ilist.end());
  }

  _Myt& operator=(::std::initializer_list<value_type> _Ilist)
  {       // assign initializer_list
    assign(_Ilist.begin(), _Ilist.end());
    return *this;
  }

  void assign(::std::initializer_list<value_type> _Ilist)
  {       // assign initializer_list
    assign(_Ilist.begin(), _Ilist.end());
  }

  iterator insert(const_iterator _Where,
                  ::std::initializer_list<value_type> _Ilist)
  {       // insert initializer_list
    return insert(_Where, _Ilist.begin(), _Ilist.end());
  }

  ~deque() _NOEXCEPT
  {       // destroy the deque
    _Tidy();
  }

  _NOINLINE _Myt& operator=(const _Myt& _Right)
  {       // assign _Right
    if (this != &_Right)
    {       // different, assign it
      if (   this->_Getal() != _Right._Getal()
          && _Alty::propagate_on_container_copy_assignment::value)
      {       // change allocator before copying
        _Tidy();
        this->_Copy_alloc(_Right._Getal());
      }

      this->_Orphan_all();

      if (_Right._Mysize() == 0)
        clear();
      else if (_Right._Mysize() <= this->_Mysize())
      {       // enough elements, copy new and destroy old
        iterator _Mid = std::copy(_Right.begin(), _Right.end(),
                                  begin());
        erase(_Mid, end());
      }
      else
      {       // new sequence longer, copy and construct new
        const_iterator _Mid = _Right.begin() + this->_Mysize();
        std::copy(_Right.begin(), _Mid, begin());
        insert(end(), _Mid, _Right.end());
      }
    }
    return *this;
  }

  iterator begin() _NOEXCEPT
  {       // return iterator for beginning of mutable sequence
    return iterator(this->_Myoff(), &this->_Get_data());
  }

  const_iterator begin() const _NOEXCEPT
  {       // return iterator for beginning of nonmutable sequence
    return const_iterator(this->_Myoff(), &this->_Get_data());
  }

  iterator end() _NOEXCEPT
  {       // return iterator for end of mutable sequence
    return iterator(this->_Myoff() + this->_Mysize(), &this->_Get_data());
  }

  const_iterator end() const _NOEXCEPT
  {       // return iterator for end of nonmutable sequence
    return const_iterator(this->_Myoff() + this->_Mysize(),
                          &this->_Get_data());
  }

  iterator _Make_iter(const_iterator _Where) const
  {       // make iterator from const_iterator
    return iterator(_Where._Myoff, &this->_Get_data());
  }

  reverse_iterator rbegin() _NOEXCEPT
  {       // return iterator for beginning of reversed mutable sequence
    return reverse_iterator(end());
  }

  const_reverse_iterator rbegin() const _NOEXCEPT
  {       // return iterator for beginning of reversed nonmutable sequence
    return const_reverse_iterator(end());
  }

  reverse_iterator rend() _NOEXCEPT
  {       // return iterator for end of reversed mutable sequence
    return reverse_iterator(begin());
  }

  const_reverse_iterator rend() const _NOEXCEPT
  {       // return iterator for end of reversed nonmutable sequence
    return const_reverse_iterator(begin());
  }

  const_iterator cbegin() const _NOEXCEPT
  {       // return iterator for beginning of nonmutable sequence
    return begin();
  }

  const_iterator cend() const _NOEXCEPT
  {       // return iterator for end of nonmutable sequence
    return end();
  }

  const_reverse_iterator crbegin() const _NOEXCEPT
  {       // return iterator for beginning of reversed nonmutable sequence
    return rbegin();
  }

  const_reverse_iterator crend() const _NOEXCEPT
  {       // return iterator for end of reversed nonmutable sequence
    return rend();
  }

  _NOINLINE void shrink_to_fit()
  {       // reduce capacity
    size_type _Oldcapacity = _DEQUESIZ * this->_Mapsize();
    size_type _Newcapacity = _Oldcapacity / 2;

    if (_Newcapacity < _DEQUESIZ * _DEQUEMAPSIZ)
      _Newcapacity = _DEQUESIZ * _DEQUEMAPSIZ;

    if (   (empty() && 0 < this->_Mapsize())
        || (   !empty()
            && size() <= _Newcapacity
            && _Newcapacity < _Oldcapacity))
    {       // worth shrinking, do it
      _Myt _Tmp(std::make_move_iterator(begin()),
                std::make_move_iterator(end()));
      swap(_Tmp);
    }
  }

  _NOINLINE void resize(size_type _Newsize)
  {       // determine new length, padding as needed
    while (this->_Mysize() < _Newsize)
      emplace_back();

    while (_Newsize < this->_Mysize())
      pop_back();
  }

  _NOINLINE void resize(size_type _Newsize, const value_type& _Val)
  {       // determine new length, padding with _Val elements as needed
    while (this->_Mysize() < _Newsize)
      push_back(_Val);
    while (_Newsize < this->_Mysize())
      pop_back();
  }

  size_type size() const _NOEXCEPT
  {       // return length of sequence
    return this->_Mysize();
  }

  size_type max_size() const _NOEXCEPT
  {       // return maximum possible length of sequence
    return this->_Getal().max_size();
  }

  bool empty() const _NOEXCEPT
  {       // test if sequence is empty
    return this->_Mysize() == 0;
  }

  allocator_type get_allocator() const _NOEXCEPT
  {       // return allocator object for values
    return this->_Getal();
  }

  const_reference at(size_type _Pos) const
  {       // subscript nonmutable sequence with checking
    if (this->_Mysize() <= _Pos)
      __iar_Raise_ran();
    return *(begin() + _Pos);
  }

  reference at(size_type _Pos)
  {       // subscript mutable sequence with checking
    if (this->_Mysize() <= _Pos)
      __iar_Raise_ran();
    return *(begin() + _Pos);
  }

  const_reference operator[](size_type _Pos) const
  {       // subscript nonmutable sequence
    #if _ITERATOR_DEBUG_LEVEL == 2
      if (this->_Mysize() <= _Pos)
        _DEBUG_ERROR("deque subscript out of range");
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    return *(begin() + _Pos);
  }

  reference operator[](size_type _Pos)
  {       // subscript mutable sequence
    #if _ITERATOR_DEBUG_LEVEL == 2
      if (this->_Mysize() <= _Pos)
        _DEBUG_ERROR("deque subscript out of range");
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    return *(begin() + _Pos);
  }

  reference front()
  {       // return first element of mutable sequence
    return *begin();
  }

  const_reference front() const
  {       // return first element of nonmutable sequence
    return *begin();
  }

  reference back()
  {       // return last element of mutable sequence
    return *(end() - 1);
  }

  const_reference back() const
  {       // return last element of nonmutable sequence
    return *(end() - 1);
  }

  _NOINLINE void push_front(const value_type& _Val)
  {       // insert element at beginning
    this->_Orphan_all();
    _PUSH_FRONT_BEGIN;
    this->_Getal().construct(  std::addressof(*this->_Map()[_Block])
                             + _Newoff % _DEQUESIZ, _Val);
    _PUSH_FRONT_END;
  }

  _NOINLINE void pop_front()
  {       // erase element at beginning
    #if _ITERATOR_DEBUG_LEVEL == 2
      if (empty())
        _DEBUG_ERROR("deque empty before pop");
      else
      {       // something to erase, do it
        _Orphan_off(this->_Myoff());
        size_type _Block = this->_Getblock(this->_Myoff());
        this->_Getal().destroy(
          std::addressof(*(this->_Map()[_Block] + this->_Myoff() % _DEQUESIZ)));
        if (--this->_Mysize() == 0)
          this->_Myoff() = 0;
        else
          ++this->_Myoff();
      }
    #else /* _ITERATOR_DEBUG_LEVEL == 2 */
      size_type _Block = this->_Getblock(this->_Myoff());
      this->_Getal().destroy(
        std::addressof(*(this->_Map()[_Block])) + this->_Myoff() % _DEQUESIZ);
      if (--this->_Mysize() == 0)
        this->_Myoff() = 0;
      else
        ++this->_Myoff();
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
  }

  _NOINLINE void push_back(const value_type& _Val)
  {       // insert element at end
    this->_Orphan_all();
    _PUSH_BACK_BEGIN;
    this->_Getal().construct(
      std::addressof(*(this->_Map()[_Block])) + _Newoff % _DEQUESIZ, _Val);
    _PUSH_BACK_END;
  }

  _NOINLINE void pop_back()
  {       // erase element at end
    #if _ITERATOR_DEBUG_LEVEL == 2
      if (empty())
        _DEBUG_ERROR("deque empty before pop");
      else
      {       // something to erase, do it
        size_type _Newoff = this->_Myoff() + this->_Mysize() - 1;
        _Orphan_off(_Newoff);
        size_type _Block = this->_Getblock(_Newoff);
        this->_Getal().destroy(
          std::addressof(*(this->_Map()[_Block] + _Newoff % _DEQUESIZ)));
        if (--this->_Mysize() == 0)
          this->_Myoff() = 0;
      }
    #else /* _ITERATOR_DEBUG_LEVEL == 2 */
      size_type _Newoff = this->_Myoff() + this->_Mysize() - 1;
      size_type _Block = this->_Getblock(_Newoff);
      this->_Getal().destroy(
        std::addressof(*(this->_Map()[_Block] + _Newoff % _DEQUESIZ)));
      if (--this->_Mysize() == 0)
        this->_Myoff() = 0;
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
  }

  template<class _Iter>
  typename enable_if<_Is_iterator<_Iter>::value,
                     void>::type
  _NOINLINE assign(_Iter _First, _Iter _Last)
  {       // assign [_First, _Last), input iterators
    clear();

    for (; _First != _Last; ++_First)
      emplace_back(*_First);
  }

  void assign(size_type _Count, const value_type& _Val)
  {       // assign _Count * _Val
    erase(begin(), end());
    _Insert_n(begin(), _Count, _Val);
  }

  _NOINLINE iterator insert(const_iterator _Where,
                            const value_type& _Val)
  {       // insert _Val at _Where
    size_type _Off = _Where - begin();

    #if _ITERATOR_DEBUG_LEVEL == 2
      if (this->_Mysize() < _Off)
        _DEBUG_ERROR("deque insert iterator outside range");
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    if (_Off <= this->_Mysize() / 2)
    {       // closer to front, push to front then copy
      push_front(_Val);
      std::rotate(begin(), begin() + 1, begin() + 1 + _Off);
    }
    else
    {       // closer to back, push to back then copy
      push_back(_Val);
      std::rotate(begin() + _Off, end() - 1, end());
    }
    return begin() + _Off;
  }

  iterator insert(const_iterator _Where, size_type _Count,
                  const value_type& _Val)
  {       // insert _Count * _Val at _Where
    size_type _Off = _Where - begin();
    _Insert_n(_Where, _Count, _Val);
    return begin() + _Off;
  }

  template<class _Iter>
  typename enable_if<_Is_iterator<_Iter>::value,
                     iterator>::type
  _NOINLINE insert(const_iterator _Where, _Iter _First, _Iter _Last)
  {       // insert [_First, _Last) at _Where, input iterators
    size_type _Off = _Where - begin();

    #if _ITERATOR_DEBUG_LEVEL == 2
      if (this->_Mysize() < _Off)
        _DEBUG_ERROR("deque insert iterator outside range");
      _DEBUG_RANGE(_First, _Last);
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    size_type _Oldsize = this->_Mysize();

    if (_First == _Last)
      ;
    else if (_Off <= this->_Mysize() / 2)
    {       // closer to front, push to front then rotate
      _TRY_BEGIN
        for (; _First != _Last; ++_First)
          push_front(*_First);    // prepend flipped
      _CATCH_ALL
        for (; _Oldsize < this->_Mysize(); )
          pop_front();    // restore old size, at least
        _RERAISE;
      _CATCH_END

      size_type _Num = this->_Mysize() - _Oldsize;
      std::reverse(begin(), begin() + _Num);  // flip new stuff in place
      std::rotate(begin(), begin() + _Num, begin() + _Num + _Off);
    }
    else
    {       // closer to back
      _TRY_BEGIN
        for (; _First != _Last; ++_First)
          push_back(*_First);     // append
      _CATCH_ALL
        for (; _Oldsize < this->_Mysize(); )
          pop_back();     // restore old size, at least
        _RERAISE;
      _CATCH_END

      rotate(begin() + _Off, begin() + _Oldsize, end());
    }
    return begin() + _Off;
  }

  iterator erase(const_iterator _Where)
  {       // erase element at _Where
    return erase(_Where, _Where + 1);
  }

  _NOINLINE iterator erase(const_iterator _First_arg,
                 const_iterator _Last_arg)
  {       // erase [_First, _Last)
    iterator _First = _Make_iter(_First_arg);
    iterator _Last = _Make_iter(_Last_arg);

    #if _ITERATOR_DEBUG_LEVEL == 2
      if (   _Last < _First
          || _First < begin() || end() < _Last)
        _DEBUG_ERROR("deque erase iterator outside range");
      _DEBUG_RANGE(_First, _Last);

      size_type _Off = _First - begin();
      size_type _Count = _Last - _First;
      bool _Moved = 0 < _Off && _Off + _Count < this->_Mysize();
    #else /* _ITERATOR_DEBUG_LEVEL == 2 */
      size_type _Off = _First - begin();
      size_type _Count = _Last - _First;
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    if (_Off < (size_type)(end() - _Last))
    {       // closer to front
      _Move_backward(begin(), _First, _Last); // copy over hole
      for (; 0 < _Count; --_Count)
        pop_front();    // pop copied elements
    }
    else
    {       // closer to back
      _Move(_Last, end(), _First);    // copy over hole
      for (; 0 < _Count; --_Count)
        pop_back();     // pop copied elements
    }

    #if _ITERATOR_DEBUG_LEVEL == 2
      if (_Moved)
        this->_Orphan_all();
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    return begin() + _Off;
  }

  void clear() _NOEXCEPT
  {       // erase all
    _Tidy();
  }

  _NOINLINE void swap(_Myt& _Right) _NOEXCEPT_OP(_Alty::is_always_equal::value)
  {       // exchange contents with _Right
    if (this == &_Right)
      ;       // same object, do nothing
    else if (this->_Getal() == _Right._Getal())
    {       // same allocator, swap control information
      this->_Swap_all(_Right);
      _Swap_adl(this->_Map(),     _Right._Map());
      std::swap(this->_Mapsize(), _Right._Mapsize());
      std::swap(this->_Myoff(),   _Right._Myoff());
      std::swap(this->_Mysize(),  _Right._Mysize());
    }
    else if (_Alty::propagate_on_container_swap::value)
    {       // swap allocators and control information
      this->_Swap_alloc(_Right);
      _Swap_adl(this->_Map(),     _Right._Map());
      std::swap(this->_Mapsize(), _Right._Mapsize());
      std::swap(this->_Myoff(),   _Right._Myoff());
      std::swap(this->_Mysize(),  _Right._Mysize());
    }
    else
    {       // containers are incompatible
      #if _ITERATOR_DEBUG_LEVEL == 2
        _DEBUG_ERROR("deque containers incompatible for swap");
      #else /* ITERATOR_DEBUG_LEVEL == 2 */
        terminate();
      #endif /* ITERATOR_DEBUG_LEVEL == 2 */
    }
  }

protected:
  _NOINLINE void _Insert_n(const_iterator _Where,
                           size_type _Count, const value_type& _Val)
  {       // insert _Count * _Val at _Where
    iterator _Mid;
    size_type _Num;
    size_type _Off = _Where - begin();
    size_type _Rem = this->_Mysize() - _Off;
    size_type _Oldsize = this->_Mysize();

    #if _ITERATOR_DEBUG_LEVEL == 2
      if (this->_Mysize() < _Off)
        _DEBUG_ERROR("deque insert iterator outside range");
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    if (_Off < _Rem)
    {       // closer to front
      _TRY_BEGIN
        if (_Off < _Count)
        {       // insert longer than prefix
          for (_Num = _Count - _Off; 0 < _Num; --_Num)
            push_front(_Val);       // push excess values
          for (_Num = _Off; 0 < _Num; --_Num)
            push_front(begin()[_Count - 1]);        // push prefix

          _Mid = begin() + _Count;
          std::fill(_Mid, _Mid + _Off,
                    _Val);  // fill in rest of values
        }
        else
        {       // insert not longer than prefix
          for (_Num = _Count; 0 < _Num; --_Num)
            push_front(begin()[_Count - 1]);        // push part of prefix

          _Mid = begin() + _Count;
          value_type _Tmp = _Val; // in case _Val is in sequence
          _Move(_Mid + _Count, _Mid + _Off,
                _Mid);  // copy rest of prefix
          std::fill(begin() + _Off, _Mid + _Off,
                    _Tmp);  // fill in values
        }
      _CATCH_ALL
        for (; _Oldsize < this->_Mysize(); )
          pop_front();    // restore old size, at least
        _RERAISE;
      _CATCH_END
    }
    else
    {               // closer to back
      _TRY_BEGIN
        if (_Rem < _Count)
        {       // insert longer than suffix
          for (_Num = _Count - _Rem; 0 < _Num; --_Num)
            push_back(_Val);        // push excess values
          for (_Num = 0; _Num < _Rem; ++_Num)
            push_back(begin()[_Off + _Num]);        // push suffix

          _Mid = begin() + _Off;
          std::fill(_Mid, _Mid + _Rem,
                    _Val);  // fill in rest of values
        }
        else
        {       // insert not longer than prefix
          for (_Num = 0; _Num < _Count; ++_Num)
            push_back(begin()[_Off + _Rem
                              - _Count + _Num]);      // push part of prefix
          
          _Mid = begin() + _Off;
          value_type _Tmp = _Val; // in case _Val is in sequence
          _Move_backward(_Mid, _Mid + _Rem - _Count,
                         _Mid + _Rem);   // copy rest of prefix
          std::fill(_Mid, _Mid + _Count,
                    _Tmp);  // fill in values
        }
      _CATCH_ALL
        for (; _Oldsize < this->_Mysize(); )
          pop_back();     // restore old size, at least
        _RERAISE;
      _CATCH_END
    }
  }

  _NOINLINE void _Growmap(size_type _Count)
  {       // grow map by at least _Count pointers, _Mapsize() a power of 2
    _STATIC_ASSERT2(1 < _DEQUEMAPSIZ,
               "The __iar_Raise_len() test should always be performed.");

    typedef typename _Alpty::pointer _Blockptr;
    _Alpty _Almap(this->_Getal());
    size_type _Newsize = 0 < this->_Mapsize() ? this->_Mapsize() : 1;
    while (_Newsize - this->_Mapsize() < _Count || _Newsize < _DEQUEMAPSIZ)
    {       // scale _Newsize to 2^N >= _Mapsize() + _Count
      if (max_size() / _DEQUESIZ - _Newsize < _Newsize)
        __iar_Raise_len();        // result too long
      _Newsize *= 2;
    }
    _Count = _Newsize - this->_Mapsize();

    size_type _Myboff = this->_Myoff() / _DEQUESIZ;
    _Mapptr _Newmap = _Almap.allocate(this->_Mapsize() + _Count);
    _Mapptr _Myptr = _Newmap + _Myboff;

    _Myptr = _Uninitialized_copy(this->_Map() + _Myboff,
                                 this->_Map() + this->_Mapsize(),
                                 _Myptr, _Almap);        // copy initial to end
    if (_Myboff <= _Count)
    {       // increment greater than offset of initial block
      _Myptr = _Uninitialized_copy(this->_Map(),
                                   this->_Map() + _Myboff,
                                   _Myptr, _Almap);        // copy rest of old
      _Uninitialized_default_fill_n(_Myptr, _Count - _Myboff,
                                    _Almap);        // clear suffix of new
      _Uninitialized_default_fill_n(_Newmap, _Myboff,
                                    _Almap);        // clear prefix of new
    }
    else
    {       // increment not greater than offset of initial block
      _Uninitialized_copy(this->_Map(),
                          this->_Map() + _Count,
                          _Myptr, _Almap);        // copy more old
      _Myptr = _Uninitialized_copy(this->_Map() + _Count,
                                   this->_Map() + _Myboff,
                                   _Newmap, _Almap);       // copy rest of old
      _Uninitialized_default_fill_n(_Myptr, _Count,
                                    _Almap);      // clear rest to initial block
    }

    _Destroy_range(this->_Map() + _Myboff, this->_Map() + this->_Mapsize(),
                   _Almap);
    if (this->_Map() != _Mapptr())
      _Almap.deallocate(this->_Map(),
                        this->_Mapsize());        // free storage for old

    this->_Map() = _Newmap;   // point at new
    this->_Mapsize() += _Count;
  }

  _NOINLINE void _Tidy()
  {       // free all storage
    _Alpty _Almap(this->_Getal());
    while (!empty())
      pop_back();
    for (size_type _Block = this->_Mapsize(); 0 < _Block; )
    {       // free storage for a block and destroy pointer
      if (this->_Map()[--_Block] != pointer())
      {       // free block and destroy its pointer
        this->_Getal().deallocate(this->_Map()[_Block], _DEQUESIZ);
        this->_Getal().destroy(&this->_Map()[_Block]);
      }
    }

    if (this->_Map() != _Mapptr())
      _Almap.deallocate(this->_Map(),
                        this->_Mapsize());        // free storage for map
    this->_Mapsize() = 0;
    this->_Map() = _Mapptr();
  }

  #if _ITERATOR_DEBUG_LEVEL == 2
    _NOINLINE void _Orphan_off(size_type _Offlo) const
    {       // orphan iterators with specified offset(s)
      size_type _Offhigh = this->_Myoff() + this->_Mysize() <= _Offlo + 1
        ? (size_type)(-1) : _Offlo;
      if (_Offlo == this->_Myoff())
        _Offlo = 0;

      __iar_Lockit_Debug _Lock;
      const_iterator **_Pnext = (const_iterator **)this->_Getpfirst();
      if (_Pnext != 0)
        while (*_Pnext != 0)
          if ((*_Pnext)->_Myoff < _Offlo
              || _Offhigh < (*_Pnext)->_Myoff)
            _Pnext = (const_iterator **)(*_Pnext)->_Getpnext();
          else
          {       // orphan the iterator
            (*_Pnext)->_Clrcont();
            *_Pnext = *(const_iterator **)(*_Pnext)->_Getpnext();
          }
    }
  #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
};

// deque TEMPLATE OPERATORS
template<class _Ty,
         class _Alloc> inline
void swap(deque<_Ty, _Alloc>& _Left, deque<_Ty, _Alloc>& _Right)
  _NOEXCEPT_OP(_NOEXCEPT_OP(_Left.swap(_Right)))
{       // swap _Left and _Right deques
  _Left.swap(_Right);
}

template<class _Ty,
         class _Alloc> inline
bool operator==(const deque<_Ty, _Alloc>& _Left,
                const deque<_Ty, _Alloc>& _Right)
{       // test for deque equality
  return    _Left.size() == _Right.size()
         && std::equal(_Left.begin(), _Left.end(), _Right.begin());
}

template<class _Ty,
         class _Alloc> inline
bool operator!=(const deque<_Ty, _Alloc>& _Left,
                const deque<_Ty, _Alloc>& _Right)
{       // test for deque inequality
  return !(_Left == _Right);
}

template<class _Ty,
         class _Alloc> inline
bool operator<(const deque<_Ty, _Alloc>& _Left,
               const deque<_Ty, _Alloc>& _Right)
{       // test if _Left < _Right for deques
  return std::lexicographical_compare(_Left.begin(), _Left.end(),
                                      _Right.begin(), _Right.end());
}

template<class _Ty,
         class _Alloc> inline
bool operator<=(const deque<_Ty, _Alloc>& _Left,
                const deque<_Ty, _Alloc>& _Right)
{       // test if _Left <= _Right for deques
  return !(_Right < _Left);
}

template<class _Ty,
         class _Alloc> inline
bool operator>(const deque<_Ty, _Alloc>& _Left,
               const deque<_Ty, _Alloc>& _Right)
{       // test if _Left > _Right for deques
  return _Right < _Left;
}

template<class _Ty,
         class _Alloc> inline
bool operator>=(const deque<_Ty, _Alloc>& _Left,
                const deque<_Ty, _Alloc>& _Right)
{       // test if _Left >= _Right for deques
  return !(_Left < _Right);
}
} /* namespace std */

#endif /* _DEQUE_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0576 */
