GOSTCoin addresses vainer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

440 lines
10 KiB

/*
* 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__) */