/*
 * M*LIB - dynamic priority queue module
 *
 * Copyright (c) 2017-2023, Patrick Pelissier
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * + Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * + Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MSTARLIB_PRIOQUEUE_H
#define MSTARLIB_PRIOQUEUE_H

#include "m-core.h"
#include "m-array.h"            /* Priority queue are built upon array */

/* Priority queue based on binary heap implementation */

/* Define a prioqueue of a given type and its associated functions.
   USAGE: PRIOQUEUE_DEF(name, type [, oplist_of_the_type]) */
#define M_PRIOQUEUE_DEF(name, ...)                                            \
  M_PRIOQUEUE_DEF_AS(name, M_F(name,_t), M_F(name,_it_t), __VA_ARGS__)


/* Define a prioqueue of a given type and its associated functions.
  as the name name_t with an iterator named it_t
   USAGE: PRIOQUEUE_DEF_AS(name, name_t, it_t, type [, oplist_of_the_type]) */
#define M_PRIOQUEUE_DEF_AS(name, name_t, it_t, ...)                           \
  M_BEGIN_PROTECTED_CODE                                                      \
  M_PR1OQUEUE_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__)                              \
                    ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t, it_t ), \
                     (name, __VA_ARGS__,                                        name_t, it_t ))) \
  M_END_PROTECTED_CODE


/* Define the oplist of a prioqueue of type.
   USAGE: PRIOQUEUE_OPLIST(name[, oplist of the type]) */
#define M_PRIOQUEUE_OPLIST(...)                                               \
  M_PR1OQUEUE_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__)                           \
                       ((__VA_ARGS__, M_BASIC_OPLIST),                        \
                        (__VA_ARGS__ )))


/*****************************************************************************/
/********************************** INTERNAL *********************************/
/*****************************************************************************/

/* Deferred evaluation for the definition,
   so that all arguments are evaluated before further expansion */
#define M_PR1OQUEUE_OPLIST_P1(arg) M_PR1OQUEUE_OPLIST_P2 arg

/* Validation of the given oplist */
#define M_PR1OQUEUE_OPLIST_P2(name, oplist)                                   \
  M_IF_OPLIST(oplist)(M_PR1OQUEUE_OPLIST_P3, M_PR1OQUEUE_OPLIST_FAILURE)(name, oplist)

