diff --git a/include/poly.h b/include/poly.h
index 65c5bb67..99b43cbf 100644
--- a/include/poly.h
+++ b/include/poly.h
@@ -68,6 +68,7 @@ typedef struct lp_interval_struct lp_interval_t;
typedef struct lp_feasibility_set_struct lp_feasibility_set_t;
typedef struct lp_polynomial_hash_set_struct lp_polynomial_hash_set_t;
typedef struct lp_polynomial_vector_struct lp_polynomial_vector_t;
+typedef struct lp_polynomial_heap_struct lp_polynomial_heap_t;
/** Enable a given tag for tracing */
void lp_trace_enable(const char* tag);
diff --git a/include/polynomial_hash_set.h b/include/polynomial_hash_set.h
index dde568d7..597e0147 100644
--- a/include/polynomial_hash_set.h
+++ b/include/polynomial_hash_set.h
@@ -32,12 +32,18 @@ struct lp_polynomial_hash_set_struct {
size_t data_size;
/** Number of set elements */
size_t size;
- /** Treshold for resize */
+ /** Threshold for resize */
size_t resize_threshold;
/** Has the set been closed */
int closed;
};
+/** Allocate and construct a new hash set */
+lp_polynomial_hash_set_t* lp_polynomial_hash_set_new(void);
+
+/** Destructs and deletes the hash set */
+void lp_polynomial_hash_set_delete(lp_polynomial_hash_set_t* set);
+
/** Construct a new set */
void lp_polynomial_hash_set_construct(lp_polynomial_hash_set_t* set);
@@ -45,17 +51,36 @@ void lp_polynomial_hash_set_construct(lp_polynomial_hash_set_t* set);
void lp_polynomial_hash_set_destruct(lp_polynomial_hash_set_t* set);
/** Returns true if empty */
-int lp_polynomial_hash_set_is_empty(lp_polynomial_hash_set_t* set);
+int lp_polynomial_hash_set_is_empty(const lp_polynomial_hash_set_t* set);
+
+/** Returns the number of elements */
+size_t lp_polynomial_hash_set_size(const lp_polynomial_hash_set_t* set);
/** Check whether p is in set. The set must not be closed). */
-int lp_polynomial_hash_set_contains(lp_polynomial_hash_set_t* set, const lp_polynomial_t* p);
+int lp_polynomial_hash_set_contains(const lp_polynomial_hash_set_t* set, const lp_polynomial_t* p);
-/** Add polynomial p to set. Returns true if p was added (not already in the set). */
+/** Add polynomial p to the set. Returns true if p was added (not already in the set). */
int lp_polynomial_hash_set_insert(lp_polynomial_hash_set_t* set, const lp_polynomial_t* p);
+/** Add polynomial p to the set. Returns true if p was added (not already in the set) and p becomes a 0 polynomial.
+ * Returns false if p was found in the set and p remained unchanged. */
+int lp_polynomial_hash_set_insert_move(lp_polynomial_hash_set_t* set, lp_polynomial_t* p);
+
+/** Add all polynomials from the vector to the hash map. Returns the number of inserted polynomials */
+int lp_polynomial_hash_set_insert_vector(lp_polynomial_hash_set_t* set, const lp_polynomial_vector_t* v);
+
+/** Add polynomial p to set. Returns true if p was removed (was in the set). */
+int lp_polynomial_hash_set_remove(lp_polynomial_hash_set_t* set, const lp_polynomial_t* p);
+
+/** Removes all elements from set that are not in other */
+void lp_polynomial_hash_set_intersect(lp_polynomial_hash_set_t* set, const lp_polynomial_hash_set_t* other);
+
/** Close the set: compact the data so that all elements get stored in data[0..size]. No addition after close! */
void lp_polynomial_hash_set_close(lp_polynomial_hash_set_t* set);
+/** Returns one element at index. Hashset must be closed. */
+const lp_polynomial_t* lp_polynomial_hash_set_at(const lp_polynomial_hash_set_t* set, size_t n);
+
/** Clear the set. */
void lp_polynomial_hash_set_clear(lp_polynomial_hash_set_t* set);
diff --git a/include/polynomial_heap.h b/include/polynomial_heap.h
new file mode 100644
index 00000000..cd4cc197
--- /dev/null
+++ b/include/polynomial_heap.h
@@ -0,0 +1,88 @@
+/**
+ * Copyright 2015, SRI International.
+ *
+ * This file is part of LibPoly.
+ *
+ * LibPoly is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LibPoly 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with LibPoly. If not, see .
+ */
+
+#pragma once
+
+#include "poly.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*lp_polynomial_heap_compare_f)(const lp_polynomial_t* A, const lp_polynomial_t* B);
+
+struct lp_polynomial_heap_struct {
+ /** The data */
+ lp_polynomial_t** data;
+ /** Size of the data */
+ size_t data_size;
+ /** Number of set elements */
+ size_t size;
+ /** The compare function */
+ lp_polynomial_heap_compare_f cmp;
+};
+
+/** Allocates a new heap and constructs it */
+lp_polynomial_heap_t* lp_polynomial_heap_new(lp_polynomial_heap_compare_f cmp);
+
+/** Destructs a heap and frees the memory */
+void lp_polynomial_heap_delete(lp_polynomial_heap_t* heap);
+
+/** Construct a new heap */
+void lp_polynomial_heap_construct(lp_polynomial_heap_t* heap, lp_polynomial_heap_compare_f cmp);
+
+/** Destruct the heap */
+void lp_polynomial_heap_destruct(lp_polynomial_heap_t* heap);
+
+/** Returns true if empty */
+int lp_polynomial_heap_is_empty(const lp_polynomial_heap_t* heap);
+
+/** Returns the number of elements */
+size_t lp_polynomial_heap_size(const lp_polynomial_heap_t* heap);
+
+/** Add polynomial p to the heap. */
+void lp_polynomial_heap_push(lp_polynomial_heap_t* heap, const lp_polynomial_t* p);
+
+/** Add polynomial p to the heap. Moves the content of p and p becomes a 0 polynomial. */
+void lp_polynomial_heap_push_move(lp_polynomial_heap_t* heap, lp_polynomial_t* p);
+
+/** Add all polynomials from the vector to the heap */
+void lp_polynomial_heap_push_vector(lp_polynomial_heap_t* heap, const lp_polynomial_vector_t* v);
+
+/** Removes and returns the top element of the heap, returns NULL if the heap is empty */
+lp_polynomial_t* lp_polynomial_heap_pop(lp_polynomial_heap_t* heap);
+
+/** Removes an element from the heap. Returns number of removed polynomials. */
+int lp_polynomial_heap_remove(lp_polynomial_heap_t* heap, const lp_polynomial_t *p);
+
+/** Returns the top element without removing it. */
+const lp_polynomial_t* lp_polynomial_heap_peek(const lp_polynomial_heap_t* heap);
+
+/** Returns one element */
+const lp_polynomial_t* lp_polynomial_heap_at(const lp_polynomial_heap_t* heap, size_t n);
+
+/** Clear the heap. */
+void lp_polynomial_heap_clear(lp_polynomial_heap_t* heap);
+
+/** Prints the heap */
+void lp_polynomial_heap_print(lp_polynomial_heap_t* heap, FILE *);
+
+#ifdef __cplusplus
+} /* close extern "C" { */
+#endif
diff --git a/include/polynomial_vector.h b/include/polynomial_vector.h
index a53b2bc9..13f539b4 100644
--- a/include/polynomial_vector.h
+++ b/include/polynomial_vector.h
@@ -28,12 +28,22 @@ extern "C" {
/** Allocate and construct a new vector */
lp_polynomial_vector_t* lp_polynomial_vector_new(const lp_polynomial_context_t* ctx);
-/* Delete the vector */
+/** Allocate and construct a new vector, copies all elements from v */
+lp_polynomial_vector_t* lp_polynomial_vector_copy(const lp_polynomial_vector_t *v);
+
+/** Delete the vector */
void lp_polynomial_vector_delete(lp_polynomial_vector_t* v);
+/** Swap two vectors */
+void lp_polynomial_vector_swap(lp_polynomial_vector_t *v1, lp_polynomial_vector_t *v2);
+
/** Add to back (makes a copy, should be in the context of the vector) */
void lp_polynomial_vector_push_back(lp_polynomial_vector_t* v, const lp_polynomial_t* p);
+/** Add to back by move. More efficient than copying, p becomes a (constructed) zero-polynomial
+ * and must be in the context of the vector. */
+void lp_polynomial_vector_push_back_move(lp_polynomial_vector_t* v, lp_polynomial_t* p);
+
/** Reset the vector to 0 elements */
void lp_polynomial_vector_reset(lp_polynomial_vector_t* v);
@@ -43,6 +53,12 @@ size_t lp_polynomial_vector_size(const lp_polynomial_vector_t* v);
/** Returns the polynomial at i (newly constructed each time) */
lp_polynomial_t* lp_polynomial_vector_at(const lp_polynomial_vector_t* v, size_t i);
+/** Returns the context of the polynomial vector */
+const lp_polynomial_context_t* lp_polynomial_vector_get_context(const lp_polynomial_vector_t *v);
+
+/** Prints the polynomial vector to the given stream. */
+void lp_polynomial_vector_print(const lp_polynomial_vector_t* v, FILE* out);
+
#ifdef __cplusplus
} /* close extern "C" { */
#endif
diff --git a/include/upolynomial.h b/include/upolynomial.h
index f7bc9247..51ad71e1 100644
--- a/include/upolynomial.h
+++ b/include/upolynomial.h
@@ -109,6 +109,12 @@ int lp_upolynomial_print(const lp_upolynomial_t* p, FILE* out);
*/
char* lp_upolynomial_to_string(const lp_upolynomial_t* p);
+/**
+ * Converts the upolynomial to a polynomial in variable var.
+ * ctx must have the same ring than upolynomial.
+ */
+lp_polynomial_t* lp_upolynomial_to_polynomial(const lp_upolynomial_t* p, const lp_polynomial_context_t* ctx, lp_variable_t var);
+
/**
* Returns true if this is a zero polynomial
*/
diff --git a/include/variable_order.h b/include/variable_order.h
index 73a5a9c5..bc7ba71e 100644
--- a/include/variable_order.h
+++ b/include/variable_order.h
@@ -45,6 +45,22 @@ void lp_variable_order_detach(lp_variable_order_t* var_order);
*/
int lp_variable_order_cmp(const lp_variable_order_t* var_order, lp_variable_t x, lp_variable_t y);
+/** returns the bigger of the two variables wrt. the order */
+static inline
+lp_variable_t lp_variable_order_max(const lp_variable_order_t* var_order, lp_variable_t x, lp_variable_t y) {
+ if (x == lp_variable_null) return y;
+ if (y == lp_variable_null) return x;
+ return lp_variable_order_cmp(var_order, x, y) < 0 ? x : y;
+}
+
+/** returns the smaller of the two variables wrt. the order */
+static inline
+lp_variable_t lp_variable_order_min(const lp_variable_order_t* var_order, lp_variable_t x, lp_variable_t y) {
+ if (x == lp_variable_null) return y;
+ if (y == lp_variable_null) return x;
+ return lp_variable_order_cmp(var_order, x, y) > 0 ? x : y;
+}
+
/** Get the size of the order */
size_t lp_variable_order_size(const lp_variable_order_t* var_order);
diff --git a/python/polypyPolynomial3.c b/python/polypyPolynomial3.c
index 8273a16d..026a80a8 100644
--- a/python/polypyPolynomial3.c
+++ b/python/polypyPolynomial3.c
@@ -182,7 +182,7 @@ PyMethodDef Polynomial_methods[] = {
{"coefficients", (PyCFunction)Polynomial_coefficients, METH_NOARGS, "Returns a dictionary from degrees to coefficients"},
{"reductum", (PyCFunction)Polynomial_reductum, METH_VARARGS, "Returns the reductum of the polynomial"},
{"sgn", (PyCFunction)Polynomial_sgn, METH_VARARGS, "Returns the sign of the polynomials in the given model"},
- {"sgn_check", (PyCFunction)Polynomial_sgn_check, METH_VARARGS, "Returns true if the sign of the polynomail respects the sign condition."},
+ {"sgn_check", (PyCFunction)Polynomial_sgn_check, METH_VARARGS, "Returns true if the sign of the polynomial respects the sign condition."},
{"rem", (PyCFunction)Polynomial_rem, METH_VARARGS, "Returns the remainder of current and given polynomial"},
{"prem", (PyCFunction)Polynomial_prem, METH_VARARGS, "Returns the pseudo remainder of current and given polynomial"},
{"sprem", (PyCFunction)Polynomial_sprem, METH_VARARGS, "Returns the sparse pseudo remainder of current and given polynomial"},
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ac20a969..366cb1f6 100755
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -34,6 +34,7 @@ set(poly_SOURCES
polynomial/polynomial_context.c
polynomial/feasibility_set.c
polynomial/polynomial_hash_set.c
+ polynomial/polynomial_heap.c
polynomial/polynomial_vector.c
poly.c
)
diff --git a/src/polynomial/polynomial_hash_set.c b/src/polynomial/polynomial_hash_set.c
index 078d2420..92fa6692 100644
--- a/src/polynomial/polynomial_hash_set.c
+++ b/src/polynomial/polynomial_hash_set.c
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include
@@ -30,6 +31,17 @@
/** Resize threshold: the size is doubled when nelems >= size * RESIZE_RATIO */
#define LP_POLYNOMIAL_HASH_SET_RESIZE_RATIO 0.7
+lp_polynomial_hash_set_t* lp_polynomial_hash_set_new(void) {
+ lp_polynomial_hash_set_t *set = malloc(sizeof(lp_polynomial_hash_set_t));
+ lp_polynomial_hash_set_construct(set);
+ return set;
+}
+
+void lp_polynomial_hash_set_delete(lp_polynomial_hash_set_t* set) {
+ lp_polynomial_hash_set_destruct(set);
+ free(set);
+}
+
void lp_polynomial_hash_set_construct(lp_polynomial_hash_set_t* set) {
set->data = malloc(LP_POLYNOMIAL_HASH_SET_DEFAULT_SIZE*sizeof(lp_polynomial_t*));
memset(set->data, 0, LP_POLYNOMIAL_HASH_SET_DEFAULT_SIZE*sizeof(lp_polynomial_t*));
@@ -52,12 +64,28 @@ void lp_polynomial_hash_set_destruct(lp_polynomial_hash_set_t* set) {
set->data = NULL;
}
-int lp_polynomial_hash_set_is_empty(lp_polynomial_hash_set_t* set) {
+int lp_polynomial_hash_set_is_empty(const lp_polynomial_hash_set_t* set) {
return set->size == 0;
}
+size_t lp_polynomial_hash_set_size(const lp_polynomial_hash_set_t* set) {
+ return set->size;
+}
+
static
-void lp_polynomial_hash_set_insert_move(lp_polynomial_t** data, size_t mask, lp_polynomial_t* p) {
+int lp_polynomial_hash_set_insert_move_check(lp_polynomial_t** data, size_t mask, lp_polynomial_t* p) {
+ size_t i = lp_polynomial_hash(p) & mask;
+ while (data[i] != 0) {
+ if (lp_polynomial_eq(data[i], p)) { return 0; }
+ i ++;
+ i &= mask;
+ }
+ data[i] = p;
+ return 1;
+}
+
+static
+void lp_polynomial_hash_set_insert_move_no_check(lp_polynomial_t** data, size_t mask, lp_polynomial_t* p) {
size_t i = lp_polynomial_hash(p) & mask;
while (data[i] != 0) {
i ++;
@@ -79,7 +107,20 @@ int lp_polynomial_hash_set_insert_copy(lp_polynomial_t** data, size_t mask, cons
}
static
-int lp_polynomial_hash_set_search(lp_polynomial_t** data, size_t mask, const lp_polynomial_t* p) {
+int lp_polynomial_hash_set_insert_swap(lp_polynomial_t** data, size_t mask, lp_polynomial_t* p) {
+ size_t i = lp_polynomial_hash(p) & mask;
+ while (data[i] != 0) {
+ if (lp_polynomial_eq(data[i], p)) { return 0; }
+ i ++;
+ i &= mask;
+ }
+ data[i] = lp_polynomial_new(lp_polynomial_get_context(p));
+ lp_polynomial_swap(data[i], p);
+ return 1;
+}
+
+static
+int lp_polynomial_hash_set_search(lp_polynomial_t* const* data, size_t mask, const lp_polynomial_t* p) {
size_t i = lp_polynomial_hash(p) & mask;
for (;;) {
if (data[i] == 0) return 0;
@@ -90,6 +131,28 @@ int lp_polynomial_hash_set_search(lp_polynomial_t** data, size_t mask, const lp_
return 0;
}
+#define SWAP(A, B) ({lp_polynomial_t *tmp = A; A = B; B = tmp;})
+
+static
+int lp_polynomial_hash_set_search_and_remove(lp_polynomial_t** data, size_t mask, const lp_polynomial_t* p) {
+ size_t i = lp_polynomial_hash(p) & mask;
+ for (;;) {
+ if (data[i] == 0) return 0;
+ if (lp_polynomial_eq(data[i], p)) break;
+ i ++;
+ i &= mask;
+ }
+ lp_polynomial_delete(data[i]);
+ data[i] = 0;
+ for (;;) {
+ size_t j = (i + 1) & mask;
+ if (data[j] == 0 || (lp_polynomial_hash(data[j]) & mask) == j) break;
+ SWAP(data[i], data[j]);
+ i = j;
+ }
+ return 1;
+}
+
/** Double the size of the set. */
static
void lp_polynomial_hash_set_extend(lp_polynomial_hash_set_t* set) {
@@ -105,7 +168,7 @@ void lp_polynomial_hash_set_extend(lp_polynomial_hash_set_t* set) {
for (i = 0; i < old_data_size; ++ i) {
lp_polynomial_t* p = set->data[i];
if (p != 0) {
- lp_polynomial_hash_set_insert_move(new_data, mask, p);
+ lp_polynomial_hash_set_insert_move_no_check(new_data, mask, p);
}
}
@@ -115,7 +178,7 @@ void lp_polynomial_hash_set_extend(lp_polynomial_hash_set_t* set) {
set->resize_threshold = new_data_size*LP_POLYNOMIAL_HASH_SET_RESIZE_RATIO;
}
-int lp_polynomial_hash_set_contains(lp_polynomial_hash_set_t* set, const lp_polynomial_t* p) {
+int lp_polynomial_hash_set_contains(const lp_polynomial_hash_set_t* set, const lp_polynomial_t* p) {
assert(p);
assert(!set->closed);
return lp_polynomial_hash_set_search(set->data, set->data_size-1, p);
@@ -137,6 +200,80 @@ int lp_polynomial_hash_set_insert(lp_polynomial_hash_set_t* set, const lp_polyno
return result;
}
+int lp_polynomial_hash_set_insert_move(lp_polynomial_hash_set_t* set, lp_polynomial_t* p) {
+ assert(p);
+ assert(set->data_size > set->size);
+ assert(!set->closed);
+
+ int result = lp_polynomial_hash_set_insert_swap(set->data, set->data_size-1, p);
+ if (result) {
+ set->size ++;
+ if (set->size > set->resize_threshold) {
+ lp_polynomial_hash_set_extend(set);
+ }
+ }
+
+ return result;
+}
+
+int lp_polynomial_hash_set_insert_vector(lp_polynomial_hash_set_t* set, const lp_polynomial_vector_t* v) {
+ assert(v);
+ assert(set->data_size > set->size);
+ assert(!set->closed);
+
+ int inserted = 0;
+ size_t size = lp_polynomial_vector_size(v);
+ for (size_t i = 0; i < size; ++i) {
+ lp_polynomial_t *p = lp_polynomial_vector_at(v, i);
+ int result = lp_polynomial_hash_set_insert_move_check(set->data, set->data_size - 1, p);
+ if (result) {
+ inserted ++;
+ set->size ++;
+ if (set->size > set->resize_threshold) {
+ lp_polynomial_hash_set_extend(set);
+ }
+ } else {
+ lp_polynomial_delete(p);
+ }
+ }
+ return inserted;
+}
+
+int lp_polynomial_hash_set_remove(lp_polynomial_hash_set_t* set, const lp_polynomial_t* p) {
+ assert(p);
+ assert(!set->closed);
+
+ int result = lp_polynomial_hash_set_search_and_remove(set->data, set->data_size-1, p);
+ if (result) {
+ set->size --;
+ }
+
+ return result;
+}
+
+void lp_polynomial_hash_set_intersect(lp_polynomial_hash_set_t* set, const lp_polynomial_hash_set_t* other) {
+ assert(!set->closed);
+
+ size_t mask = set->data_size - 1;
+ for (size_t i = 0; i < set->data_size;) {
+ if (set->data[i] == NULL) {
+ ++i;
+ continue;
+ }
+ if (!lp_polynomial_hash_set_contains(other, set->data[i])) {
+ lp_polynomial_delete(set->data[i]);
+ set->data[i] = NULL;
+ size_t k = i;
+ for (;;) {
+ size_t j = (k + 1) & mask;
+ if (set->data[j] == 0 || (lp_polynomial_hash(set->data[j]) & mask) == j) break;
+ SWAP(set->data[k], set->data[j]);
+ k = j;
+ }
+ }
+ }
+}
+
void lp_polynomial_hash_set_close(lp_polynomial_hash_set_t* set) {
if (set->closed) {
@@ -160,6 +297,14 @@ void lp_polynomial_hash_set_close(lp_polynomial_hash_set_t* set) {
assert(i == set->size && i < data_size);
}
+const lp_polynomial_t* lp_polynomial_hash_set_at(const lp_polynomial_hash_set_t* set, size_t n) {
+ assert(set->closed);
+ if (n >= set->size) {
+ return NULL;
+ }
+ return set->data[n];
+}
+
void lp_polynomial_hash_set_clear(lp_polynomial_hash_set_t* set) {
lp_polynomial_hash_set_destruct(set);
lp_polynomial_hash_set_construct(set);
diff --git a/src/polynomial/polynomial_heap.c b/src/polynomial/polynomial_heap.c
new file mode 100644
index 00000000..7bf6fd43
--- /dev/null
+++ b/src/polynomial/polynomial_heap.c
@@ -0,0 +1,197 @@
+/**
+ * Copyright 2015, SRI International.
+ *
+ * This file is part of LibPoly.
+ *
+ * LibPoly is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LibPoly 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with LibPoly. If not, see .
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+/** Default initial size (must be a power of 2) */
+#define LP_POLYNOMIAL_HEAP_DEFAULT_SIZE 32
+
+lp_polynomial_heap_t* lp_polynomial_heap_new(lp_polynomial_heap_compare_f cmp) {
+ lp_polynomial_heap_t *heap = malloc(sizeof(lp_polynomial_heap_t));
+ lp_polynomial_heap_construct(heap, cmp);
+ return heap;
+}
+
+void lp_polynomial_heap_delete(lp_polynomial_heap_t* heap) {
+ lp_polynomial_heap_destruct(heap);
+ free(heap);
+}
+
+void lp_polynomial_heap_construct(lp_polynomial_heap_t *heap, lp_polynomial_heap_compare_f cmp) {
+ heap->data = malloc(LP_POLYNOMIAL_HEAP_DEFAULT_SIZE * sizeof(lp_polynomial_t*));
+ heap->data_size = LP_POLYNOMIAL_HEAP_DEFAULT_SIZE;
+ heap->size = 0;
+ heap->cmp = cmp;
+}
+
+void lp_polynomial_heap_destruct(lp_polynomial_heap_t* heap) {
+ // remove all the polynomials
+ for (size_t i = 0; i < heap->size; ++i) {
+ lp_polynomial_delete(heap->data[i]);
+ }
+ // free the space
+ free(heap->data);
+ heap->data = NULL;
+}
+
+int lp_polynomial_heap_is_empty(const lp_polynomial_heap_t *heap) {
+ return heap->size == 0;
+}
+
+size_t lp_polynomial_heap_size(const lp_polynomial_heap_t* heap) {
+ return heap->size;
+}
+
+#define SWAP(A,B) ({ lp_polynomial_t *tmp = B; B = A; A = tmp; })
+// macros assume a heap indices 1...size
+#define HEAP_SWAP(heap, i, j) SWAP(heap->data[(i)-1], heap->data[(j)-1])
+#define HEAP_CMP(heap, i, j) (heap->cmp(heap->data[(i)-1], heap->data[(j)-1]))
+
+static
+void lp_polynomial_heap_extend(lp_polynomial_heap_t *heap) {
+ // double the size
+ heap->data_size <<= 1;
+ heap->data = realloc(heap->data, heap->data_size * sizeof(lp_polynomial_t*));
+}
+
+static
+void lp_polynomial_heap_heapify_up(lp_polynomial_heap_t *heap) {
+ for (size_t pos = heap->size;
+ pos > 1 && HEAP_CMP(heap, pos / 2, pos) < 0;
+ pos /= 2) {
+ // if data[pos] is smaller or equal than data[parent] swap
+ HEAP_SWAP(heap, pos / 2, pos);
+ }
+}
+
+static
+void lp_polynomial_heap_heapify_down(lp_polynomial_heap_t *heap, size_t pos) {
+ // we're using a 1-based index to enable heap index calculation
+ ++ pos;
+ // while there is still at least a left child
+ while (2 * pos <= heap->size) {
+ size_t l = 2 * pos;
+ size_t r = 2 * pos + 1;
+
+ // find larger child
+ size_t o = (r <= heap->size && HEAP_CMP(heap, l, r) < 0) ? r : l;
+
+ // in case current element is larger than larger child, we're done
+ if (HEAP_CMP(heap, pos, o) >= 0) break;
+
+ // swap larger child with current pos
+ HEAP_SWAP(heap, pos, o);
+ pos = o;
+ }
+}
+
+/** inserts a polynomial, does not copy the polynomial */
+static
+void lp_polynomial_heap_insert(lp_polynomial_heap_t* heap, lp_polynomial_t* p) {
+ assert(p);
+ heap->size++;
+ if (heap->size > heap->data_size) {
+ lp_polynomial_heap_extend(heap);
+ }
+ heap->data[heap->size - 1] = p;
+ lp_polynomial_heap_heapify_up(heap);
+}
+
+void lp_polynomial_heap_push(lp_polynomial_heap_t* heap, const lp_polynomial_t* p) {
+ lp_polynomial_heap_insert(heap, lp_polynomial_new_copy(p));
+}
+
+void lp_polynomial_heap_push_move(lp_polynomial_heap_t* heap, lp_polynomial_t* p) {
+ lp_polynomial_t *tmp = lp_polynomial_new(lp_polynomial_get_context(p));
+ lp_polynomial_swap(tmp, p);
+ lp_polynomial_heap_insert(heap, tmp);
+}
+
+void lp_polynomial_heap_push_vector(lp_polynomial_heap_t* heap, const lp_polynomial_vector_t* v) {
+ size_t size = lp_polynomial_vector_size(v);
+ for (size_t i = 0; i < size; ++i) {
+ // lp_polynomial_vector_at gives a fresh copied polynomial, we reuse it
+ lp_polynomial_heap_insert(heap, lp_polynomial_vector_at(v, i));
+ }
+}
+
+lp_polynomial_t* lp_polynomial_heap_pop(lp_polynomial_heap_t* heap) {
+ // empty heap does not have a top
+ if (heap->size == 0) {
+ return NULL;
+ }
+ // get the top element
+ lp_polynomial_t *ret = heap->data[0];
+ // reduce size and moves last element to top
+ heap->data[0] = heap->data[--heap->size];
+ // restore heap condition
+ lp_polynomial_heap_heapify_down(heap, 0);
+
+ return ret;
+}
+
+int lp_polynomial_heap_remove(lp_polynomial_heap_t* heap, const lp_polynomial_t *p){
+ int result = 0;
+ for (size_t i = 0; i < heap->size; ++i) {
+ if (lp_polynomial_eq(p, heap->data[i])) {
+ heap->data[i] = heap->data[--heap->size];
+ lp_polynomial_heap_heapify_down(heap, i);
+ result++;
+ }
+ }
+ return result;
+}
+
+const lp_polynomial_t* lp_polynomial_heap_peek(const lp_polynomial_heap_t* heap) {
+ // empty heap does not have a top
+ if (heap->size == 0) {
+ return NULL;
+ }
+ // return the top element
+ return heap->data[0];
+}
+
+const lp_polynomial_t* lp_polynomial_heap_at(const lp_polynomial_heap_t* heap, size_t n) {
+ if (n >= heap->size) {
+ return NULL;
+ }
+ return heap->data[n];
+}
+
+void lp_polynomial_heap_clear(lp_polynomial_heap_t* heap) {
+ lp_polynomial_heap_compare_f cmp = heap->cmp;
+ lp_polynomial_heap_destruct(heap);
+ lp_polynomial_heap_construct(heap, cmp);
+}
+
+void lp_polynomial_heap_print(lp_polynomial_heap_t* heap, FILE *stream) {
+ fputc('[', stream);
+ for (size_t i = 0; i < heap->size; ++i) {
+ lp_polynomial_print(heap->data[i], stream);
+ if (i < heap->size - 1)
+ fputc(',', stream);
+ }
+ fputc(']', stream);
+}
\ No newline at end of file
diff --git a/src/polynomial/polynomial_vector.c b/src/polynomial/polynomial_vector.c
index 0de1ffb7..802bd184 100644
--- a/src/polynomial/polynomial_vector.c
+++ b/src/polynomial/polynomial_vector.c
@@ -19,6 +19,7 @@
#include "polynomial_vector.h"
#include "polynomial.h"
+#include "output.h"
#include "polynomial/gcd.h"
@@ -32,6 +33,19 @@ lp_polynomial_vector_t* lp_polynomial_vector_new(const lp_polynomial_context_t*
return result;
}
+lp_polynomial_vector_t* lp_polynomial_vector_copy(const lp_polynomial_vector_t *v) {
+ lp_polynomial_vector_t* result = (lp_polynomial_vector_t*) malloc(sizeof(lp_polynomial_vector_t));
+ // copy all fields
+ *result = *v;
+ // deep copy of data
+ result->data = (coefficient_t*) malloc(v->capacity * sizeof(coefficient_t));
+ for (size_t i = 0; i < v->size; ++i) {
+ coefficient_construct_copy(result->ctx, result->data + i, v->data + i);
+ }
+ lp_polynomial_context_attach((lp_polynomial_context_t*)result->ctx);
+ return result;
+}
+
void lp_polynomial_vector_delete(lp_polynomial_vector_t* v) {
lp_polynomial_vector_destruct(v);
free(v);
@@ -51,6 +65,14 @@ void lp_polynomial_vector_destruct(lp_polynomial_vector_t* v) {
lp_polynomial_context_detach((lp_polynomial_context_t*)v->ctx);
}
+const lp_polynomial_context_t* lp_polynomial_vector_get_context(const lp_polynomial_vector_t *v) {
+ return v->ctx;
+}
+
+void lp_polynomial_vector_swap(lp_polynomial_vector_t *v1, lp_polynomial_vector_t *v2) {
+ lp_polynomial_vector_t tmp = *v1; *v1 = *v2; *v2 = tmp;
+}
+
static inline
void lp_polynomial_vector_check_size_for_add(lp_polynomial_vector_t* v) {
if (v->size == v->capacity) {
@@ -66,6 +88,15 @@ void lp_polynomial_vector_push_back(lp_polynomial_vector_t* v, const lp_polynomi
v->size ++;
}
+void lp_polynomial_vector_push_back_move(lp_polynomial_vector_t* v, lp_polynomial_t* p) {
+ assert(lp_polynomial_context_equal(v->ctx, p->ctx));
+ lp_polynomial_vector_check_size_for_add(v);
+ coefficient_t *v_p = v->data + v->size;
+ coefficient_construct_from_int(v->ctx, v_p, 0);
+ coefficient_swap(&p->data, v_p);
+ v->size ++;
+}
+
void lp_polynomial_vector_push_back_coeff(lp_polynomial_vector_t* v, const coefficient_t* C) {
lp_polynomial_vector_check_size_for_add(v);
coefficient_construct_copy(v->ctx, v->data + v->size, C);
@@ -73,7 +104,7 @@ void lp_polynomial_vector_push_back_coeff(lp_polynomial_vector_t* v, const coeff
}
void lp_polynomial_vector_reset(lp_polynomial_vector_t* v) {
- size_t i = 0;
+ size_t i;
for (i = 0; i < v->size; ++ i) {
coefficient_destruct(v->data + i);
}
@@ -88,6 +119,17 @@ lp_polynomial_t* lp_polynomial_vector_at(const lp_polynomial_vector_t* v, size_t
return lp_polynomial_new_from_coefficient(v->ctx, v->data + i);
}
+void lp_polynomial_vector_print(const lp_polynomial_vector_t* v, FILE* out) {
+ fputc('[', out);
+ size_t i;
+ for (i = 0; i < v->size; ++ i) {
+ coefficient_print(v->ctx, v->data + i, out);
+ if (i != v->size - 1)
+ fputc(',', out);
+ }
+ fputc(']', out);
+}
+
void lp_polynomial_vector_push_back_coeff_prime(lp_polynomial_vector_t* v, const coefficient_t* C) {
size_t old_size = v->size;
diff --git a/src/upolynomial/upolynomial.c b/src/upolynomial/upolynomial.c
index 57a67818..cbf048ed 100644
--- a/src/upolynomial/upolynomial.c
+++ b/src/upolynomial/upolynomial.c
@@ -31,11 +31,11 @@
#include
#include
-#include
-#include
#include "upolynomial/upolynomial.h"
+#include
+
size_t lp_upolynomial_degree(const lp_upolynomial_t* p) {
assert(p);
assert(p->size > 0);
@@ -43,6 +43,7 @@ size_t lp_upolynomial_degree(const lp_upolynomial_t* p) {
}
// Construct the polynomial, but don't construct monomials
+static
lp_upolynomial_t* lp_upolynomial_construct_empty(const lp_int_ring_t* K, size_t size) {
size_t malloc_size = sizeof(lp_upolynomial_t) + size*sizeof(ulp_monomial_t);
lp_upolynomial_t* new_p = (lp_upolynomial_t*) malloc(malloc_size);
@@ -1206,3 +1207,22 @@ lp_upolynomial_t* lp_upolynomial_subst_x_neg(const lp_upolynomial_t* f) {
return neg;
}
+
+lp_polynomial_t* lp_upolynomial_to_polynomial(const lp_upolynomial_t* p, const lp_polynomial_context_t* ctx, lp_variable_t var) {
+ assert(p);
+ assert(lp_int_ring_equal(p->K, ctx->K));
+
+ lp_polynomial_t *poly = lp_polynomial_new(ctx);
+
+ lp_monomial_t mono;
+ lp_monomial_construct(ctx, &mono);
+ for (size_t i = 0; i < p->size; ++i) {
+ lp_monomial_set_coefficient(ctx, &mono, &p->monomials[i].coefficient);
+ lp_monomial_push(&mono, var, p->monomials[i].degree);
+ lp_polynomial_add_monomial(poly, &mono);
+ lp_monomial_clear(ctx, &mono);
+ }
+ lp_monomial_destruct(&mono);
+
+ return poly;
+}