1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
//------------------------------------------------------------------------------
// GB_binary_search.h: binary search in a sorted list
//------------------------------------------------------------------------------
// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//------------------------------------------------------------------------------
#ifndef GB_BINARY_SEARCH_H
#define GB_BINARY_SEARCH_H
//------------------------------------------------------------------------------
// GB_TRIM_BINARY_SEARCH: simple binary search
//------------------------------------------------------------------------------
// search for integer i in the list X [pleft...pright]; no zombies.
// The list X [pleft ... pright] is in ascending order. It may have
// duplicates.
#define GB_TRIM_BINARY_SEARCH(i,X,pleft,pright) \
{ \
/* binary search of X [pleft ... pright] for integer i */ \
while (pleft < pright) \
{ \
int64_t pmiddle = (pleft + pright) / 2 ; \
if (X [pmiddle] < i) \
{ \
/* if in the list, it appears in [pmiddle+1..pright] */ \
pleft = pmiddle + 1 ; \
} \
else \
{ \
/* if in the list, it appears in [pleft..pmiddle] */ \
pright = pmiddle ; \
} \
} \
/* binary search is narrowed down to a single item */ \
/* or it has found the list is empty */ \
ASSERT (pleft == pright || pleft == pright + 1) ; \
}
//------------------------------------------------------------------------------
// GB_BINARY_SEARCH: binary search and check if found
//------------------------------------------------------------------------------
// If found is true then X [pleft == pright] == i. If duplicates appear then
// X [pleft] is any one of the entries with value i in the list.
// If found is false then
// X [original_pleft ... pleft-1] < i and
// X [pleft+1 ... original_pright] > i holds.
// The value X [pleft] may be either < or > i.
#define GB_BINARY_SEARCH(i,X,pleft,pright,found) \
{ \
GB_TRIM_BINARY_SEARCH (i, X, pleft, pright) ; \
found = (pleft == pright && X [pleft] == i) ; \
}
//------------------------------------------------------------------------------
// GB_SPLIT_BINARY_SEARCH: binary search, and then partition the list
//------------------------------------------------------------------------------
// If found is true then X [pleft] == i. If duplicates appear then X [pleft]
// is any one of the entries with value i in the list.
// If found is false then
// X [original_pleft ... pleft-1] < i and
// X [pleft ... original_pright] > i holds, and pleft-1 == pright
// If X has no duplicates, then whether or not i is found,
// X [original_pleft ... pleft-1] < i and
// X [pleft ... original_pright] >= i holds.
#define GB_SPLIT_BINARY_SEARCH(i,X,pleft,pright,found) \
{ \
GB_BINARY_SEARCH (i, X, pleft, pright, found) \
if (!found && (pleft == pright)) \
{ \
if (i > X [pleft]) \
{ \
pleft++ ; \
} \
else \
{ \
pright++ ; \
} \
} \
}
//------------------------------------------------------------------------------
// GB_TRIM_BINARY_SEARCH_ZOMBIE: binary search in the presence of zombies
//------------------------------------------------------------------------------
#define GB_TRIM_BINARY_SEARCH_ZOMBIE(i,X,pleft,pright) \
{ \
/* binary search of X [pleft ... pright] for integer i */ \
while (pleft < pright) \
{ \
int64_t pmiddle = (pleft + pright) / 2 ; \
if (i > GB_UNFLIP (X [pmiddle])) \
{ \
/* if in the list, it appears in [pmiddle+1..pright] */ \
pleft = pmiddle + 1 ; \
} \
else \
{ \
/* if in the list, it appears in [pleft..pmiddle] */ \
pright = pmiddle ; \
} \
} \
/* binary search is narrowed down to a single item */ \
/* or it has found the list is empty */ \
ASSERT (pleft == pright || pleft == pright + 1) ; \
}
//------------------------------------------------------------------------------
// GB_BINARY_SEARCH_ZOMBIE: binary search with zombies; check if found
//------------------------------------------------------------------------------
#define GB_BINARY_SEARCH_ZOMBIE(i,X,pleft,pright,found,nzombies,is_zombie) \
{ \
if (nzombies > 0) \
{ \
GB_TRIM_BINARY_SEARCH_ZOMBIE (i, X, pleft, pright) ; \
found = false ; \
is_zombie = false ; \
if (pleft == pright) \
{ \
int64_t i2 = X [pleft] ; \
is_zombie = GB_IS_ZOMBIE (i2) ; \
if (is_zombie) \
{ \
i2 = GB_FLIP (i2) ; \
} \
found = (i == i2) ; \
} \
} \
else \
{ \
is_zombie = false ; \
GB_BINARY_SEARCH(i,X,pleft,pright,found) \
} \
}
//------------------------------------------------------------------------------
// GB_SPLIT_BINARY_SEARCH_ZOMBIE: binary search with zombies; then partition
//------------------------------------------------------------------------------
#define GB_SPLIT_BINARY_SEARCH_ZOMBIE(i,X,pleft,pright,found,nzom,is_zombie) \
{ \
if (nzom > 0) \
{ \
GB_TRIM_BINARY_SEARCH_ZOMBIE (i, X, pleft, pright) ; \
found = false ; \
is_zombie = false ; \
if (pleft == pright) \
{ \
int64_t i2 = X [pleft] ; \
is_zombie = GB_IS_ZOMBIE (i2) ; \
if (is_zombie) \
{ \
i2 = GB_FLIP (i2) ; \
} \
found = (i == i2) ; \
if (!found) \
{ \
if (i > i2) \
{ \
pleft++ ; \
} \
else \
{ \
pright++ ; \
} \
} \
} \
} \
else \
{ \
is_zombie = false ; \
GB_SPLIT_BINARY_SEARCH(i,X,pleft,pright,found) \
} \
}
#endif
|