/* Prepare a clean compilation failure */
#define M_PR1OQUEUE_OPLIST_FAILURE(name, oplist)                              \
  ((M_LIB_ERROR(ARGUMENT_OF_PRIOQUEUE_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))

/* Define oplist of a priority queue */
#define M_PR1OQUEUE_OPLIST_P3(name, oplist)                                   \
  (INIT(M_F(name, _init))                                                     \
   ,INIT_SET(M_F(name, _init_set))                                            \
   ,INIT_WITH(API_1(M_INIT_VAI))                                              \
   ,SET(M_F(name, _set))                                                      \
   ,CLEAR(M_F(name, _clear))                                                  \
   ,INIT_MOVE(M_F(name, _init_move))                                          \
   ,MOVE(M_F(name, _move))                                                    \
   ,SWAP(M_F(name, _swap))                                                    \
   ,NAME(name)                                                                \
   ,TYPE(M_F(name,_ct))                                                       \
   ,SUBTYPE(M_F(name, _subtype_ct))                                           \
   ,RESET(M_F(name,_reset))                                                   \
   ,PUSH(M_F(name,_push))                                                     \
   ,POP(M_F(name,_pop))                                                       \
   ,OPLIST(oplist)                                                            \
   ,EMPTY_P(M_F(name, _empty_p))                                              \
   ,GET_SIZE(M_F(name, _size))                                                \
   ,IT_TYPE(M_F(name, _it_ct))                                                \
   ,IT_FIRST(M_F(name,_it))                                                   \
   ,IT_END(M_F(name,_it_end))                                                 \
   ,IT_SET(M_F(name,_it_set))                                                 \
   ,IT_END_P(M_F(name,_end_p))                                                \
   ,IT_EQUAL_P(M_F(name,_it_equal_p))                                         \
   ,IT_LAST_P(M_F(name,_last_p))                                              \
   ,IT_NEXT(M_F(name,_next))                                                  \
   ,IT_CREF(M_F(name,_cref))                                                  \
   ,M_IF_METHOD(GET_STR, oplist)(GET_STR(M_F(name, _get_str)),)               \
   ,M_IF_METHOD(PARSE_STR, oplist)(PARSE_STR(M_F(name, _parse_str)),)         \
   ,M_IF_METHOD(OUT_STR, oplist)(OUT_STR(M_F(name, _out_str)),)               \
   ,M_IF_METHOD(IN_STR, oplist)(IN_STR(M_F(name, _in_str)),)                  \
   ,M_IF_METHOD(OUT_SERIAL, oplist)(OUT_SERIAL(M_F(name, _out_serial)),)      \
   ,M_IF_METHOD(IN_SERIAL, oplist)(IN_SERIAL(M_F(name, _in_serial)),)         \
   )


/********************************** INTERNAL *********************************/

/* Deferred evaluation for the definition,
   so that all arguments are evaluated before further expansion */
#define M_PR1OQUEUE_DEF_P1(arg)    M_ID( M_PR1OQUEUE_DEF_P2 arg )

/* Validate the oplist before going further */
#define M_PR1OQUEUE_DEF_P2(name, type, oplist, prioqueue_t, it_t)             \
  M_IF_OPLIST(oplist)(M_PR1OQUEUE_DEF_P3, M_PR1OQUEUE_DEF_FAILURE)(name, type, oplist, prioqueue_t, it_t)

/* Stop processing with a compilation failure */
#define M_PR1OQUEUE_DEF_FAILURE(name, type, oplist, prioqueue_t, it_t)        \
  M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(PRIOQUEUE_DEF): the given argument is not a valid oplist: " #oplist)

/* Define the priority queue:
   - name: prefix to use,
   - type: type of the contained objects,
   - oplist: oplist of the contained objects,
   - prioqueue_t: type of the container,
   - it_t: iterator of the container
*/
#define M_PR1OQUEUE_DEF_P3(name, type, oplist, prioqueue_t, it_t)             \
  /* Definition of the internal array used to construct the priority queue */ \
  ARRAY_DEF(M_F(name, _array), type, oplist)                                  \
  M_PR1OQUEUE_DEF_TYPE(name, type, oplist, prioqueue_t, it_t)                 \
  M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist)                            \
  M_PR1OQUEUE_DEF_CORE(name, type, oplist, prioqueue_t, it_t)                 \
  M_PR1OQUEUE_DEF_IT(name, type, oplist, prioqueue_t, it_t)                   \
  M_PR1OQUEUE_DEF_IO(name, type, oplist, prioqueue_t, it_t)                   \
  M_EMPLACE_QUEUE_DEF(name, prioqueue_t, M_F(name, _emplace), oplist, M_EMPLACE_QUEUE_GENE)

/* Define the types */
#define M_PR1OQUEUE_DEF_TYPE(name, type, oplist, prioqueue_t, it_t)           \
                                                                              \
  /* Define the priority queue over the defined array */                      \
  typedef struct M_F(name, _s) {                                              \
    M_F(name, _array_t) array;                                                \
  } prioqueue_t[1];                                                           \
  /* Define the pointer references to the priority queue */                   \
  typedef struct M_F(name, _s) *M_F(name, _ptr);                              \
  typedef const struct M_F(name, _s) *M_F(name, _srcptr);                     \
                                                                              \
  /* The iterator is the same one as the one of the internal array */         \
  typedef M_F(name, _array_it_t) it_t;                                        \
                                                                              \
  /* Definition of the internal types used by the oplist */                   \
  typedef prioqueue_t M_F(name, _ct);                                         \
  typedef type        M_F(name, _subtype_ct);                                 \
  typedef it_t        M_F(name, _it_ct);                                      \

