1*8e33eff8Schristos /* 2*8e33eff8Schristos * A Pairing Heap implementation. 3*8e33eff8Schristos * 4*8e33eff8Schristos * "The Pairing Heap: A New Form of Self-Adjusting Heap" 5*8e33eff8Schristos * https://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdf 6*8e33eff8Schristos * 7*8e33eff8Schristos * With auxiliary twopass list, described in a follow on paper. 8*8e33eff8Schristos * 9*8e33eff8Schristos * "Pairing Heaps: Experiments and Analysis" 10*8e33eff8Schristos * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.2988&rep=rep1&type=pdf 11*8e33eff8Schristos * 12*8e33eff8Schristos ******************************************************************************* 13*8e33eff8Schristos */ 14*8e33eff8Schristos 15*8e33eff8Schristos #ifndef PH_H_ 16*8e33eff8Schristos #define PH_H_ 17*8e33eff8Schristos 18*8e33eff8Schristos /* Node structure. */ 19*8e33eff8Schristos #define phn(a_type) \ 20*8e33eff8Schristos struct { \ 21*8e33eff8Schristos a_type *phn_prev; \ 22*8e33eff8Schristos a_type *phn_next; \ 23*8e33eff8Schristos a_type *phn_lchild; \ 24*8e33eff8Schristos } 25*8e33eff8Schristos 26*8e33eff8Schristos /* Root structure. */ 27*8e33eff8Schristos #define ph(a_type) \ 28*8e33eff8Schristos struct { \ 29*8e33eff8Schristos a_type *ph_root; \ 30*8e33eff8Schristos } 31*8e33eff8Schristos 32*8e33eff8Schristos /* Internal utility macros. */ 33*8e33eff8Schristos #define phn_lchild_get(a_type, a_field, a_phn) \ 34*8e33eff8Schristos (a_phn->a_field.phn_lchild) 35*8e33eff8Schristos #define phn_lchild_set(a_type, a_field, a_phn, a_lchild) do { \ 36*8e33eff8Schristos a_phn->a_field.phn_lchild = a_lchild; \ 37*8e33eff8Schristos } while (0) 38*8e33eff8Schristos 39*8e33eff8Schristos #define phn_next_get(a_type, a_field, a_phn) \ 40*8e33eff8Schristos (a_phn->a_field.phn_next) 41*8e33eff8Schristos #define phn_prev_set(a_type, a_field, a_phn, a_prev) do { \ 42*8e33eff8Schristos a_phn->a_field.phn_prev = a_prev; \ 43*8e33eff8Schristos } while (0) 44*8e33eff8Schristos 45*8e33eff8Schristos #define phn_prev_get(a_type, a_field, a_phn) \ 46*8e33eff8Schristos (a_phn->a_field.phn_prev) 47*8e33eff8Schristos #define phn_next_set(a_type, a_field, a_phn, a_next) do { \ 48*8e33eff8Schristos a_phn->a_field.phn_next = a_next; \ 49*8e33eff8Schristos } while (0) 50*8e33eff8Schristos 51*8e33eff8Schristos #define phn_merge_ordered(a_type, a_field, a_phn0, a_phn1, a_cmp) do { \ 52*8e33eff8Schristos a_type *phn0child; \ 53*8e33eff8Schristos \ 54*8e33eff8Schristos assert(a_phn0 != NULL); \ 55*8e33eff8Schristos assert(a_phn1 != NULL); \ 56*8e33eff8Schristos assert(a_cmp(a_phn0, a_phn1) <= 0); \ 57*8e33eff8Schristos \ 58*8e33eff8Schristos phn_prev_set(a_type, a_field, a_phn1, a_phn0); \ 59*8e33eff8Schristos phn0child = phn_lchild_get(a_type, a_field, a_phn0); \ 60*8e33eff8Schristos phn_next_set(a_type, a_field, a_phn1, phn0child); \ 61*8e33eff8Schristos if (phn0child != NULL) { \ 62*8e33eff8Schristos phn_prev_set(a_type, a_field, phn0child, a_phn1); \ 63*8e33eff8Schristos } \ 64*8e33eff8Schristos phn_lchild_set(a_type, a_field, a_phn0, a_phn1); \ 65*8e33eff8Schristos } while (0) 66*8e33eff8Schristos 67*8e33eff8Schristos #define phn_merge(a_type, a_field, a_phn0, a_phn1, a_cmp, r_phn) do { \ 68*8e33eff8Schristos if (a_phn0 == NULL) { \ 69*8e33eff8Schristos r_phn = a_phn1; \ 70*8e33eff8Schristos } else if (a_phn1 == NULL) { \ 71*8e33eff8Schristos r_phn = a_phn0; \ 72*8e33eff8Schristos } else if (a_cmp(a_phn0, a_phn1) < 0) { \ 73*8e33eff8Schristos phn_merge_ordered(a_type, a_field, a_phn0, a_phn1, \ 74*8e33eff8Schristos a_cmp); \ 75*8e33eff8Schristos r_phn = a_phn0; \ 76*8e33eff8Schristos } else { \ 77*8e33eff8Schristos phn_merge_ordered(a_type, a_field, a_phn1, a_phn0, \ 78*8e33eff8Schristos a_cmp); \ 79*8e33eff8Schristos r_phn = a_phn1; \ 80*8e33eff8Schristos } \ 81*8e33eff8Schristos } while (0) 82*8e33eff8Schristos 83*8e33eff8Schristos #define ph_merge_siblings(a_type, a_field, a_phn, a_cmp, r_phn) do { \ 84*8e33eff8Schristos a_type *head = NULL; \ 85*8e33eff8Schristos a_type *tail = NULL; \ 86*8e33eff8Schristos a_type *phn0 = a_phn; \ 87*8e33eff8Schristos a_type *phn1 = phn_next_get(a_type, a_field, phn0); \ 88*8e33eff8Schristos \ 89*8e33eff8Schristos /* \ 90*8e33eff8Schristos * Multipass merge, wherein the first two elements of a FIFO \ 91*8e33eff8Schristos * are repeatedly merged, and each result is appended to the \ 92*8e33eff8Schristos * singly linked FIFO, until the FIFO contains only a single \ 93*8e33eff8Schristos * element. We start with a sibling list but no reference to \ 94*8e33eff8Schristos * its tail, so we do a single pass over the sibling list to \ 95*8e33eff8Schristos * populate the FIFO. \ 96*8e33eff8Schristos */ \ 97*8e33eff8Schristos if (phn1 != NULL) { \ 98*8e33eff8Schristos a_type *phnrest = phn_next_get(a_type, a_field, phn1); \ 99*8e33eff8Schristos if (phnrest != NULL) { \ 100*8e33eff8Schristos phn_prev_set(a_type, a_field, phnrest, NULL); \ 101*8e33eff8Schristos } \ 102*8e33eff8Schristos phn_prev_set(a_type, a_field, phn0, NULL); \ 103*8e33eff8Schristos phn_next_set(a_type, a_field, phn0, NULL); \ 104*8e33eff8Schristos phn_prev_set(a_type, a_field, phn1, NULL); \ 105*8e33eff8Schristos phn_next_set(a_type, a_field, phn1, NULL); \ 106*8e33eff8Schristos phn_merge(a_type, a_field, phn0, phn1, a_cmp, phn0); \ 107*8e33eff8Schristos head = tail = phn0; \ 108*8e33eff8Schristos phn0 = phnrest; \ 109*8e33eff8Schristos while (phn0 != NULL) { \ 110*8e33eff8Schristos phn1 = phn_next_get(a_type, a_field, phn0); \ 111*8e33eff8Schristos if (phn1 != NULL) { \ 112*8e33eff8Schristos phnrest = phn_next_get(a_type, a_field, \ 113*8e33eff8Schristos phn1); \ 114*8e33eff8Schristos if (phnrest != NULL) { \ 115*8e33eff8Schristos phn_prev_set(a_type, a_field, \ 116*8e33eff8Schristos phnrest, NULL); \ 117*8e33eff8Schristos } \ 118*8e33eff8Schristos phn_prev_set(a_type, a_field, phn0, \ 119*8e33eff8Schristos NULL); \ 120*8e33eff8Schristos phn_next_set(a_type, a_field, phn0, \ 121*8e33eff8Schristos NULL); \ 122*8e33eff8Schristos phn_prev_set(a_type, a_field, phn1, \ 123*8e33eff8Schristos NULL); \ 124*8e33eff8Schristos phn_next_set(a_type, a_field, phn1, \ 125*8e33eff8Schristos NULL); \ 126*8e33eff8Schristos phn_merge(a_type, a_field, phn0, phn1, \ 127*8e33eff8Schristos a_cmp, phn0); \ 128*8e33eff8Schristos phn_next_set(a_type, a_field, tail, \ 129*8e33eff8Schristos phn0); \ 130*8e33eff8Schristos tail = phn0; \ 131*8e33eff8Schristos phn0 = phnrest; \ 132*8e33eff8Schristos } else { \ 133*8e33eff8Schristos phn_next_set(a_type, a_field, tail, \ 134*8e33eff8Schristos phn0); \ 135*8e33eff8Schristos tail = phn0; \ 136*8e33eff8Schristos phn0 = NULL; \ 137*8e33eff8Schristos } \ 138*8e33eff8Schristos } \ 139*8e33eff8Schristos phn0 = head; \ 140*8e33eff8Schristos phn1 = phn_next_get(a_type, a_field, phn0); \ 141*8e33eff8Schristos if (phn1 != NULL) { \ 142*8e33eff8Schristos while (true) { \ 143*8e33eff8Schristos head = phn_next_get(a_type, a_field, \ 144*8e33eff8Schristos phn1); \ 145*8e33eff8Schristos assert(phn_prev_get(a_type, a_field, \ 146*8e33eff8Schristos phn0) == NULL); \ 147*8e33eff8Schristos phn_next_set(a_type, a_field, phn0, \ 148*8e33eff8Schristos NULL); \ 149*8e33eff8Schristos assert(phn_prev_get(a_type, a_field, \ 150*8e33eff8Schristos phn1) == NULL); \ 151*8e33eff8Schristos phn_next_set(a_type, a_field, phn1, \ 152*8e33eff8Schristos NULL); \ 153*8e33eff8Schristos phn_merge(a_type, a_field, phn0, phn1, \ 154*8e33eff8Schristos a_cmp, phn0); \ 155*8e33eff8Schristos if (head == NULL) { \ 156*8e33eff8Schristos break; \ 157*8e33eff8Schristos } \ 158*8e33eff8Schristos phn_next_set(a_type, a_field, tail, \ 159*8e33eff8Schristos phn0); \ 160*8e33eff8Schristos tail = phn0; \ 161*8e33eff8Schristos phn0 = head; \ 162*8e33eff8Schristos phn1 = phn_next_get(a_type, a_field, \ 163*8e33eff8Schristos phn0); \ 164*8e33eff8Schristos } \ 165*8e33eff8Schristos } \ 166*8e33eff8Schristos } \ 167*8e33eff8Schristos r_phn = phn0; \ 168*8e33eff8Schristos } while (0) 169*8e33eff8Schristos 170*8e33eff8Schristos #define ph_merge_aux(a_type, a_field, a_ph, a_cmp) do { \ 171*8e33eff8Schristos a_type *_phn = phn_next_get(a_type, a_field, a_ph->ph_root); \ 172*8e33eff8Schristos if (_phn != NULL) { \ 173*8e33eff8Schristos phn_prev_set(a_type, a_field, a_ph->ph_root, NULL); \ 174*8e33eff8Schristos phn_next_set(a_type, a_field, a_ph->ph_root, NULL); \ 175*8e33eff8Schristos phn_prev_set(a_type, a_field, _phn, NULL); \ 176*8e33eff8Schristos ph_merge_siblings(a_type, a_field, _phn, a_cmp, _phn); \ 177*8e33eff8Schristos assert(phn_next_get(a_type, a_field, _phn) == NULL); \ 178*8e33eff8Schristos phn_merge(a_type, a_field, a_ph->ph_root, _phn, a_cmp, \ 179*8e33eff8Schristos a_ph->ph_root); \ 180*8e33eff8Schristos } \ 181*8e33eff8Schristos } while (0) 182*8e33eff8Schristos 183*8e33eff8Schristos #define ph_merge_children(a_type, a_field, a_phn, a_cmp, r_phn) do { \ 184*8e33eff8Schristos a_type *lchild = phn_lchild_get(a_type, a_field, a_phn); \ 185*8e33eff8Schristos if (lchild == NULL) { \ 186*8e33eff8Schristos r_phn = NULL; \ 187*8e33eff8Schristos } else { \ 188*8e33eff8Schristos ph_merge_siblings(a_type, a_field, lchild, a_cmp, \ 189*8e33eff8Schristos r_phn); \ 190*8e33eff8Schristos } \ 191*8e33eff8Schristos } while (0) 192*8e33eff8Schristos 193*8e33eff8Schristos /* 194*8e33eff8Schristos * The ph_proto() macro generates function prototypes that correspond to the 195*8e33eff8Schristos * functions generated by an equivalently parameterized call to ph_gen(). 196*8e33eff8Schristos */ 197*8e33eff8Schristos #define ph_proto(a_attr, a_prefix, a_ph_type, a_type) \ 198*8e33eff8Schristos a_attr void a_prefix##new(a_ph_type *ph); \ 199*8e33eff8Schristos a_attr bool a_prefix##empty(a_ph_type *ph); \ 200*8e33eff8Schristos a_attr a_type *a_prefix##first(a_ph_type *ph); \ 201*8e33eff8Schristos a_attr a_type *a_prefix##any(a_ph_type *ph); \ 202*8e33eff8Schristos a_attr void a_prefix##insert(a_ph_type *ph, a_type *phn); \ 203*8e33eff8Schristos a_attr a_type *a_prefix##remove_first(a_ph_type *ph); \ 204*8e33eff8Schristos a_attr a_type *a_prefix##remove_any(a_ph_type *ph); \ 205*8e33eff8Schristos a_attr void a_prefix##remove(a_ph_type *ph, a_type *phn); 206*8e33eff8Schristos 207*8e33eff8Schristos /* 208*8e33eff8Schristos * The ph_gen() macro generates a type-specific pairing heap implementation, 209*8e33eff8Schristos * based on the above cpp macros. 210*8e33eff8Schristos */ 211*8e33eff8Schristos #define ph_gen(a_attr, a_prefix, a_ph_type, a_type, a_field, a_cmp) \ 212*8e33eff8Schristos a_attr void \ 213*8e33eff8Schristos a_prefix##new(a_ph_type *ph) { \ 214*8e33eff8Schristos memset(ph, 0, sizeof(ph(a_type))); \ 215*8e33eff8Schristos } \ 216*8e33eff8Schristos a_attr bool \ 217*8e33eff8Schristos a_prefix##empty(a_ph_type *ph) { \ 218*8e33eff8Schristos return (ph->ph_root == NULL); \ 219*8e33eff8Schristos } \ 220*8e33eff8Schristos a_attr a_type * \ 221*8e33eff8Schristos a_prefix##first(a_ph_type *ph) { \ 222*8e33eff8Schristos if (ph->ph_root == NULL) { \ 223*8e33eff8Schristos return NULL; \ 224*8e33eff8Schristos } \ 225*8e33eff8Schristos ph_merge_aux(a_type, a_field, ph, a_cmp); \ 226*8e33eff8Schristos return ph->ph_root; \ 227*8e33eff8Schristos } \ 228*8e33eff8Schristos a_attr a_type * \ 229*8e33eff8Schristos a_prefix##any(a_ph_type *ph) { \ 230*8e33eff8Schristos if (ph->ph_root == NULL) { \ 231*8e33eff8Schristos return NULL; \ 232*8e33eff8Schristos } \ 233*8e33eff8Schristos a_type *aux = phn_next_get(a_type, a_field, ph->ph_root); \ 234*8e33eff8Schristos if (aux != NULL) { \ 235*8e33eff8Schristos return aux; \ 236*8e33eff8Schristos } \ 237*8e33eff8Schristos return ph->ph_root; \ 238*8e33eff8Schristos } \ 239*8e33eff8Schristos a_attr void \ 240*8e33eff8Schristos a_prefix##insert(a_ph_type *ph, a_type *phn) { \ 241*8e33eff8Schristos memset(&phn->a_field, 0, sizeof(phn(a_type))); \ 242*8e33eff8Schristos \ 243*8e33eff8Schristos /* \ 244*8e33eff8Schristos * Treat the root as an aux list during insertion, and lazily \ 245*8e33eff8Schristos * merge during a_prefix##remove_first(). For elements that \ 246*8e33eff8Schristos * are inserted, then removed via a_prefix##remove() before the \ 247*8e33eff8Schristos * aux list is ever processed, this makes insert/remove \ 248*8e33eff8Schristos * constant-time, whereas eager merging would make insert \ 249*8e33eff8Schristos * O(log n). \ 250*8e33eff8Schristos */ \ 251*8e33eff8Schristos if (ph->ph_root == NULL) { \ 252*8e33eff8Schristos ph->ph_root = phn; \ 253*8e33eff8Schristos } else { \ 254*8e33eff8Schristos phn_next_set(a_type, a_field, phn, phn_next_get(a_type, \ 255*8e33eff8Schristos a_field, ph->ph_root)); \ 256*8e33eff8Schristos if (phn_next_get(a_type, a_field, ph->ph_root) != \ 257*8e33eff8Schristos NULL) { \ 258*8e33eff8Schristos phn_prev_set(a_type, a_field, \ 259*8e33eff8Schristos phn_next_get(a_type, a_field, ph->ph_root), \ 260*8e33eff8Schristos phn); \ 261*8e33eff8Schristos } \ 262*8e33eff8Schristos phn_prev_set(a_type, a_field, phn, ph->ph_root); \ 263*8e33eff8Schristos phn_next_set(a_type, a_field, ph->ph_root, phn); \ 264*8e33eff8Schristos } \ 265*8e33eff8Schristos } \ 266*8e33eff8Schristos a_attr a_type * \ 267*8e33eff8Schristos a_prefix##remove_first(a_ph_type *ph) { \ 268*8e33eff8Schristos a_type *ret; \ 269*8e33eff8Schristos \ 270*8e33eff8Schristos if (ph->ph_root == NULL) { \ 271*8e33eff8Schristos return NULL; \ 272*8e33eff8Schristos } \ 273*8e33eff8Schristos ph_merge_aux(a_type, a_field, ph, a_cmp); \ 274*8e33eff8Schristos \ 275*8e33eff8Schristos ret = ph->ph_root; \ 276*8e33eff8Schristos \ 277*8e33eff8Schristos ph_merge_children(a_type, a_field, ph->ph_root, a_cmp, \ 278*8e33eff8Schristos ph->ph_root); \ 279*8e33eff8Schristos \ 280*8e33eff8Schristos return ret; \ 281*8e33eff8Schristos } \ 282*8e33eff8Schristos a_attr a_type * \ 283*8e33eff8Schristos a_prefix##remove_any(a_ph_type *ph) { \ 284*8e33eff8Schristos /* \ 285*8e33eff8Schristos * Remove the most recently inserted aux list element, or the \ 286*8e33eff8Schristos * root if the aux list is empty. This has the effect of \ 287*8e33eff8Schristos * behaving as a LIFO (and insertion/removal is therefore \ 288*8e33eff8Schristos * constant-time) if a_prefix##[remove_]first() are never \ 289*8e33eff8Schristos * called. \ 290*8e33eff8Schristos */ \ 291*8e33eff8Schristos if (ph->ph_root == NULL) { \ 292*8e33eff8Schristos return NULL; \ 293*8e33eff8Schristos } \ 294*8e33eff8Schristos a_type *ret = phn_next_get(a_type, a_field, ph->ph_root); \ 295*8e33eff8Schristos if (ret != NULL) { \ 296*8e33eff8Schristos a_type *aux = phn_next_get(a_type, a_field, ret); \ 297*8e33eff8Schristos phn_next_set(a_type, a_field, ph->ph_root, aux); \ 298*8e33eff8Schristos if (aux != NULL) { \ 299*8e33eff8Schristos phn_prev_set(a_type, a_field, aux, \ 300*8e33eff8Schristos ph->ph_root); \ 301*8e33eff8Schristos } \ 302*8e33eff8Schristos return ret; \ 303*8e33eff8Schristos } \ 304*8e33eff8Schristos ret = ph->ph_root; \ 305*8e33eff8Schristos ph_merge_children(a_type, a_field, ph->ph_root, a_cmp, \ 306*8e33eff8Schristos ph->ph_root); \ 307*8e33eff8Schristos return ret; \ 308*8e33eff8Schristos } \ 309*8e33eff8Schristos a_attr void \ 310*8e33eff8Schristos a_prefix##remove(a_ph_type *ph, a_type *phn) { \ 311*8e33eff8Schristos a_type *replace, *parent; \ 312*8e33eff8Schristos \ 313*8e33eff8Schristos if (ph->ph_root == phn) { \ 314*8e33eff8Schristos /* \ 315*8e33eff8Schristos * We can delete from aux list without merging it, but \ 316*8e33eff8Schristos * we need to merge if we are dealing with the root \ 317*8e33eff8Schristos * node and it has children. \ 318*8e33eff8Schristos */ \ 319*8e33eff8Schristos if (phn_lchild_get(a_type, a_field, phn) == NULL) { \ 320*8e33eff8Schristos ph->ph_root = phn_next_get(a_type, a_field, \ 321*8e33eff8Schristos phn); \ 322*8e33eff8Schristos if (ph->ph_root != NULL) { \ 323*8e33eff8Schristos phn_prev_set(a_type, a_field, \ 324*8e33eff8Schristos ph->ph_root, NULL); \ 325*8e33eff8Schristos } \ 326*8e33eff8Schristos return; \ 327*8e33eff8Schristos } \ 328*8e33eff8Schristos ph_merge_aux(a_type, a_field, ph, a_cmp); \ 329*8e33eff8Schristos if (ph->ph_root == phn) { \ 330*8e33eff8Schristos ph_merge_children(a_type, a_field, ph->ph_root, \ 331*8e33eff8Schristos a_cmp, ph->ph_root); \ 332*8e33eff8Schristos return; \ 333*8e33eff8Schristos } \ 334*8e33eff8Schristos } \ 335*8e33eff8Schristos \ 336*8e33eff8Schristos /* Get parent (if phn is leftmost child) before mutating. */ \ 337*8e33eff8Schristos if ((parent = phn_prev_get(a_type, a_field, phn)) != NULL) { \ 338*8e33eff8Schristos if (phn_lchild_get(a_type, a_field, parent) != phn) { \ 339*8e33eff8Schristos parent = NULL; \ 340*8e33eff8Schristos } \ 341*8e33eff8Schristos } \ 342*8e33eff8Schristos /* Find a possible replacement node, and link to parent. */ \ 343*8e33eff8Schristos ph_merge_children(a_type, a_field, phn, a_cmp, replace); \ 344*8e33eff8Schristos /* Set next/prev for sibling linked list. */ \ 345*8e33eff8Schristos if (replace != NULL) { \ 346*8e33eff8Schristos if (parent != NULL) { \ 347*8e33eff8Schristos phn_prev_set(a_type, a_field, replace, parent); \ 348*8e33eff8Schristos phn_lchild_set(a_type, a_field, parent, \ 349*8e33eff8Schristos replace); \ 350*8e33eff8Schristos } else { \ 351*8e33eff8Schristos phn_prev_set(a_type, a_field, replace, \ 352*8e33eff8Schristos phn_prev_get(a_type, a_field, phn)); \ 353*8e33eff8Schristos if (phn_prev_get(a_type, a_field, phn) != \ 354*8e33eff8Schristos NULL) { \ 355*8e33eff8Schristos phn_next_set(a_type, a_field, \ 356*8e33eff8Schristos phn_prev_get(a_type, a_field, phn), \ 357*8e33eff8Schristos replace); \ 358*8e33eff8Schristos } \ 359*8e33eff8Schristos } \ 360*8e33eff8Schristos phn_next_set(a_type, a_field, replace, \ 361*8e33eff8Schristos phn_next_get(a_type, a_field, phn)); \ 362*8e33eff8Schristos if (phn_next_get(a_type, a_field, phn) != NULL) { \ 363*8e33eff8Schristos phn_prev_set(a_type, a_field, \ 364*8e33eff8Schristos phn_next_get(a_type, a_field, phn), \ 365*8e33eff8Schristos replace); \ 366*8e33eff8Schristos } \ 367*8e33eff8Schristos } else { \ 368*8e33eff8Schristos if (parent != NULL) { \ 369*8e33eff8Schristos a_type *next = phn_next_get(a_type, a_field, \ 370*8e33eff8Schristos phn); \ 371*8e33eff8Schristos phn_lchild_set(a_type, a_field, parent, next); \ 372*8e33eff8Schristos if (next != NULL) { \ 373*8e33eff8Schristos phn_prev_set(a_type, a_field, next, \ 374*8e33eff8Schristos parent); \ 375*8e33eff8Schristos } \ 376*8e33eff8Schristos } else { \ 377*8e33eff8Schristos assert(phn_prev_get(a_type, a_field, phn) != \ 378*8e33eff8Schristos NULL); \ 379*8e33eff8Schristos phn_next_set(a_type, a_field, \ 380*8e33eff8Schristos phn_prev_get(a_type, a_field, phn), \ 381*8e33eff8Schristos phn_next_get(a_type, a_field, phn)); \ 382*8e33eff8Schristos } \ 383*8e33eff8Schristos if (phn_next_get(a_type, a_field, phn) != NULL) { \ 384*8e33eff8Schristos phn_prev_set(a_type, a_field, \ 385*8e33eff8Schristos phn_next_get(a_type, a_field, phn), \ 386*8e33eff8Schristos phn_prev_get(a_type, a_field, phn)); \ 387*8e33eff8Schristos } \ 388*8e33eff8Schristos } \ 389*8e33eff8Schristos } 390*8e33eff8Schristos 391*8e33eff8Schristos #endif /* PH_H_ */ 392