mirror of https://github.com/GOSTSec/vanitygen
samr7
12 years ago
2 changed files with 440 additions and 411 deletions
@ -0,0 +1,439 @@
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Vanitygen, vanity bitcoin address generator |
||||
* Copyright (C) 2011 <samr7@cs.washington.edu> |
||||
* |
||||
* Vanitygen is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* any later version. |
||||
* |
||||
* Vanitygen is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with Vanitygen. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#if !defined (__VG_AVL_H__) |
||||
#define __VG_AVL_H__ |
||||
|
||||
#include <assert.h> |
||||
|
||||
/*
|
||||
* AVL tree implementation |
||||
*/ |
||||
|
||||
typedef enum { CENT = 1, LEFT = 0, RIGHT = 2 } avl_balance_t; |
||||
|
||||
typedef struct _avl_item_s { |
||||
struct _avl_item_s *ai_left, *ai_right, *ai_up; |
||||
avl_balance_t ai_balance; |
||||
#ifndef NDEBUG |
||||
int ai_indexed; |
||||
#endif |
||||
} avl_item_t; |
||||
|
||||
typedef struct _avl_root_s { |
||||
avl_item_t *ar_root; |
||||
} avl_root_t; |
||||
|
||||
static INLINE void |
||||
avl_root_init(avl_root_t *rootp) |
||||
{ |
||||
rootp->ar_root = NULL; |
||||
} |
||||
|
||||
static INLINE int |
||||
avl_root_empty(avl_root_t *rootp) |
||||
{ |
||||
return (rootp->ar_root == NULL) ? 1 : 0; |
||||
} |
||||
|
||||
static INLINE void |
||||
avl_item_init(avl_item_t *itemp) |
||||
{ |
||||
itemp->ai_left = NULL; |
||||
itemp->ai_right = NULL; |
||||
itemp->ai_up = NULL; |
||||
itemp->ai_balance = CENT; |
||||
#ifndef NDEBUG |
||||
itemp->ai_indexed = 0; |
||||
#endif |
||||
} |
||||
|
||||
#define container_of(ptr, type, member) \ |
||||
(((type*) (((unsigned char *)ptr) - \ |
||||
(size_t)&(((type *)((unsigned char *)0))->member)))) |
||||
|
||||
#define avl_item_entry(ptr, type, member) \ |
||||
container_of(ptr, type, member) |
||||
|
||||
|
||||
|
||||
static INLINE void |
||||
_avl_rotate_ll(avl_root_t *rootp, avl_item_t *itemp) |
||||
{ |
||||
avl_item_t *tmp; |
||||
tmp = itemp->ai_left; |
||||
itemp->ai_left = tmp->ai_right; |
||||
if (itemp->ai_left) |
||||
itemp->ai_left->ai_up = itemp; |
||||
tmp->ai_right = itemp; |
||||
|
||||
if (itemp->ai_up) { |
||||
if (itemp->ai_up->ai_left == itemp) { |
||||
itemp->ai_up->ai_left = tmp; |
||||
} else { |
||||
assert(itemp->ai_up->ai_right == itemp); |
||||
itemp->ai_up->ai_right = tmp; |
||||
} |
||||
} else { |
||||
rootp->ar_root = tmp; |
||||
} |
||||
tmp->ai_up = itemp->ai_up; |
||||
itemp->ai_up = tmp; |
||||
} |
||||
|
||||
static INLINE void |
||||
_avl_rotate_lr(avl_root_t *rootp, avl_item_t *itemp) |
||||
{ |
||||
avl_item_t *rcp, *rlcp; |
||||
rcp = itemp->ai_left; |
||||
rlcp = rcp->ai_right; |
||||
if (itemp->ai_up) { |
||||
if (itemp == itemp->ai_up->ai_left) { |
||||
itemp->ai_up->ai_left = rlcp; |
||||
} else { |
||||
assert(itemp == itemp->ai_up->ai_right); |
||||
itemp->ai_up->ai_right = rlcp; |
||||
} |
||||
} else { |
||||
rootp->ar_root = rlcp; |
||||
} |
||||
rlcp->ai_up = itemp->ai_up; |
||||
rcp->ai_right = rlcp->ai_left; |
||||
if (rcp->ai_right) |
||||
rcp->ai_right->ai_up = rcp; |
||||
itemp->ai_left = rlcp->ai_right; |
||||
if (itemp->ai_left) |
||||
itemp->ai_left->ai_up = itemp; |
||||
rlcp->ai_left = rcp; |
||||
rlcp->ai_right = itemp; |
||||
rcp->ai_up = rlcp; |
||||
itemp->ai_up = rlcp; |
||||
} |
||||
|
||||
static INLINE void |
||||
_avl_rotate_rr(avl_root_t *rootp, avl_item_t *itemp) |
||||
{ |
||||
avl_item_t *tmp; |
||||
tmp = itemp->ai_right; |
||||
itemp->ai_right = tmp->ai_left; |
||||
if (itemp->ai_right) |
||||
itemp->ai_right->ai_up = itemp; |
||||
tmp->ai_left = itemp; |
||||
|
||||
if (itemp->ai_up) { |
||||
if (itemp->ai_up->ai_right == itemp) { |
||||
itemp->ai_up->ai_right = tmp; |
||||
} else { |
||||
assert(itemp->ai_up->ai_left == itemp); |
||||
itemp->ai_up->ai_left = tmp; |
||||
} |
||||
} else { |
||||
rootp->ar_root = tmp; |
||||
} |
||||
tmp->ai_up = itemp->ai_up; |
||||
itemp->ai_up = tmp; |
||||
} |
||||
|
||||
static INLINE void |
||||
_avl_rotate_rl(avl_root_t *rootp, avl_item_t *itemp) |
||||
{ |
||||
avl_item_t *rcp, *rlcp; |
||||
rcp = itemp->ai_right; |
||||
rlcp = rcp->ai_left; |
||||
if (itemp->ai_up) { |
||||
if (itemp == itemp->ai_up->ai_right) { |
||||
itemp->ai_up->ai_right = rlcp; |
||||
} else { |
||||
assert(itemp == itemp->ai_up->ai_left); |
||||
itemp->ai_up->ai_left = rlcp; |
||||
} |
||||
} else { |
||||
rootp->ar_root = rlcp; |
||||
} |
||||
rlcp->ai_up = itemp->ai_up; |
||||
rcp->ai_left = rlcp->ai_right; |
||||
if (rcp->ai_left) |
||||
rcp->ai_left->ai_up = rcp; |
||||
itemp->ai_right = rlcp->ai_left; |
||||
if (itemp->ai_right) |
||||
itemp->ai_right->ai_up = itemp; |
||||
rlcp->ai_right = rcp; |
||||
rlcp->ai_left = itemp; |
||||
rcp->ai_up = rlcp; |
||||
itemp->ai_up = rlcp; |
||||
} |
||||
|
||||
static void |
||||
avl_delete_fix(avl_root_t *rootp, avl_item_t *itemp, avl_item_t *parentp) |
||||
{ |
||||
avl_item_t *childp; |
||||
|
||||
if ((parentp->ai_left == NULL) && |
||||
(parentp->ai_right == NULL)) { |
||||
assert(itemp == NULL); |
||||
parentp->ai_balance = CENT; |
||||
itemp = parentp; |
||||
parentp = itemp->ai_up; |
||||
} |
||||
|
||||
while (parentp) { |
||||
if (itemp == parentp->ai_right) { |
||||
itemp = parentp->ai_left; |
||||
if (parentp->ai_balance == LEFT) { |
||||
/* Parent was left-heavy, now worse */ |
||||
if (itemp->ai_balance == LEFT) { |
||||
/* If left child is also
|
||||
* left-heavy, LL fixes it. */ |
||||
_avl_rotate_ll(rootp, parentp); |
||||
itemp->ai_balance = CENT; |
||||
parentp->ai_balance = CENT; |
||||
parentp = itemp; |
||||
} else if (itemp->ai_balance == CENT) { |
||||
_avl_rotate_ll(rootp, parentp); |
||||
itemp->ai_balance = RIGHT; |
||||
parentp->ai_balance = LEFT; |
||||
break; |
||||
} else { |
||||
childp = itemp->ai_right; |
||||
_avl_rotate_lr(rootp, parentp); |
||||
itemp->ai_balance = CENT; |
||||
parentp->ai_balance = CENT; |
||||
if (childp->ai_balance == RIGHT) |
||||
itemp->ai_balance = LEFT; |
||||
if (childp->ai_balance == LEFT) |
||||
parentp->ai_balance = RIGHT; |
||||
childp->ai_balance = CENT; |
||||
parentp = childp; |
||||
} |
||||
} else if (parentp->ai_balance == CENT) { |
||||
parentp->ai_balance = LEFT; |
||||
break; |
||||
} else { |
||||
parentp->ai_balance = CENT; |
||||
} |
||||
|
||||
} else { |
||||
itemp = parentp->ai_right; |
||||
if (parentp->ai_balance == RIGHT) { |
||||
if (itemp->ai_balance == RIGHT) { |
||||
_avl_rotate_rr(rootp, parentp); |
||||
itemp->ai_balance = CENT; |
||||
parentp->ai_balance = CENT; |
||||
parentp = itemp; |
||||
} else if (itemp->ai_balance == CENT) { |
||||
_avl_rotate_rr(rootp, parentp); |
||||
itemp->ai_balance = LEFT; |
||||
parentp->ai_balance = RIGHT; |
||||
break; |
||||
} else { |
||||
childp = itemp->ai_left; |
||||
_avl_rotate_rl(rootp, parentp); |
||||
|
||||
itemp->ai_balance = CENT; |
||||
parentp->ai_balance = CENT; |
||||
if (childp->ai_balance == RIGHT) |
||||
parentp->ai_balance = LEFT; |
||||
if (childp->ai_balance == LEFT) |
||||
itemp->ai_balance = RIGHT; |
||||
childp->ai_balance = CENT; |
||||
parentp = childp; |
||||
} |
||||
} else if (parentp->ai_balance == CENT) { |
||||
parentp->ai_balance = RIGHT; |
||||
break; |
||||
} else { |
||||
parentp->ai_balance = CENT; |
||||
} |
||||
} |
||||
|
||||
itemp = parentp; |
||||
parentp = itemp->ai_up; |
||||
} |
||||
} |
||||
|
||||
static void |
||||
avl_insert_fix(avl_root_t *rootp, avl_item_t *itemp) |
||||
{ |
||||
avl_item_t *childp, *parentp = itemp->ai_up; |
||||
itemp->ai_left = itemp->ai_right = NULL; |
||||
#ifndef NDEBUG |
||||
assert(!itemp->ai_indexed); |
||||
itemp->ai_indexed = 1; |
||||
#endif |
||||
while (parentp) { |
||||
if (itemp == parentp->ai_left) { |
||||
if (parentp->ai_balance == LEFT) { |
||||
/* Parent was left-heavy, now worse */ |
||||
if (itemp->ai_balance == LEFT) { |
||||
/* If left child is also
|
||||
* left-heavy, LL fixes it. */ |
||||
_avl_rotate_ll(rootp, parentp); |
||||
itemp->ai_balance = CENT; |
||||
parentp->ai_balance = CENT; |
||||
break; |
||||
} else { |
||||
assert(itemp->ai_balance != CENT); |
||||
childp = itemp->ai_right; |
||||
_avl_rotate_lr(rootp, parentp); |
||||
itemp->ai_balance = CENT; |
||||
parentp->ai_balance = CENT; |
||||
if (childp->ai_balance == RIGHT) |
||||
itemp->ai_balance = LEFT; |
||||
if (childp->ai_balance == LEFT) |
||||
parentp->ai_balance = RIGHT; |
||||
childp->ai_balance = CENT; |
||||
break; |
||||
} |
||||
} else if (parentp->ai_balance == CENT) { |
||||
parentp->ai_balance = LEFT; |
||||
} else { |
||||
parentp->ai_balance = CENT; |
||||
return; |
||||
} |
||||
} else { |
||||
if (parentp->ai_balance == RIGHT) { |
||||
if (itemp->ai_balance == RIGHT) { |
||||
_avl_rotate_rr(rootp, parentp); |
||||
itemp->ai_balance = CENT; |
||||
parentp->ai_balance = CENT; |
||||
break; |
||||
} else { |
||||
assert(itemp->ai_balance != CENT); |
||||
childp = itemp->ai_left; |
||||
_avl_rotate_rl(rootp, parentp); |
||||
itemp->ai_balance = CENT; |
||||
parentp->ai_balance = CENT; |
||||
if (childp->ai_balance == RIGHT) |
||||
parentp->ai_balance = LEFT; |
||||
if (childp->ai_balance == LEFT) |
||||
itemp->ai_balance = RIGHT; |
||||
childp->ai_balance = CENT; |
||||
break; |
||||
} |
||||
} else if (parentp->ai_balance == CENT) { |
||||
parentp->ai_balance = RIGHT; |
||||
} else { |
||||
parentp->ai_balance = CENT; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
itemp = parentp; |
||||
parentp = itemp->ai_up; |
||||
} |
||||
} |
||||
|
||||
static INLINE avl_item_t * |
||||
avl_first(avl_root_t *rootp) |
||||
{ |
||||
avl_item_t *itemp = rootp->ar_root; |
||||
if (itemp) { |
||||
while (itemp->ai_left) |
||||
itemp = itemp->ai_left; |
||||
} |
||||
return itemp; |
||||
} |
||||
|
||||
static INLINE avl_item_t * |
||||
avl_next(avl_item_t *itemp) |
||||
{ |
||||
if (itemp->ai_right) { |
||||
itemp = itemp->ai_right; |
||||
while (itemp->ai_left) |
||||
itemp = itemp->ai_left; |
||||
return itemp; |
||||
} |
||||
|
||||
while (itemp->ai_up && (itemp == itemp->ai_up->ai_right)) |
||||
itemp = itemp->ai_up; |
||||
|
||||
if (!itemp->ai_up) |
||||
return NULL; |
||||
|
||||
return itemp->ai_up; |
||||
} |
||||
|
||||
static void |
||||
avl_remove(avl_root_t *rootp, avl_item_t *itemp) |
||||
{ |
||||
avl_item_t *relocp, *replacep, *parentp = NULL; |
||||
#ifndef NDEBUG |
||||
assert(itemp->ai_indexed); |
||||
itemp->ai_indexed = 0; |
||||
#endif |
||||
/* If the item is directly replaceable, do it. */ |
||||
if ((itemp->ai_left == NULL) || (itemp->ai_right == NULL)) { |
||||
parentp = itemp->ai_up; |
||||
replacep = itemp->ai_left; |
||||
if (replacep == NULL) |
||||
replacep = itemp->ai_right; |
||||
if (replacep != NULL) |
||||
replacep->ai_up = parentp; |
||||
if (parentp == NULL) { |
||||
rootp->ar_root = replacep; |
||||
} else { |
||||
if (itemp == parentp->ai_left) |
||||
parentp->ai_left = replacep; |
||||
else |
||||
parentp->ai_right = replacep; |
||||
|
||||
avl_delete_fix(rootp, replacep, parentp); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
/*
|
||||
* Otherwise we do an indirect replacement with |
||||
* the item's leftmost right descendant. |
||||
*/ |
||||
relocp = avl_next(itemp); |
||||
assert(relocp); |
||||
assert(relocp->ai_up != NULL); |
||||
assert(relocp->ai_left == NULL); |
||||
replacep = relocp->ai_right; |
||||
relocp->ai_left = itemp->ai_left; |
||||
if (relocp->ai_left != NULL) |
||||
relocp->ai_left->ai_up = relocp; |
||||
if (itemp->ai_up == NULL) |
||||
rootp->ar_root = relocp; |
||||
else { |
||||
if (itemp == itemp->ai_up->ai_left) |
||||
itemp->ai_up->ai_left = relocp; |
||||
else |
||||
itemp->ai_up->ai_right = relocp; |
||||
} |
||||
if (relocp == relocp->ai_up->ai_left) { |
||||
assert(relocp->ai_up != itemp); |
||||
relocp->ai_up->ai_left = replacep; |
||||
parentp = relocp->ai_up; |
||||
if (replacep != NULL) |
||||
replacep->ai_up = relocp->ai_up; |
||||
relocp->ai_right = itemp->ai_right; |
||||
} else { |
||||
assert(relocp->ai_up == itemp); |
||||
relocp->ai_right = replacep; |
||||
parentp = relocp; |
||||
} |
||||
if (relocp->ai_right != NULL) |
||||
relocp->ai_right->ai_up = relocp; |
||||
relocp->ai_up = itemp->ai_up; |
||||
relocp->ai_balance = itemp->ai_balance; |
||||
avl_delete_fix(rootp, replacep, parentp); |
||||
} |
||||
|
||||
#endif /* !defined (__VG_AVL_H__) */ |
Loading…
Reference in new issue