/* Define the core functions */
#define M_PR1OQUEUE_DEF_CORE(name, type, oplist, prioqueue_t, it_t)           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _init)(prioqueue_t p)                                             \
  {                                                                           \
    M_F(name, _array_init)(p->array);                                         \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _init_set)(prioqueue_t p, prioqueue_t const o)                    \
  {                                                                           \
    M_F(name, _array_init_set)(p->array, o->array);                           \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _set)(prioqueue_t p, prioqueue_t const o)                         \
  {                                                                           \
    M_F(name, _array_set)(p->array, o->array);                                \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _clear)(prioqueue_t p)                                            \
  {                                                                           \
    M_F(name, _array_clear)(p->array);                                        \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _init_move)(prioqueue_t p, prioqueue_t o)                         \
  {                                                                           \
    M_F(name, _array_init_move)(p->array, o->array);                          \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _move)(prioqueue_t p, prioqueue_t o)                              \
  {                                                                           \
    M_F(name, _array_move)(p->array, o->array);                               \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _swap)(prioqueue_t p, prioqueue_t o)                              \
  {                                                                           \
    M_F(name, _array_swap)(p->array, o->array);                               \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _reset)(prioqueue_t p)                                            \
  {                                                                           \
    M_F(name, _array_reset)(p->array);                                        \
  }                                                                           \
                                                                              \
  M_INLINE size_t                                                             \
  M_F(name, _i_parent)(size_t i)                                              \
  {                                                                           \
    M_ASSERT (i > 0);                                                         \
    return (i - 1) / 2;                                                       \
  }                                                                           \
                                                                              \
  M_INLINE size_t                                                             \
  M_F(name, _i_lchild)(size_t i)                                              \
  {                                                                           \
    M_ASSERT(i <= ((SIZE_MAX)-2)/2);                                          \
    return 2*i + 1;                                                           \
  }                                                                           \
                                                                              \
  M_INLINE size_t                                                             \
  M_F(name, _i_rchild)(size_t i)                                              \
  {                                                                           \
    M_ASSERT(i <= ((SIZE_MAX)-2)/2);                                          \
    return 2*i + 2;                                                           \
  }                                                                           \
                                                                              \
  M_INLINE int                                                                \
  M_F(name, _i_cmp)(const prioqueue_t p, size_t i, size_t j)                  \
  {                                                                           \
    return M_CALL_CMP(oplist, *M_F(name, _array_cget)(p->array, i),           \
                      *M_F(name, _array_cget)(p->array, j));                  \
  }                                                                           \
                                                                              \
  M_INLINE bool                                                               \
  M_F(name, _empty_p)(prioqueue_t const p)                                    \
  {                                                                           \
    return M_F(name, _array_empty_p)(p->array);                               \
  }                                                                           \
                                                                              \
  M_INLINE size_t                                                             \
  M_F(name, _size)(prioqueue_t const p)                                       \
  {                                                                           \
    return M_F(name, _array_size)(p->array);                                  \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _push)(prioqueue_t p, type const x)                               \
  {                                                                           \
    /* Push back the new element at the end of the array */                   \
    M_F(name, _array_push_back)(p->array, x);                                 \
                                                                              \
    /* Reorder the array by swapping with its parent                          \
     * until it reaches the right position */                                 \
    size_t i = M_F(name, _array_size)(p->array)-1;                            \
    while (i > 0) {                                                           \
      size_t j = M_F(name, _i_parent)(i);                                     \
      if (M_F(name, _i_cmp)(p, j, i) <= 0)                                    \
        break;                                                                \
      M_F(name, _array_swap_at) (p->array, i, j);                             \
      i = j;                                                                  \
    }                                                                         \
  }                                                                           \
                                                                              \
  M_INLINE type const *                                                       \
  M_F(name, _front)(prioqueue_t const p)                                      \
  {                                                                           \
    return M_F(name, _array_cget)(p->array, 0);                               \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _pop)(type *x, prioqueue_t p)                                     \
  {                                                                           \
    /* Swap the front element with the last element */                        \
    size_t size = M_F(name, _array_size)(p->array)-1;                         \
    M_F(name, _array_swap_at) (p->array, 0, size);                            \
    /* Swap the new last element  */                                          \
    M_F(name, _array_pop_back)(x, p->array);                                  \
                                                                              \
    /* Reorder the heap */                                                    \
    size_t i = 0;                                                             \
    while (true) {                                                            \
      size_t child = M_F(name, _i_lchild)(i);                                 \
      if (child >= size)                                                      \
        break;                                                                \
      size_t otherChild = M_F(name, _i_rchild)(i);                            \
      if (otherChild < size                                                   \
          && M_F(name, _i_cmp)(p, otherChild, child) < 0 ) {                  \
        child = otherChild;                                                   \
      }                                                                       \
      if (M_F(name, _i_cmp)(p, i, child) <= 0)                                \
        break;                                                                \
      M_F(name, _array_swap_at) (p->array, i, child);                         \
      i = child;                                                              \
    }                                                                         \
  }                                                                           \
                                                                              \
  M_IF_METHOD(EQUAL, oplist)                                                  \
  (                                                                           \
    /* EQUAL & CMP may be uncorrelated */                                     \
    M_INLINE bool                                                             \
    M_F(name, _equal_p)(prioqueue_t const p, prioqueue_t const q)             \
    {                                                                         \
      return M_F(name, _array_equal_p)(p->array, q->array);                   \
    }                                                                         \
                                                                              \
   M_INLINE size_t                                                            \
   M_F(name, _i_find)(prioqueue_t p, type const x)                            \
   {                                                                          \
     size_t size = M_F(name, _array_size)(p->array);                          \
     size_t i = 0;                                                            \
     for(i = 0; i < size; i++) {                                              \
       /* We cannot use CMP and the partial order to go faster                \
        EQUAL & CMP may be uncorrelated */                                    \
       if (M_CALL_EQUAL(oplist, *M_F(name, _array_cget)(p->array, i), x))     \
         break;                                                               \
     }                                                                        \
     return i;                                                                \
   }                                                                          \
                                                                              \
   M_INLINE bool                                                              \
   M_F(name, _erase)(prioqueue_t p, type const x)                             \
   {                                                                          \
     /* First pass: search for an item EQUAL to x */                          \
     size_t size = M_F(name, _array_size)(p->array);                          \
     size_t i = M_F(name, _i_find)(p, x);                                     \
     /* If x is not found, then stop */                                       \
     if (i >= size)                                                           \
       return false;                                                          \
     /* Swap the found item and the last element */                           \
     size--;                                                                  \
     M_F(name, _array_swap_at) (p->array, i, size);                           \
     M_F(name, _array_pop_back)(NULL, p->array);                              \
     /* Move back the last swapped element to its right position in the heap */ \
     while (true) {                                                           \
       size_t child = M_F(name, _i_lchild)(i);                                \
       if (child >= size) break;                                              \
       size_t otherChild = M_F(name, _i_rchild)(i);                           \
       if (otherChild < size                                                  \
           && M_F(name, _i_cmp)(p, otherChild, child) < 0 ) {                 \
         child = otherChild;                                                  \
       }                                                                      \
       if (M_F(name, _i_cmp)(p, i, child) <= 0) break;                        \
       M_F(name, _array_swap_at) (p->array, i, child);                        \
       i = child;                                                             \
     }                                                                        \
     return true;                                                             \
   }                                                                          \
                                                                              \
   M_INLINE void                                                              \
   M_F(name, _update)(prioqueue_t p, type const xold, type const xnew)        \
   {                                                                          \
     /* NOTE: xold can be the same pointer than xnew */                       \
     /* First pass: search for an item EQUAL to x */                          \
     size_t size = M_F(name, _array_size)(p->array);                          \
     size_t i = M_F(name, _i_find)(p, xold);                                  \
     /* We shall have found the item */                                       \
     M_ASSERT (i < size);                                                     \
     /* Test if the position of the old data is further or nearer than the new */ \
     int cmp = M_CALL_CMP(oplist, *M_F(name, _array_cget)(p->array, i), xnew); \
     /* Set the found item to the new element */                              \
     M_F(name, _array_set_at) (p->array, i, xnew);                            \
     if (cmp < 0) {                                                           \
      /* Move back the updated element to its new position, further in the heap */ \
      while (true) {                                                          \
        size_t child = M_F(name, _i_lchild)(i);                               \
        if (child >= size) break;                                             \
        size_t otherChild = M_F(name, _i_rchild)(i);                          \
        if (otherChild < size                                                 \
            && M_F(name, _i_cmp)(p, otherChild, child) < 0 ) {                \
          child = otherChild;                                                 \
        }                                                                     \
        if (M_F(name, _i_cmp)(p, i, child) <= 0) break;                       \
        M_F(name, _array_swap_at) (p->array, i, child);                       \
        i = child;                                                            \
      }                                                                       \
     } else {                                                                 \
      /* Move back the updated element to its new position, nearest in the heap */ \
      while (i > 0) {                                                         \
        size_t parent = M_F(name, _i_parent)(i);                              \
        if (M_F(name, _i_cmp)(p, parent, i) <= 0) break;                      \
        M_F(name, _array_swap_at) (p->array, i, parent);                      \
        i = parent;                                                           \
      }                                                                       \
     }                                                                        \
   }                                                                          \
   , /* No EQUAL */ )                                                         \

