diff --git a/cscoin-heap64.c b/cscoin-heap64.c new file mode 100644 index 0000000..76d8c7e --- /dev/null +++ b/cscoin-heap64.c @@ -0,0 +1,86 @@ +#include "cscoin-heap64.h" + +CSCoinHeap64 * +cscoin_heap64_new (guint64 *heap, gsize heap_len, GCompareFunc cmp) +{ + CSCoinHeap64 *self; + + self = g_malloc (sizeof (CSCoinHeap64)); + + cscoin_heap64_init (self, heap, heap_len, cmp); + + return self; +} + +void +cscoin_heap64_init (CSCoinHeap64 *self, guint64 *heap, gsize heap_len, GCompareFunc cmp) +{ + g_return_if_fail (self != NULL); + + self->heap = heap; + self->heap_len = heap_len; + self->cmp = cmp; + + gint i; + for (i = 0; i < self->heap_len; i++) + { + self->heap[i] = CSCOIN_HEAP64_NULL; + } +} + +gboolean +cscoin_heap64_push (CSCoinHeap64 *self, guint64 val) +{ + gint i; + guint64 tmp; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (val != CSCOIN_HEAP64_NULL, FALSE); + + i = 0; + while (self->heap[i++] != CSCOIN_HEAP64_NULL); + + self->heap[i - 1] = val; + + /* heapify */ + while (i > 1) + { + /* swap parent & child */ + if (self->cmp (self->heap + ((i - 1) / 2), self->heap + i) < 0) + { + tmp = self->heap[(i - 1) / 2]; + self->heap[(i - 1) / 2] = tmp; + self->heap[i] = tmp; + } + i--; + } + + return TRUE; +} + +guint64 +cscoin_heap64_pop (CSCoinHeap64 *self) +{ + gint i; + guint64 ret; + + ret = self->heap[0]; + + for (i = 0; i < self->heap_len && self->heap[i] != CSCOIN_HEAP64_NULL;) + { + if (self->cmp (self->heap + 2 * i + 1, self->heap + 2 * i + 2) < 0) + { + // raise left + self->heap[i] = self->heap[2 * i + 1]; + i = (2 * i) + 1; + } + else + { + // raise right + self->heap[i] = self->heap[2 * i + 2]; + i = (2 * i) + 2; + } + } + + return ret; +} diff --git a/cscoin-heap64.h b/cscoin-heap64.h new file mode 100644 index 0000000..960bdd3 --- /dev/null +++ b/cscoin-heap64.h @@ -0,0 +1,31 @@ +#ifndef __CSCOIN_HEAP64_H__ +#define __CSCOIN_HEAP64_H__ + +#include + +/* random sentinel (don't use this value explicitly) */ +#define CSCOIN_HEAP64_NULL G_GUINT64_CONSTANT (12839182022384) + +typedef struct _CSCoinHeap64 CSCoinHeap64; + +struct _CSCoinHeap64 +{ + guint64 *heap; + gsize heap_len; + GCompareFunc cmp; +}; + +CSCoinHeap64 * cscoin_heap64_new (guint64 *heap, + gsize heap_len, + GCompareFunc cmp); +void cscoin_heap64_free (CSCoinHeap64 *self); +void cscoin_heap64_init (CSCoinHeap64 *self, + guint64 *heap, + gsize heap_len, + GCompareFunc cmp); +gboolean cscoin_heap64_push (CSCoinHeap64 *self, guint64 val); +guint64 cscoin_heap64_pop (CSCoinHeap64 *self); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (CSCoinHeap64, cscoin_heap64_free); + +#endif /* __CSCOIN_HEAP64_H__ */ diff --git a/cscoin-solver.c b/cscoin-solver.c index 9829e66..c7ffe75 100644 --- a/cscoin-solver.c +++ b/cscoin-solver.c @@ -1,5 +1,6 @@ #include "cscoin-solver.h" #include "cscoin-mt64.h" +#include "cscoin-heap64.h" #include #include @@ -63,11 +64,13 @@ cscoin_solve_challenge (gint challenge_id, guint16 prefix; } checksum_digest; guint64 numbers[nb_elements]; + CSCoinHeap64 numbers_heap; guint nonce; gchar nonce_str[32]; gint i; cscoin_mt64_init (&mt64); + cscoin_heap64_init (&numbers_heap, numbers, nb_elements, guint64cmp_asc); /* OpenMP partitionning */ guint nonce_from, nonce_to; @@ -93,7 +96,7 @@ cscoin_solve_challenge (gint challenge_id, for (i = 0; i < nb_elements; i++) { - numbers[i] = cscoin_mt64_next_uint64 (&mt64); + cscoin_heap64_push (&numbers_heap, cscoin_mt64_next_uint64 (&mt64)); } switch (challenge_type) @@ -108,10 +111,11 @@ cscoin_solve_challenge (gint challenge_id, SHA256_Init (&checksum); + guint64 number; gchar number_str[32]; - for (i = 0; i < nb_elements; i++) + while ((number = cscoin_heap64_pop (&numbers_heap)) != CSCOIN_HEAP64_NULL) { - g_snprintf (number_str, 32, "%lu", numbers[i]); + g_snprintf (number_str, 32, "%lu", number); SHA256_Update (&checksum, number_str, strlen (number_str)); } diff --git a/meson.build b/meson.build index 1d1af1b..ba5cbc7 100644 --- a/meson.build +++ b/meson.build @@ -12,7 +12,7 @@ soup = dependency('libsoup-2.4') json_glib = dependency('json-glib-1.0') openssl = dependency('openssl') -solver_lib = library('cscoin-solver', 'cscoin-solver.c', 'cscoin-mt64.c', +solver_lib = library('cscoin-solver', 'cscoin-solver.c', 'cscoin-mt64.c', 'cscoin-heap64.c', dependencies: [glib, gio, gomp, openssl]) executable('cscoin-miner', 'cscoin-miner.vala', diff --git a/tests/heap64-test.vala b/tests/heap64-test.vala new file mode 100644 index 0000000..e69de29