Revision d12d603036b334b53d6e886cfa985a082e981860 authored by Emmanuel Thomé on 29 January 2021, 06:20:31 UTC, committed by Emmanuel Thomé on 29 January 2021, 21:39:17 UTC
1 parent 590bfe4
ropt_tree.c
/**
* @file ropt_tree.c
* Liftings and priority queue structs.
*/
#include "cado.h" // IWYU pragma: keep
#include <float.h> // FLT_MAX DBL_MAX
#include <stdio.h> // fprintf stderr
#include <stdlib.h> // free malloc
#include <stdint.h> /* AIX wants it first (it's a bug) */
#include <gmp.h>
#include "ropt_tree.h"
#if 0 /* Leave them for debug */
/**
* Print the info for the node
*/
static inline void
print_node ( node *pnode )
{
fprintf(stderr, "(%u,%u):%u:%d:(%.2f)\n",
pnode->u, pnode->v, pnode->nr, pnode->e, pnode->val);
/* int i; */
/* for (i = 0; i < pnode->nr; i++) */
/* printf ("pnode->r[%d]: %lu\n", i, pnode->r[i]); */
}
/**
* Print a tree, non-recursive. Two styles.
* - If level == 0, print the whole tree;
* - If level == i, print nodes at height i.
*/
static inline void
print_tree ( node *root,
int level )
{
if (level < 0) {
fprintf(stderr,"Error: level >= 0. \n");
exit(1);
}
int i, currlevel = 0;
node *ptr = root;
printf ("\n");
if (!ptr) /* if empty */
return;
/* find leftmost */
while (ptr->firstchild) {
ptr = ptr->firstchild;
++ currlevel;
}
while (ptr) {
if (level != 0) {
if (currlevel == level) {
for (i = 0; i < currlevel; ++i)
printf("- ");
print_node(ptr);
}
}
else {
for (i = 0; i < currlevel; ++i)
printf("- ");
print_node(ptr);
}
if (ptr->nextsibling) {
ptr = ptr->nextsibling;
//++ level; // aligned layout, uncommont for sloped layout
while (ptr->firstchild) {
ptr = ptr->firstchild;
++ currlevel;
}
}
else {
ptr = ptr->parent; /* move up */
-- currlevel;
}
}
printf ("\n");
return;
}
#endif
/**
* Malloc or realloc (double) the memory space of pnode->r[]
* and pnode->roottype[].
*/
void
alloc_r_node ( node *pnode )
{
//assert (pnode->alloc <= pnode->nr);
if (pnode->nr == 0) {
pnode->r = (unsigned int *)
malloc ( sizeof (unsigned int) );
pnode->roottype = (char *)
malloc ( sizeof (char) );
pnode->alloc = 1;
}
else {
pnode->r = (unsigned int *)
realloc ( pnode->r, 2 * pnode->nr * sizeof (unsigned int) );
pnode->roottype = (char *)
realloc ( pnode->roottype, 2 * pnode->nr * sizeof (char) );
pnode->alloc = (pnode->alloc * 2);
}
if (pnode->r == NULL) {
fprintf (stderr, "Error, cannot reallocate memory in alloc_r_node().\n");
exit (1);
}
}
/**
* Some indices, note the queue is shifted by 1.
*/
static inline int
pq_parent ( int i )
{
return (i>>1);
}
/**
* Initialise an empty tree.
*/
void
new_tree ( node **root )
{
*root = NULL;
}
/**
* Create new empty node.
*/
node *
new_node ( void )
{
node *pnode;
pnode = (node *) malloc(sizeof(node));
if (pnode == NULL) {
fprintf(stderr,"Error: malloc failed in new_node()\n");
exit(1);
}
pnode->firstchild = pnode->nextsibling = pnode->parent = NULL;
pnode->r = NULL;
pnode->roottype = NULL;
pnode->u = pnode->v = pnode->nr = pnode->e = 0;
pnode->val = 0.0;
return pnode;
}
/**
* Insert child node to the current node, where *parent is
* the ptr to the parent of the current node.
*
* - If (u, v) exits in any childrent of the parent;
* -- Check if r exists;
* --- If not, add r and/or "is_multiple=k".
* - If (u, v) doesnot exit;
* -- Add a node with (u, v, r, curr_e, val) and/or "is_multiple=k".
*/
#define DEBUG_INSERT_NODE 0
void
insert_node ( node *parent,
node **currnode,
unsigned int u,
unsigned int v,
unsigned int r,
char curr_e,
unsigned int p,
unsigned int pe,
char k )
{
unsigned int i;
node *lastnode = NULL;
node *nextnode = NULL;
nextnode = parent->firstchild;
lastnode = nextnode;
/* add r to some existing node (u, v) */
while ((nextnode != NULL)) {
if ((nextnode->u == u) && (nextnode->v == v)) {
/* if (u,v) pair exists, see whether
the root r already exists in the node. */
for (i = 0; i < nextnode->nr; i ++) {
if ( nextnode->r[i] == r )
return;
}
/* otherwise, insert this root */
if (nextnode->alloc <= nextnode->nr)
alloc_r_node (nextnode);
nextnode->roottype[nextnode->nr] = k;
nextnode->r[nextnode->nr] = r;
nextnode->nr += 1;
if (k == 2)
nextnode->val += 1.0 / (double) pe;
else {
if (curr_e == 1)
nextnode->val += 1.0 / ((double)p - 1.0);
}
#if DEBUG_INSERT_NODE
fprintf ( stderr, "add to (u: %u, v: %u), nr: %u, "
"r: %u, e: %d, val: %f\n",
u, v, nextnode->nr, nextnode->r[nextnode->nr-1],
curr_e, nextnode->val );
#endif
break;
}
lastnode = nextnode;
nextnode = nextnode->nextsibling;
}
/* add new (u, v) node */
if (nextnode == NULL) {
*currnode = new_node();
/* has left sibling? */
if (lastnode != NULL)
lastnode->nextsibling = (*currnode);
else
parent->firstchild = (*currnode);
(*currnode)->parent = parent;
(*currnode)->u = u;
(*currnode)->v = v;
alloc_r_node (*currnode);
(*currnode)->r[0] = r;
(*currnode)->roottype[0] = k;
(*currnode)->nr += 1;
(*currnode)->e = curr_e;
/* such (u, v) is new, hence we inheritate the val from its parent. */
if (k == 2)
(*currnode)->val += 1.0 / (double) pe + (*currnode)->parent->val;
else {
if (curr_e == 1)
(*currnode)->val += 1.0 / ((double)p - 1.0);
else
(*currnode)->val = (*currnode)->parent->val;
}
#if DEBUG_INSERT_NODE
fprintf ( stderr, "creating (u: %u, v: %u), nr: %u, "
"r: %u, e: %d, val: %f\n", u, v,
(*currnode)->nr, (*currnode)->r[0], curr_e,
(*currnode)->val );
#endif
}
// print_tree(parent, 0);
}
/**
* Free current node ptr.
*/
void
free_node ( node **ptr )
{
if (*ptr) {
if ((*ptr)->r)
free ((*ptr)->r);
if ((*ptr)->roottype)
free ((*ptr)->roottype);
(*ptr)->parent = (*ptr)->firstchild =
(*ptr)->nextsibling = NULL;
free (*ptr);
}
}
/**
* Create priority queue for best sublattices of length len.
*/
void
new_sublattice_pq ( sublattice_pq **ppqueue,
unsigned long len )
{
if ( len < 2 ) {
fprintf(stderr,"Error: len < 2 in new_sublattice_pq()\n");
exit(1);
}
(*ppqueue) = (sublattice_pq *) malloc (sizeof (sublattice_pq));
if ( (*ppqueue) == NULL) {
fprintf(stderr,"Error: malloc failed in new_sublattice_pq()\n");
exit(1);
}
(*ppqueue)->len = len;
(*ppqueue)->u = (mpz_t *) malloc (len* sizeof (mpz_t));
(*ppqueue)->v = (mpz_t *) malloc (len* sizeof (mpz_t));
(*ppqueue)->val = (float *) malloc (len* sizeof (float));
(*ppqueue)->modulus = (mpz_t *) malloc (len* sizeof (mpz_t));
if ( (*ppqueue)->u == NULL || (*ppqueue)->v == NULL ||
(*ppqueue)->v == NULL || (*ppqueue)->val == NULL ) {
fprintf(stderr,"Error: malloc failed in new_sublattice_pq()\n");
exit(1);
}
int i;
for (i = 0; i < (*ppqueue)->len; i++) {
mpz_init ( (*ppqueue)->u[i] );
mpz_init ( (*ppqueue)->v[i] );
mpz_init ( (*ppqueue)->modulus[i] );
}
mpz_set_ui ( (*ppqueue)->u[0], 0 );
mpz_set_ui ( (*ppqueue)->v[0], 0 );
mpz_set_ui ( (*ppqueue)->modulus[0], 0 );
(*ppqueue)->val[0] = -FLT_MAX;
(*ppqueue)->used = 1; // u[0] and v[0] are null elements
}
/**
* Create priority queue for best sublattices of length len.
*/
void
free_sublattice_pq ( sublattice_pq **ppqueue )
{
int i;
for (i = 0; i < (*ppqueue)->len; i++)
{
mpz_clear ( (*ppqueue)->u[i] );
mpz_clear ( (*ppqueue)->v[i] );
mpz_clear ( (*ppqueue)->modulus[i] );
}
free ( (*ppqueue)->val );
free ( (*ppqueue)->u );
free ( (*ppqueue)->v );
free ( (*ppqueue)->modulus );
free ( *ppqueue );
}
/**
* Sift-up to add, if the queue is not full.
*/
static inline void
insert_sublattice_pq_up ( sublattice_pq *pqueue,
mpz_t u,
mpz_t v,
mpz_t mod,
float val )
{
int i;
for ( i = pqueue->used;
val < pqueue->val[pq_parent(i)];
i /= 2 ) {
mpz_set ( pqueue->u[i], pqueue->u[pq_parent(i)] );
mpz_set ( pqueue->v[i], pqueue->v[pq_parent(i)] );
mpz_set ( pqueue->modulus[i], pqueue->modulus[pq_parent(i)] );
pqueue->val[i] = pqueue->val[pq_parent(i)];
}
mpz_set (pqueue->u[i], u);
mpz_set (pqueue->v[i], v);
mpz_set (pqueue->modulus[i], mod);
pqueue->val[i] = val;
pqueue->used ++;
}
/**
* Sift-down, if the heap is full.
*/
static inline void
insert_sublattice_pq_down ( sublattice_pq *pqueue,
mpz_t u,
mpz_t v,
mpz_t mod,
float val )
{
int i, l;
for (i = 1; i*2 < pqueue->used; i = l) {
l = (i << 1);
/* right > left ? */
if ( (l+1) < pqueue->used &&
pqueue->val[l+1] <= pqueue->val[l] )
l ++;
/* switch larger child with parent */
if ( (pqueue->val[l] < val) ||
(pqueue->val[l] == val && mpz_cmp (pqueue->u[l], u) > 0) ) {
mpz_set (pqueue->u[i], pqueue->u[l]);
mpz_set (pqueue->v[i], pqueue->v[l]);
mpz_set (pqueue->modulus[i], pqueue->modulus[l]);
pqueue->val[i] = pqueue->val[l];
}
else
break;
}
mpz_set (pqueue->u[i], u);
mpz_set (pqueue->v[i], v);
mpz_set (pqueue->modulus[i], mod);
pqueue->val[i] = val;
}
/**
* Insert to the priority queue.
*/
void
insert_sublattice_pq ( sublattice_pq *pqueue,
mpz_t u,
mpz_t v,
mpz_t mod,
float val )
{
/*
gmp_fprintf (stderr, "# Debug: inserting (%Zd, %Zd), val: %.2f, "
"used: %d, len: %d\n", u, v, val,
pqueue->used, pqueue->len);
*/
/* queue is full, */
if (pqueue->len == pqueue->used) {
if ( val >= pqueue->val[1] ) {
insert_sublattice_pq_down (pqueue, u, v, mod, val);
}
}
/* queue is not full, sift-up */
else if (pqueue->len > pqueue->used) {
insert_sublattice_pq_up (pqueue, u, v, mod, val);
}
else {
fprintf(stderr,"Error: error (pqueue->len < pqueue->used) "
"in insert_sublattice_pq()\n");
exit(1);
}
}
/**
* Create priority queue for sublattices over a single p^e.
*/
void
new_single_sublattice_pq ( single_sublattice_pq **ppqueue,
unsigned long len )
{
if ( len < 1 ) {
fprintf(stderr,"Error: len < 1 in new_single_sublattice_pq()\n");
exit(1);
}
(*ppqueue) = (single_sublattice_pq *) malloc (
sizeof(single_sublattice_pq) );
if ( (*ppqueue) == NULL) {
fprintf(stderr,"Error: malloc failed in new_single_sublattice_pq()\n");
exit(1);
}
(*ppqueue)->len = len;
(*ppqueue)->u = (unsigned int *) malloc (len * sizeof (unsigned int));
(*ppqueue)->v = (unsigned int *) malloc (len * sizeof (unsigned int));
(*ppqueue)->e = (char *) malloc (len * sizeof (char));
(*ppqueue)->val = (float *) malloc (len * sizeof (float));
if ( (*ppqueue)->u == NULL ||
(*ppqueue)->v == NULL ||
(*ppqueue)->e == NULL ||
(*ppqueue)->val == NULL ) {
fprintf(stderr,"Error: malloc failed in new_single_sublattice_pq()\n");
exit(1);
}
/* u[0] and v[0] are null elements */
(*ppqueue)->u[0] = 0;
(*ppqueue)->v[0] = 0;
(*ppqueue)->e[0] = 0;
(*ppqueue)->val[0] = -FLT_MAX;
(*ppqueue)->used = 1;
}
/**
* Free
*/
void
free_single_sublattice_pq ( single_sublattice_pq **ppqueue )
{
free ( (*ppqueue)->u );
free ( (*ppqueue)->v );
free ( (*ppqueue)->e );
free ( (*ppqueue)->val );
free ( *ppqueue );
}
/**
* Sift-up to add, if the queue is not full.
*/
static inline void
insert_single_sublattice_pq_up ( single_sublattice_pq *pqueue,
unsigned int u,
unsigned int v,
float val,
char e )
{
int k;
for ( k = pqueue->used;
val < pqueue->val[pq_parent(k)];
k /= 2 )
{
pqueue->u[k] = pqueue->u[pq_parent(k)];
pqueue->v[k] = pqueue->v[pq_parent(k)];
pqueue->e[k] = pqueue->e[pq_parent(k)];
pqueue->val[k] = pqueue->val[pq_parent(k)];
}
pqueue->u[k] = u;
pqueue->v[k] = v;
pqueue->e[k] = e;
pqueue->val[k] = val;
pqueue->used ++;
}
/**
* Sift-down, if the heap is full.
*/
static inline void
insert_single_sublattice_pq_down ( single_sublattice_pq *pqueue,
unsigned int u,
unsigned int v,
float val,
char e )
{
int k, l;
for (k = 1; k*2 < pqueue->used; k = l) {
l = (k << 1);
/* right < left ? */
if ( (l+1) < pqueue->used &&
(pqueue->val[l+1] < pqueue->val[l]) )
l ++;
/* switch smaller child with parent */
if ( pqueue->val[l] < val ) {
pqueue->u[k] = pqueue->u[l];
pqueue->v[k] = pqueue->v[l];
pqueue->e[k] = pqueue->e[l];
pqueue->val[k] = pqueue->val[l];
}
else
break;
}
pqueue->u[k] = u;
pqueue->v[k] = v;
pqueue->e[k] = e;
pqueue->val[k] = val;
}
/**
* Insert to the priority queue.
*/
void
insert_single_sublattice_pq ( single_sublattice_pq *pqueue,
unsigned int u,
unsigned int v,
float val,
char e )
{
/* queue is full, */
if (pqueue->len == pqueue->used) {
if ( val > pqueue->val[1] ) {
insert_single_sublattice_pq_down (pqueue, u, v, val, e);
}
}
/* queue is not full, sift-up */
else if (pqueue->len > pqueue->used) {
insert_single_sublattice_pq_up (pqueue, u, v, val, e);
}
else {
fprintf (stderr, "Error: error (pqueue->len < pqueue->used) "
"in insert_single_sublattice_pq()\n");
exit(1);
}
}
/**
* Extract the max of the priority queue.
*/
void
extract_single_sublattice_pq ( single_sublattice_pq *pqueue,
unsigned int *u,
unsigned int *v,
float *val,
char *e )
{
/* don't extract u[0] since it is just a placeholder. */
pqueue->used --;
(*u) = pqueue->u[1];
(*v) = pqueue->v[1];
(*val) = pqueue->val[1];
(*e) = pqueue->e[1];
insert_single_sublattice_pq_down ( pqueue,
pqueue->u[pqueue->used],
pqueue->v[pqueue->used],
pqueue->val[pqueue->used],
pqueue->e[pqueue->used] );
}
/**
* Create priority queue for sublattices with best alpha.
*/
void
new_alpha_pq ( alpha_pq **ppqueue,
unsigned long len )
{
if ( len < 2 ) {
fprintf(stderr,"Error: len < 2 in new_alpha_pq()\n");
exit(1);
}
(*ppqueue) = (alpha_pq *) malloc (sizeof (alpha_pq));
if ( (*ppqueue) == NULL) {
fprintf(stderr,"Error: malloc failed in new_alpha_pq()\n");
exit(1);
}
(*ppqueue)->len = len;
(*ppqueue)->w = (int *) malloc (len* sizeof (int));
(*ppqueue)->alpha = (float *) malloc (len* sizeof (float));
(*ppqueue)->u = (mpz_t *) malloc (len* sizeof (mpz_t));
(*ppqueue)->v = (mpz_t *) malloc (len* sizeof (mpz_t));
(*ppqueue)->modulus = (mpz_t *) malloc (len* sizeof (mpz_t));
if ( (*ppqueue)->w == NULL ||
(*ppqueue)->alpha == NULL ||
(*ppqueue)->modulus == NULL ||
(*ppqueue)->u == NULL ||
(*ppqueue)->v == NULL ) {
fprintf(stderr,"Error: malloc failed in new_sub_alpha_pq()\n");
exit(1);
}
int i;
for (i = 0; i < (*ppqueue)->len; i++)
{
mpz_init ( (*ppqueue)->u[i] );
mpz_init ( (*ppqueue)->v[i] );
mpz_init ( (*ppqueue)->modulus[i] );
}
mpz_set_ui ( (*ppqueue)->u[0], 0 );
mpz_set_ui ( (*ppqueue)->v[0], 0 );
mpz_set_ui ( (*ppqueue)->modulus[0], 0 );
(*ppqueue)->alpha[0] = FLT_MAX;
(*ppqueue)->w[0] = 0;
(*ppqueue)->used = 1;
}
/**
* Free
*/
void
free_alpha_pq ( alpha_pq **ppqueue )
{
int i;
for (i = 0; i < (*ppqueue)->len; i++)
{
mpz_clear ( (*ppqueue)->u[i] );
mpz_clear ( (*ppqueue)->v[i] );
mpz_clear ( (*ppqueue)->modulus[i] );
}
free ( (*ppqueue)->u );
free ( (*ppqueue)->v );
free ( (*ppqueue)->modulus );
free ( (*ppqueue)->w );
free ( (*ppqueue)->alpha );
free ( *ppqueue );
}
/**
* Sift-up to add, if the queue is not full.
*/
static inline void
insert_alpha_pq_up ( alpha_pq *pqueue,
int w,
mpz_t u,
mpz_t v,
mpz_t modulus,
double alpha )
{
int k;
for ( k = pqueue->used;
alpha > pqueue->alpha[pq_parent(k)];
k /= 2 )
{
mpz_set ( pqueue->u[k], pqueue->u[pq_parent(k)] );
mpz_set ( pqueue->v[k], pqueue->v[pq_parent(k)] );
mpz_set ( pqueue->modulus[k], pqueue->modulus[pq_parent(k)] );
pqueue->w[k] = pqueue->w[pq_parent(k)];
pqueue->alpha[k] = pqueue->alpha[pq_parent(k)];
}
mpz_set (pqueue->u[k], u);
mpz_set (pqueue->v[k], v);
mpz_set (pqueue->modulus[k], modulus);
pqueue->w[k] = w;
pqueue->alpha[k] = alpha;
pqueue->used ++;
}
/**
* Sift-down, if the heap is full.
*/
static inline void
insert_alpha_pq_down ( alpha_pq *pqueue,
int w,
mpz_t u,
mpz_t v,
mpz_t modulus,
double alpha )
{
int k, l;
for (k = 1; k*2 < pqueue->used; k = l) {
l = (k << 1);
/* right > left ? */
if ( (l+1) < pqueue->used &&
(pqueue->alpha[l+1] > pqueue->alpha[l]) )
l ++;
/* switch larger child with parent */
if ( pqueue->alpha[l] > alpha ) {
mpz_set (pqueue->u[k], pqueue->u[l]);
mpz_set (pqueue->v[k], pqueue->v[l]);
mpz_set (pqueue->modulus[k], pqueue->modulus[l]);
pqueue->w[k] = pqueue->w[l];
pqueue->alpha[k] = pqueue->alpha[l];
}
else
break;
}
mpz_set (pqueue->u[k], u);
mpz_set (pqueue->v[k], v);
mpz_set (pqueue->modulus[k], modulus);
pqueue->w[k] = w;
pqueue->alpha[k] = alpha;
}
/**
* Extract the max of the priority queue.
*/
void
extract_alpha_pq ( alpha_pq *pqueue,
int *w,
mpz_t u,
mpz_t v,
mpz_t modulus,
double *alpha )
{
/* don't extract u[0] since it is just a placeholder. */
pqueue->used --;
mpz_set (u, pqueue->u[1]);
mpz_set (v, pqueue->v[1]);
mpz_set (modulus, pqueue->modulus[1]);
*alpha = pqueue->alpha[1];
*w = pqueue->w[1];
insert_alpha_pq_down ( pqueue,
pqueue->w[pqueue->used],
pqueue->u[pqueue->used],
pqueue->v[pqueue->used],
pqueue->modulus[pqueue->used],
pqueue->alpha[pqueue->used] );
}
/**
* Insert to the priority queue.
*/
void
insert_alpha_pq ( alpha_pq *pqueue,
int w,
mpz_t u,
mpz_t v,
mpz_t modulus,
double alpha )
{
/* queue is full, */
if (pqueue->len == pqueue->used) {
if ( pqueue->alpha[1] > alpha) {
insert_alpha_pq_down (pqueue, w, u, v, modulus, alpha);
}
}
/* queue is not full, sift-up */
else if (pqueue->len > pqueue->used) {
insert_alpha_pq_up (pqueue, w, u, v, modulus, alpha);
}
else {
fprintf(stderr,"Error: error (pqueue->len < pqueue->used) "
"in insert_alpha_pq()\n");
exit(1);
}
}
/**
* Reset priority queue for alpha.
*/
void
reset_alpha_pq ( alpha_pq *pqueue )
{
if ( pqueue == NULL) {
fprintf(stderr,"Error: malloc failed in reset_alpha_pq()\n");
exit(1);
}
if ( pqueue->w == NULL || pqueue->u == NULL ||
pqueue->v == NULL || pqueue->modulus == NULL ||
pqueue->alpha == NULL ) {
fprintf(stderr,"Error: malloc failed in reset_alpha_pq()\n");
exit(1);
}
mpz_set_ui ( pqueue->u[0], 0 );
mpz_set_ui ( pqueue->v[0], 0 );
mpz_set_ui ( pqueue->modulus[0], 0 );
pqueue->w[0] = 0;
pqueue->alpha[0] = FLT_MAX;
pqueue->used = 1;
}
/**
* Remove duplicates in alpha queue.
*/
void
remove_rep_alpha ( alpha_pq *pqueue )
{
int flag;
alpha_pq *new;
new_alpha_pq (&new, pqueue->len);
for (int i=1; i<pqueue->used; i++) {
flag = 0;
for (int k=i+1; k<pqueue->used; k++) {
if ( (pqueue->w[i] == pqueue->w[k]) &&
mpz_cmp(pqueue->u[i],pqueue->u[k])==0 &&
mpz_cmp(pqueue->v[i],pqueue->v[k])==0 &&
mpz_cmp(pqueue->modulus[i], pqueue->modulus[k])==0) {
flag = 1;
break;
}
}
if (flag==0) {
insert_alpha_pq (new, pqueue->w[i], pqueue->u[i], pqueue->v[i],
pqueue->modulus[i], pqueue->alpha[i]);
}
}
reset_alpha_pq (pqueue);
pqueue->used = new->used;
for (int i=1; i<pqueue->used; i++) {
pqueue->w[i] = new->w[i];
mpz_set(pqueue->u[i],new->u[i]);
mpz_set(pqueue->v[i],new->v[i]);
mpz_set(pqueue->modulus[i],new->modulus[i]);
pqueue->alpha[i] = new->alpha[i];
}
free_alpha_pq (&new);
}
/**
* Create priority queue for best root scores (in MAT[] for a sublattice).
*/
void
new_sievescore_pq ( sievescore_pq **ppqueue,
unsigned long len )
{
if ( len < 2 ) {
fprintf(stderr,"Error: len < 2 in new_sievescore_pq()\n");
exit(1);
}
(*ppqueue) = (sievescore_pq *) malloc (sizeof (sievescore_pq));
if ( (*ppqueue) == NULL) {
fprintf(stderr,"Error: malloc failed in new_sievescore_pq()\n");
exit(1);
}
(*ppqueue)->len = len;
(*ppqueue)->i = (long *) malloc (len* sizeof (long));
(*ppqueue)->j = (long *) malloc (len* sizeof (long));
(*ppqueue)->alpha = (int16_t *) malloc (len* sizeof (int16_t));
if ( (*ppqueue)->i == NULL ||
(*ppqueue)->j == NULL ||
(*ppqueue)->alpha == NULL ) {
fprintf(stderr,"Error: malloc failed in new_sievescore_pq()\n");
exit(1);
}
/* i[0] and j[0] are null elements */
(*ppqueue)->i[0] = 0;
(*ppqueue)->j[0] = 0;
(*ppqueue)->alpha[0] = INT16_MAX;
(*ppqueue)->used = 1;
}
/**
* Reset priority queue for best root scores (in MAT[] for a sublattice).
*/
void
reset_sievescore_pq ( sievescore_pq *pqueue )
{
if ( pqueue == NULL) {
fprintf(stderr,"Error: malloc failed in new_sievescore_pq()\n");
exit(1);
}
if ( pqueue->i == NULL ||
pqueue->j == NULL ||
pqueue->alpha == NULL ) {
fprintf(stderr,"Error: malloc failed in new_sievescore_pq()\n");
exit(1);
}
/* i[0] and j[0] are null elements */
pqueue->i[0] = 0;
pqueue->j[0] = 0;
pqueue->alpha[0] = INT16_MAX;
pqueue->used = 1;
}
/**
* Free
*/
void
free_sievescore_pq ( sievescore_pq **ppqueue )
{
free ( (*ppqueue)->i );
free ( (*ppqueue)->j );
free ( (*ppqueue)->alpha );
free ( *ppqueue );
}
/**
* Sift-up to add, if the queue is not full.
*/
static inline void
insert_sievescore_pq_up ( sievescore_pq *pqueue,
long i,
long j,
int16_t alpha )
{
int k;
for ( k = pqueue->used;
alpha > pqueue->alpha[pq_parent(k)];
k /= 2 )
{
pqueue->i[k] = pqueue->i[pq_parent(k)];
pqueue->j[k] = pqueue->j[pq_parent(k)];
pqueue->alpha[k] = pqueue->alpha[pq_parent(k)];
}
pqueue->i[k] = i;
pqueue->j[k] = j;
pqueue->alpha[k] = alpha;
pqueue->used ++;
}
/**
* Sift-down, if the heap is full.
*/
static inline void
insert_sievescore_pq_down ( sievescore_pq *pqueue,
long i,
long j,
int16_t alpha )
{
int k, l;
for (k = 1; k*2 < pqueue->used; k = l) {
l = (k << 1);
/* right > left ? */
if ( (l+1) < pqueue->used &&
(pqueue->alpha[l+1] > pqueue->alpha[l]) )
l ++;
/* switch larger child with parent */
if ( pqueue->alpha[l] > alpha ) {
pqueue->i[k] = pqueue->i[l];
pqueue->j[k] = pqueue->j[l];
pqueue->alpha[k] = pqueue->alpha[l];
}
else
break;
}
pqueue->i[k] = i;
pqueue->j[k] = j;
pqueue->alpha[k] = alpha;
}
/**
* Insert to the priority queue.
*/
void
insert_sievescore_pq ( sievescore_pq *pqueue,
long i,
long j,
int16_t alpha )
{
/* fprintf (stderr, "# Debug: inserting (%ld, %ld), "
"alpha: %d, used: %d, len: %d\n", */
/* queue is full, */
if (pqueue->len == pqueue->used) {
if ( alpha < pqueue->alpha[1] ) {
insert_sievescore_pq_down (pqueue, i, j, alpha);
}
}
/* queue is not full, sift-up */
else if (pqueue->len > pqueue->used) {
insert_sievescore_pq_up (pqueue, i, j, alpha);
}
else {
fprintf(stderr,"Error: error (pqueue->len < pqueue->used) "
"in insert_sublattice_pq()\n");
exit(1);
}
}
/**
* Create priority queue for MurphyE
*/
void
new_MurphyE_pq ( MurphyE_pq **ppqueue,
unsigned long len )
{
if ( len < 2 ) {
fprintf(stderr,"Error: len < 2 in new_MurphyE_pq()\n");
exit(1);
}
(*ppqueue) = (MurphyE_pq *) malloc (sizeof (MurphyE_pq));
if ( (*ppqueue) == NULL) {
fprintf(stderr,"Error: malloc failed in new_MurphyE_pq()\n");
exit(1);
}
(*ppqueue)->len = len;
(*ppqueue)->w = (int *) malloc (len* sizeof (int));
(*ppqueue)->u = (mpz_t *) malloc (len* sizeof (mpz_t));
(*ppqueue)->v = (mpz_t *) malloc (len* sizeof (mpz_t));
(*ppqueue)->modulus = (mpz_t *) malloc (len* sizeof (mpz_t));
(*ppqueue)->E = (double *) malloc (len* sizeof (double));
if ( (*ppqueue)->u == NULL || (*ppqueue)->v == NULL ||
(*ppqueue)->w == NULL || (*ppqueue)->E == NULL ||
(*ppqueue)->modulus == NULL ) {
fprintf(stderr,"Error: malloc failed in new_MurphyE_pq()\n");
exit(1);
}
int i;
for (i = 0; i < (*ppqueue)->len; i++)
{
mpz_init ( (*ppqueue)->u[i] );
mpz_init ( (*ppqueue)->v[i] );
mpz_init ( (*ppqueue)->modulus[i] );
}
mpz_set_ui ( (*ppqueue)->u[0], 0 );
mpz_set_ui ( (*ppqueue)->v[0], 0 );
mpz_set_ui ( (*ppqueue)->modulus[0], 0 );
(*ppqueue)->w[0] = 0;
(*ppqueue)->E[0] = -DBL_MAX;
(*ppqueue)->used = 1;
}
/**
* Free
*/
void
free_MurphyE_pq ( MurphyE_pq **ppqueue )
{
int i;
for (i = 0; i < (*ppqueue)->len; i++) {
mpz_clear ( (*ppqueue)->u[i] );
mpz_clear ( (*ppqueue)->v[i] );
mpz_clear ( (*ppqueue)->modulus[i] );
}
free ( (*ppqueue)->w );
free ( (*ppqueue)->u );
free ( (*ppqueue)->modulus );
free ( (*ppqueue)->v );
free ( (*ppqueue)->E );
free ( *ppqueue );
}
/**
* Sift-up to add, if the queue is not full.
*/
static inline void
insert_MurphyE_pq_up ( MurphyE_pq *pqueue,
int w,
mpz_t u,
mpz_t v,
mpz_t modulus,
double E )
{
int k;
for ( k = pqueue->used;
E < pqueue->E[pq_parent(k)];
k /= 2 )
{
mpz_set ( pqueue->u[k], pqueue->u[pq_parent(k)] );
mpz_set ( pqueue->v[k], pqueue->v[pq_parent(k)] );
mpz_set ( pqueue->modulus[k], pqueue->modulus[pq_parent(k)] );
pqueue->w[k] = pqueue->w[pq_parent(k)];
pqueue->E[k] = pqueue->E[pq_parent(k)];
}
mpz_set (pqueue->u[k], u);
mpz_set (pqueue->v[k], v);
mpz_set (pqueue->modulus[k], modulus);
pqueue->w[k] = w;
pqueue->E[k] = E;
pqueue->used ++;
}
/**
* Sift-down, if the heap is full.
*/
static inline void
insert_MurphyE_pq_down ( MurphyE_pq *pqueue,
int w,
mpz_t u,
mpz_t v,
mpz_t modulus,
double E )
{
int k, l;
for (k = 1; k*2 < pqueue->used; k = l) {
l = (k << 1);
/* right < left ? */
if ( (l+1) < pqueue->used &&
(pqueue->E[l+1] < pqueue->E[l]) )
l ++;
/* switch smaller child with parent */
if ( pqueue->E[l] < E ) {
mpz_set (pqueue->u[k], pqueue->u[l]);
mpz_set (pqueue->v[k], pqueue->v[l]);
mpz_set (pqueue->modulus[k], pqueue->modulus[l]);
pqueue->w[k] = pqueue->w[l];
pqueue->E[k] = pqueue->E[l];
}
else
break;
}
mpz_set (pqueue->u[k], u);
mpz_set (pqueue->v[k], v);
mpz_set (pqueue->modulus[k], modulus);
pqueue->w[k] = w;
pqueue->E[k] = E;
}
/**
* Extract the max of the priority queue.
*/
void
extract_MurphyE_pq ( MurphyE_pq *pqueue,
int *w,
mpz_t u,
mpz_t v,
mpz_t modulus,
double *E )
{
/* don't extract u[0] since it is just a placeholder. */
pqueue->used --;
mpz_set (u, pqueue->u[1]);
mpz_set (v, pqueue->v[1]);
mpz_set (modulus, pqueue->modulus[1]);
*w = pqueue->w[1];
*E = pqueue->E[1];
insert_MurphyE_pq_down ( pqueue,
pqueue->w[pqueue->used],
pqueue->u[pqueue->used],
pqueue->v[pqueue->used],
pqueue->modulus[pqueue->used],
pqueue->E[pqueue->used] );
}
/**
* Insert to the priority queue.
*/
void
insert_MurphyE_pq ( MurphyE_pq *pqueue,
int w,
mpz_t u,
mpz_t v,
mpz_t modulus,
double E )
{
/* queue is full, */
if (pqueue->len == pqueue->used) {
if ( E > pqueue->E[1] ) {
insert_MurphyE_pq_down (pqueue, w, u, v, modulus, E);
}
}
/* queue is not full, sift-up */
else if (pqueue->len > pqueue->used) {
insert_MurphyE_pq_up (pqueue, w, u, v, modulus, E);
}
else {
fprintf(stderr,"Error: error (pqueue->len < pqueue->used) "
"in insert_MurphyE_pq()\n");
exit(1);
}
}
/**
* Reset priority queue for alpha.
*/
void
reset_MurphyE_pq ( MurphyE_pq *pqueue )
{
if ( pqueue == NULL) {
fprintf(stderr,"Error: malloc failed in reset_MurphyE_pq()\n");
exit(1);
}
if ( pqueue->w == NULL || pqueue->u == NULL ||
pqueue->v == NULL || pqueue->modulus == NULL ||
pqueue->E == NULL ) {
fprintf(stderr,"Error: malloc failed in reset_MurphyE_pq()\n");
exit(1);
}
mpz_set_ui ( pqueue->u[0], 0 );
mpz_set_ui ( pqueue->v[0], 0 );
mpz_set_ui ( pqueue->modulus[0], 0 );
pqueue->w[0] = 0;
pqueue->E[0] = -DBL_MAX;
pqueue->used = 1;
}
/**
* Remove duplicates in murphyE queue.
*/
void
remove_rep_MurphyE ( MurphyE_pq *pqueue )
{
int flag;
MurphyE_pq *new;
new_MurphyE_pq (&new, pqueue->len);
for (int i=1; i<pqueue->used; i++) {
flag = 0;
for (int k=i+1; k<pqueue->used; k++) {
if ( (pqueue->w[i] == pqueue->w[k]) &&
mpz_cmp(pqueue->u[i],pqueue->u[k])==0 &&
mpz_cmp(pqueue->v[i],pqueue->v[k])==0 &&
mpz_cmp(pqueue->modulus[i], pqueue->modulus[k])==0) {
flag = 1;
break;
}
}
if (flag==0) {
insert_MurphyE_pq (new, pqueue->w[i], pqueue->u[i], pqueue->v[i],
pqueue->modulus[i], pqueue->E[i]);
}
}
reset_MurphyE_pq (pqueue);
pqueue->used = new->used;
for (int i=1; i<pqueue->used; i++) {
pqueue->w[i] = new->w[i];
mpz_set(pqueue->u[i],new->u[i]);
mpz_set(pqueue->v[i],new->v[i]);
mpz_set(pqueue->modulus[i],new->modulus[i]);
pqueue->E[i] = new->E[i];
}
free_MurphyE_pq (&new);
}
Computing file changes ...