/* Define the IT based functions */
#define M_PR1OQUEUE_DEF_IT(name, type, oplist, prioqueue_t, it_t)             \
                                                                              \
  /* Define iterators over the array iterator */                              \
  M_INLINE void                                                               \
  M_F(name, _it)(it_t it, prioqueue_t const v)                                \
  {                                                                           \
    M_F(name, _array_it)(it, v->array);                                       \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _it_last)(it_t it, prioqueue_t const v)                           \
  {                                                                           \
    M_F(name, _array_it_last)(it, v->array);                                  \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _it_end)(it_t it, prioqueue_t const v)                            \
  {                                                                           \
    M_F(name, _array_it_end)(it, v->array);                                   \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _it_set)(it_t it, const it_t org)                                 \
  {                                                                           \
    M_F(name, _array_it_set)(it, org);                                        \
  }                                                                           \
                                                                              \
  M_INLINE bool                                                               \
  M_F(name, _end_p)(const it_t it)                                            \
  {                                                                           \
    return M_F(name, _array_end_p)(it);                                       \
  }                                                                           \
                                                                              \
  M_INLINE bool                                                               \
  M_F(name, _last_p)(const it_t it)                                           \
  {                                                                           \
    return M_F(name, _array_last_p)(it);                                      \
  }                                                                           \
                                                                              \
  M_INLINE bool                                                               \
  M_F(name, _it_equal_p)(const it_t it1,                                      \
                         const it_t it2)                                      \
  {                                                                           \
    return M_F(name, _array_it_equal_p)(it1, it2);                            \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _next)(it_t it)                                                   \
  {                                                                           \
    M_F(name, _array_next)(it);                                               \
  }                                                                           \
                                                                              \
  M_INLINE void                                                               \
  M_F(name, _previous)(it_t it)                                               \
  {                                                                           \
    M_F(name, _array_previous)(it);                                           \
  }                                                                           \
                                                                              \
  M_INLINE type const *                                                       \
  M_F(name, _cref)(const it_t it)                                             \
  {                                                                           \
    return M_F(name, _array_cref)(it);                                        \
  }                                                                           \

