Perform a random walk starting in the current position of the iterator. * Return 0 if the tree is empty or on out of memory. Otherwise 1 is returned * and the iterator is set to the node reached after doing a random walk * of 'steps' steps. If the 'steps' argument is 0, the random walk is performed * using a random number of steps between 1 and two times the logarithm of * the number of eleme
| 2150 | * tree certain keys will be reported much more often than others. At least |
| 2151 | * this function should be able to expore every possible element eventually. */ |
| 2152 | int raxRandomWalk(raxIterator *it, size_t steps) { |
| 2153 | if (it->rt->numele == 0) { |
| 2154 | it->flags |= RAX_ITER_EOF; |
| 2155 | return 0; |
| 2156 | } |
| 2157 | |
| 2158 | if (steps == 0) { |
| 2159 | size_t fle = 1+floor(log(it->rt->numele)); |
| 2160 | fle *= 2; |
| 2161 | steps = 1 + rand() % fle; |
| 2162 | } |
| 2163 | |
| 2164 | raxNode *n = it->node; |
| 2165 | int inline_leaf = raxIteratorIsInlineLeaf(it); |
| 2166 | int node_child = it->node_child; |
| 2167 | while(steps > 0 || !(inline_leaf || n->iskey)) { |
| 2168 | if (inline_leaf) { |
| 2169 | inline_leaf = 0; |
| 2170 | int todel = n->iscompr ? n->size : 1; |
| 2171 | raxIteratorDelChars(it,todel); |
| 2172 | if (n->iskey) steps--; |
| 2173 | continue; |
| 2174 | } |
| 2175 | |
| 2176 | int numchildren = n->iscompr ? 1 : n->size; |
| 2177 | int r = rand() % (numchildren+(n != it->rt->head)); |
| 2178 | |
| 2179 | if (r == numchildren) { |
| 2180 | /* Go up to parent. */ |
| 2181 | n = raxStackPop(&it->stack); |
| 2182 | node_child = -1; |
| 2183 | int todel = n->iscompr ? n->size : 1; |
| 2184 | raxIteratorDelChars(it,todel); |
| 2185 | } else { |
| 2186 | /* Select a random child. */ |
| 2187 | raxNode **cp = raxNodeFirstChildPtr(n)+r; |
| 2188 | int cidx = n->iscompr ? 0 : r; |
| 2189 | if (n->iscompr) { |
| 2190 | if (!raxIteratorAddChars(it,n->data,n->size)) return 0; |
| 2191 | } else { |
| 2192 | if (!raxIteratorAddChars(it,n->data+r,1)) return 0; |
| 2193 | } |
| 2194 | if (raxIsInlineLeaf(n,cidx)) { |
| 2195 | memcpy(&it->data,cp,sizeof(it->data)); |
| 2196 | inline_leaf = 1; |
| 2197 | node_child = cidx; |
| 2198 | } else { |
| 2199 | if (!raxStackPush(&it->stack,n)) return 0; |
| 2200 | memcpy(&n,cp,sizeof(n)); |
| 2201 | node_child = cidx; |
| 2202 | } |
| 2203 | } |
| 2204 | if (inline_leaf || n->iskey) steps--; |
| 2205 | } |
| 2206 | it->node = n; |
| 2207 | it->node_child = node_child; |
| 2208 | if (inline_leaf) { |
| 2209 | it->flags |= RAX_ITER_INLINE_LEAF; |
nothing calls this directly
no test coverage detected