/* Define the IO functions */
#define M_PR1OQUEUE_DEF_IO(name, type, oplist, prioqueue_t, it_t)             \
  M_IF_METHOD(OUT_STR, oplist)(                                               \
  M_INLINE void                                                               \
  M_F(name, _out_str)(FILE *file, const prioqueue_t p)                        \
  {                                                                           \
    M_F(name, _array_out_str)(file, p->array);                                \
  }                                                                           \
  ,/* No OUT_STR */)                                                          \
                                                                              \
  M_IF_METHOD(IN_STR, oplist)(                                                \
  M_INLINE bool                                                               \
  M_F(name, _in_str)(prioqueue_t p, FILE *file)                               \
  {                                                                           \
    return M_F(name, _array_in_str)(p->array, file);                          \
  }                                                                           \
  ,/* No IN_STR */)                                                           \
                                                                              \
  M_IF_METHOD(GET_STR, oplist)(                                               \
  M_INLINE void                                                               \
  M_F(name, _get_str)(string_t str, const prioqueue_t p, bool append)         \
  {                                                                           \
    M_F(name, _array_get_str)(str, p->array, append);                         \
  }                                                                           \
  ,/* No GET_STR */)                                                          \
                                                                              \
  M_IF_METHOD(PARSE_STR, oplist)(                                             \
  M_INLINE bool                                                               \
  M_F(name, _parse_str)(prioqueue_t p, const char str[], const char **endp)   \
  {                                                                           \
    return M_F(name, _array_parse_str)(p->array, str, endp);                  \
  }                                                                           \
  ,/* No PARSE_STR */)                                                        \
                                                                              \
  M_IF_METHOD(OUT_SERIAL, oplist)(                                            \
  M_INLINE m_serial_return_code_t                                             \
  M_F(name, _out_serial)(m_serial_write_t f, const prioqueue_t p)             \
  {                                                                           \
    return M_F(name, _array_out_serial)(f, p->array);                         \
  }                                                                           \
  ,/* No OUT_SERIAL */)                                                       \
                                                                              \
  M_IF_METHOD2(IN_SERIAL, INIT, oplist)(                                      \
  M_INLINE m_serial_return_code_t                                             \
  M_F(name, _in_serial)(prioqueue_t p, m_serial_read_t f)                     \
  {                                                                           \
    return M_F(name, _array_in_serial)(p->array, f);                          \
  }                                                                           \
  ,/* No in_SERIAL */)                                                        \


// TODO: set all & remove all function

/********************************** INTERNAL *********************************/

#if M_USE_SMALL_NAME
#define PRIOQUEUE_DEF M_PRIOQUEUE_DEF
#define PRIOQUEUE_DEF_AS M_PRIOQUEUE_DEF_AS
#define PRIOQUEUE_OPLIST M_PRIOQUEUE_OPLIST
#endif

#endif
