diff --git a/CMakeLists.txt b/CMakeLists.txt
index 33790c79..ec4b2af2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.12)
#
# Stop warning on cygwin
@@ -67,16 +67,11 @@ add_subdirectory(src)
add_subdirectory(include)
if(LIBPOLY_BUILD_PYTHON_API)
-
- # Need the Python binary to run tests
- find_package(PythonInterp)
-
+ find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
# Configure the Python bindings
add_subdirectory(python)
-
# Configure the Python tests
add_subdirectory(test/python)
-
endif()
if (BUILD_TESTING)
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index aa57fcd7..19facb62 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -13,18 +13,19 @@ set(polypy_SOURCES
polypyFeasibilitySet.c
)
-find_package(PythonLibs)
-
include_directories(${GMP_INCLUDE_DIR})
include_directories(${libpoly_SOURCE_DIR}/include)
-include_directories(${PYTHON_INCLUDE_PATH})
add_library(polypy MODULE ${polypy_SOURCES})
+target_include_directories(polypy PRIVATE ${Python3_INCLUDE_DIRS})
+target_link_libraries(polypy PRIVATE poly ${Python3_LIBRARIES})
+
set_target_properties(polypy PROPERTIES PREFIX "")
+#set_target_properties(polypy PROPERTIES SUFFIX "${Python3_EXTENSION_SUFFIX}")
+
if (APPLE)
set_target_properties(polypy PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
endif()
-target_link_libraries(polypy poly)
string (REPLACE ";" "', '" polypy_SOURCES_STR "${polypy_SOURCES}")
configure_file(setup.py.in ${CMAKE_CURRENT_SOURCE_DIR}/setup.py)
diff --git a/python/polypy.c b/python/polypy.c
index 2bd880f9..89fd7ac6 100644
--- a/python/polypy.c
+++ b/python/polypy.c
@@ -17,11 +17,172 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include "Python.h"
+#include "python.h"
-#if PY_MAJOR_VERSION >= 3
-#include "polypy3.c"
-#else
-#include "polypy2.c"
+#include "polypyInteger.h"
+#include "polypyVariable.h"
+#include "polypyVariableOrder.h"
+#include "polypyUPolynomial.h"
+#include "polypyAlgebraicNumber.h"
+#include "polypyPolynomial.h"
+#include "polypyAssignment.h"
+#include "polypyValue.h"
+#include "polypyInterval.h"
+#include "polypyFeasibilitySet.h"
+
+static PyObject*
+Trace_enable(PyObject* self, PyObject* args) {
+#ifndef NDEBUG
+ const char *tag;
+ if (!PyArg_ParseTuple(args, "s", &tag)) {
+ return NULL;
+ }
+ lp_trace_enable(tag);
+#endif
+ Py_RETURN_NONE;
+}
+
+static PyObject*
+Trace_disable(PyObject* self, PyObject* args) {
+#ifndef NDEBUG
+ const char *tag;
+ if (!PyArg_ParseTuple(args, "s", &tag)) {
+ return NULL;
+ }
+ lp_trace_disable(tag);
+#endif
+ Py_RETURN_NONE;
+}
+
+static PyObject*
+Stats_print(PyObject* self) {
+ lp_stats_print(stdout);
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef polypy_methods[] = {
+ {"trace_enable", (PyCFunction)Trace_enable, METH_VARARGS, "Enables tracing for the given tag"},
+ {"trace_disable", (PyCFunction)Trace_disable, METH_VARARGS, "Disables tracing for the given tag"},
+ {"stats_print", (PyCFunction)Stats_print, METH_NOARGS, "Prints the statistics"},
+ {NULL} /* Sentinel */
+};
+
+
+static struct PyModuleDef polypymodule = {
+ PyModuleDef_HEAD_INIT,
+ "polypy",
+ NULL,
+ 0, // sizeof polypy struct
+ polypy_methods,
+ NULL,
+ NULL,
+ NULL
+};
+
+#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
#endif
+PyMODINIT_FUNC
+PyInit_polypy(void)
+{
+ PyObject* m;
+
+ if (PyType_Ready(&CoefficientRingType) < 0)
+ return NULL;
+ if (PyType_Ready(&VariableType) < 0)
+ return NULL;
+ if (PyType_Ready(&VariableOrderType) < 0)
+ return NULL;
+ if (PyType_Ready(&AssignmentType) < 0)
+ return NULL;
+ if (PyType_Ready(&PolynomialType) < 0)
+ return NULL;
+ if (PyType_Ready(&UPolynomialType) < 0)
+ return NULL;
+ if (PyType_Ready(&AlgebraicNumberType) < 0)
+ return NULL;
+ if (PyType_Ready(&ValueType) < 0)
+ return NULL;
+ if (PyType_Ready(&IntervalType) < 0)
+ return NULL;
+ if (PyType_Ready(&FeasibilitySetType) < 0)
+ return NULL;
+
+ m = PyModule_Create(&polypymodule);
+
+ // Initialize the library
+ lp_set_output_language(LP_OUTPUT_PYTHON);
+
+ Py_INCREF(&CoefficientRingType);
+ PyModule_AddObject(m, "CoefficientRing", (PyObject*)&CoefficientRingType);
+
+ PyObject* PyZ = PyCoefficientRing_create(lp_Z);
+ Py_INCREF(PyZ);
+ PyModule_AddObject(m, "Z", PyZ);
+
+ Py_INCREF(&VariableType);
+ PyModule_AddObject(m, "Variable", (PyObject*)&VariableType);
+
+ Py_INCREF(&VariableOrderType);
+ PyModule_AddObject(m, "VariableOrder", (PyObject*)&VariableOrderType);
+
+ PyObject* variable_order = VariableOrder_create(VariableOrder_get_default_order());
+ Py_INCREF(variable_order);
+ PyModule_AddObject(m, "variable_order", variable_order);
+
+ Py_INCREF(&PolynomialType);
+ PyModule_AddObject(m, "Polynomial", (PyObject*)&PolynomialType);
+
+ // Sign conditions
+ PyObject* Py_SGN_LT_0 = PyLong_FromLong(LP_SGN_LT_0);
+ PyObject* Py_SGN_LE_0 = PyLong_FromLong(LP_SGN_LE_0);
+ PyObject* Py_SGN_EQ_0 = PyLong_FromLong(LP_SGN_EQ_0);
+ PyObject* Py_SGN_NE_0 = PyLong_FromLong(LP_SGN_NE_0);
+ PyObject* Py_SGN_GT_0 = PyLong_FromLong(LP_SGN_GT_0);
+ PyObject* Py_SGN_GE_0 = PyLong_FromLong(LP_SGN_GE_0);
+ PyModule_AddObject(m, "SGN_LT_0", Py_SGN_LT_0);
+ PyModule_AddObject(m, "SGN_LE_0", Py_SGN_LE_0);
+ PyModule_AddObject(m, "SGN_EQ_0", Py_SGN_EQ_0);
+ PyModule_AddObject(m, "SGN_NE_0", Py_SGN_NE_0);
+ PyModule_AddObject(m, "SGN_GT_0", Py_SGN_GT_0);
+ PyModule_AddObject(m, "SGN_GE_0", Py_SGN_GE_0);
+
+ Py_INCREF(&AssignmentType);
+ PyModule_AddObject(m, "Assignment", (PyObject*)&AssignmentType);
+
+ Py_INCREF(&UPolynomialType);
+ PyModule_AddObject(m, "UPolynomial", (PyObject*)&UPolynomialType);
+
+ int x_coeff[2] = { 0, 1 };
+ lp_upolynomial_t* x_poly = lp_upolynomial_construct_from_int(lp_Z, 1, x_coeff);
+ PyObject* x = PyUPolynomial_create(x_poly);
+ Py_INCREF(x);
+ PyModule_AddObject(m, "x", x);
+
+ Py_INCREF(&AlgebraicNumberType);
+ PyModule_AddObject(m, "AlgebraicNumber", (PyObject*)&AlgebraicNumberType);
+
+ Py_INCREF(&ValueType);
+ PyModule_AddObject(m, "Value", (PyObject*)&ValueType);
+
+ // Sign conditions
+ lp_value_t value_inf_pos, value_inf_neg;
+ lp_value_construct(&value_inf_pos, LP_VALUE_PLUS_INFINITY, NULL);
+ lp_value_construct(&value_inf_neg, LP_VALUE_MINUS_INFINITY, NULL);
+ PyObject* inf_pos = PyValue_create(&value_inf_pos);
+ PyObject* inf_neg = PyValue_create(&value_inf_neg);
+ PyModule_AddObject(m, "INFINITY_POS", inf_pos);
+ PyModule_AddObject(m, "INFINITY_NEG", inf_neg);
+ Py_INCREF(inf_pos);
+ Py_INCREF(inf_neg);
+ lp_value_destruct(&value_inf_pos);
+ lp_value_destruct(&value_inf_neg);
+
+ Py_INCREF(&IntervalType);
+ PyModule_AddObject(m, "Interval", (PyObject*)&IntervalType);
+
+ Py_INCREF(&FeasibilitySetType);
+ PyModule_AddObject(m, "FeasibilitySet", (PyObject*)&FeasibilitySetType);
+
+ return m;
+}
diff --git a/python/polypy2.c b/python/polypy2.c
deleted file mode 100644
index 6fabdce2..00000000
--- a/python/polypy2.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/**
- * 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 "polypyInteger.h"
-#include "polypyVariable.h"
-#include "polypyVariableOrder.h"
-#include "polypyUPolynomial.h"
-#include "polypyAlgebraicNumber.h"
-#include "polypyPolynomial.h"
-#include "polypyAssignment.h"
-#include "polypyValue.h"
-#include "polypyInterval.h"
-#include "polypyFeasibilitySet.h"
-
-static PyObject*
-Trace_enable(PyObject* self, PyObject* args) {
-#ifndef NDEBUG
- const char *tag;
- if (!PyArg_ParseTuple(args, "s", &tag)) {
- return 0;
- }
- lp_trace_enable(tag);
-#endif
- Py_RETURN_NONE;
-}
-
-static PyObject*
-Trace_disable(PyObject* self, PyObject* args) {
-#ifndef NDEBUG
- const char *tag;
- if (!PyArg_ParseTuple(args, "s", &tag)) {
- return 0;
- }
- lp_trace_disable(tag);
-#endif
- Py_RETURN_NONE;
-}
-
-static PyObject*
-Stats_print(PyObject* self) {
- lp_stats_print(stdout);
- Py_RETURN_NONE;
-}
-
-static PyMethodDef polypy_methods[] = {
- {"trace_enable", (PyCFunction)Trace_enable, METH_VARARGS, "Enables tracing for the given tag"},
- {"trace_disable", (PyCFunction)Trace_disable, METH_VARARGS, "Disables tracing for the given tag"},
- {"stats_print", (PyCFunction)Stats_print, METH_NOARGS, "Prints the statistics"},
- {NULL} /* Sentinel */
-};
-
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC
-initpolypy(void)
-{
- PyObject* m;
-
- if (PyType_Ready(&CoefficientRingType) < 0)
- return;
- if (PyType_Ready(&VariableType) < 0)
- return;
- if (PyType_Ready(&VariableOrderType) < 0)
- return;
- if (PyType_Ready(&AssignmentType) < 0)
- return;
- if (PyType_Ready(&PolynomialType) < 0)
- return;
- if (PyType_Ready(&UPolynomialType) < 0)
- return;
- if (PyType_Ready(&AlgebraicNumberType) < 0)
- return;
- if (PyType_Ready(&ValueType) < 0)
- return;
- if (PyType_Ready(&IntervalType) < 0)
- return;
- if (PyType_Ready(&FeasibilitySetType) < 0)
- return;
-
- m = Py_InitModule3("polypy", polypy_methods, "PolyPy Library.");
-
- // Initialize the library
- lp_set_output_language(LP_OUTPUT_PYTHON);
-
- Py_INCREF(&CoefficientRingType);
- PyModule_AddObject(m, "CoefficientRing", (PyObject*)&CoefficientRingType);
-
- PyObject* PyZ = PyCoefficientRing_create(lp_Z);
- Py_INCREF(PyZ);
- PyModule_AddObject(m, "Z", PyZ);
-
- Py_INCREF(&VariableType);
- PyModule_AddObject(m, "Variable", (PyObject*)&VariableType);
-
- Py_INCREF(&VariableOrderType);
- PyModule_AddObject(m, "VariableOrder", (PyObject*)&VariableOrderType);
-
- PyObject* variable_order = VariableOrder_create(VariableOrder_get_default_order());
- Py_INCREF(variable_order);
- PyModule_AddObject(m, "variable_order", variable_order);
-
- Py_INCREF(&PolynomialType);
- PyModule_AddObject(m, "Polynomial", (PyObject*)&PolynomialType);
-
- // Sign conditions
- PyObject* Py_SGN_LT_0 = PyInt_FromLong(LP_SGN_LT_0);
- PyObject* Py_SGN_LE_0 = PyInt_FromLong(LP_SGN_LE_0);
- PyObject* Py_SGN_EQ_0 = PyInt_FromLong(LP_SGN_EQ_0);
- PyObject* Py_SGN_NE_0 = PyInt_FromLong(LP_SGN_NE_0);
- PyObject* Py_SGN_GT_0 = PyInt_FromLong(LP_SGN_GT_0);
- PyObject* Py_SGN_GE_0 = PyInt_FromLong(LP_SGN_GE_0);
- PyModule_AddObject(m, "SGN_LT_0", Py_SGN_LT_0);
- PyModule_AddObject(m, "SGN_LE_0", Py_SGN_LE_0);
- PyModule_AddObject(m, "SGN_EQ_0", Py_SGN_EQ_0);
- PyModule_AddObject(m, "SGN_NE_0", Py_SGN_NE_0);
- PyModule_AddObject(m, "SGN_GT_0", Py_SGN_GT_0);
- PyModule_AddObject(m, "SGN_GE_0", Py_SGN_GE_0);
-
- Py_INCREF(&AssignmentType);
- PyModule_AddObject(m, "Assignment", (PyObject*)&AssignmentType);
-
- Py_INCREF(&UPolynomialType);
- PyModule_AddObject(m, "UPolynomial", (PyObject*)&UPolynomialType);
-
- int x_coeff[2] = { 0, 1 };
- lp_upolynomial_t* x_poly = lp_upolynomial_construct_from_int(lp_Z, 1, x_coeff);
- PyObject* x = PyUPolynomial_create(x_poly);
- Py_INCREF(x);
- PyModule_AddObject(m, "x", x);
-
- Py_INCREF(&AlgebraicNumberType);
- PyModule_AddObject(m, "AlgebraicNumber", (PyObject*)&AlgebraicNumberType);
-
- Py_INCREF(&ValueType);
- PyModule_AddObject(m, "Value", (PyObject*)&ValueType);
-
- // Sign conditions
- lp_value_t value_inf_pos, value_inf_neg;
- lp_value_construct(&value_inf_pos, LP_VALUE_PLUS_INFINITY, NULL);
- lp_value_construct(&value_inf_neg, LP_VALUE_MINUS_INFINITY, NULL);
- PyObject* inf_pos = PyValue_create(&value_inf_pos);
- PyObject* inf_neg = PyValue_create(&value_inf_neg);
- PyModule_AddObject(m, "INFINITY_POS", inf_pos);
- PyModule_AddObject(m, "INFINITY_NEG", inf_neg);
- Py_INCREF(inf_pos);
- Py_INCREF(inf_neg);
- lp_value_destruct(&value_inf_pos);
- lp_value_destruct(&value_inf_neg);
-
- Py_INCREF(&IntervalType);
- PyModule_AddObject(m, "Interval", (PyObject*)&IntervalType);
-
- Py_INCREF(&FeasibilitySetType);
- PyModule_AddObject(m, "FeasibilitySet", (PyObject*)&FeasibilitySetType);
-}
diff --git a/python/polypy3.c b/python/polypy3.c
deleted file mode 100644
index 0bbcf75d..00000000
--- a/python/polypy3.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/**
- * 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 "polypyInteger.h"
-#include "polypyVariable.h"
-#include "polypyVariableOrder.h"
-#include "polypyUPolynomial.h"
-#include "polypyAlgebraicNumber.h"
-#include "polypyPolynomial.h"
-#include "polypyAssignment.h"
-#include "polypyValue.h"
-#include "polypyInterval.h"
-#include "polypyFeasibilitySet.h"
-
-static PyObject*
-Trace_enable(PyObject* self, PyObject* args) {
-#ifndef NDEBUG
- const char *tag;
- if (!PyArg_ParseTuple(args, "s", &tag)) {
- return 0;
- }
- lp_trace_enable(tag);
-#endif
- Py_RETURN_NONE;
-}
-
-static PyObject*
-Trace_disable(PyObject* self, PyObject* args) {
-#ifndef NDEBUG
- const char *tag;
- if (!PyArg_ParseTuple(args, "s", &tag)) {
- return 0;
- }
- lp_trace_disable(tag);
-#endif
- Py_RETURN_NONE;
-}
-
-static PyObject*
-Stats_print(PyObject* self) {
- lp_stats_print(stdout);
- Py_RETURN_NONE;
-}
-
-static PyMethodDef polypy_methods[] = {
- {"trace_enable", (PyCFunction)Trace_enable, METH_VARARGS, "Enables tracing for the given tag"},
- {"trace_disable", (PyCFunction)Trace_disable, METH_VARARGS, "Disables tracing for the given tag"},
- {"stats_print", (PyCFunction)Stats_print, METH_NOARGS, "Prints the statistics"},
- {NULL} /* Sentinel */
-};
-
-
-static struct PyModuleDef polypymodule = {
- PyModuleDef_HEAD_INIT,
- "polypy",
- NULL,
- 0, // sizeof polypy struct
- polypy_methods,
- 0,
- 0,
- 0
-};
-
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-PyMODINIT_FUNC
-PyInit_polypy(void)
-{
- PyObject* m;
-
- if (PyType_Ready(&CoefficientRingType) < 0)
- return NULL;
- if (PyType_Ready(&VariableType) < 0)
- return NULL;
- if (PyType_Ready(&VariableOrderType) < 0)
- return NULL;
- if (PyType_Ready(&AssignmentType) < 0)
- return NULL;
- if (PyType_Ready(&PolynomialType) < 0)
- return NULL;
- if (PyType_Ready(&UPolynomialType) < 0)
- return NULL;
- if (PyType_Ready(&AlgebraicNumberType) < 0)
- return NULL;
- if (PyType_Ready(&ValueType) < 0)
- return NULL;
- if (PyType_Ready(&IntervalType) < 0)
- return NULL;
- if (PyType_Ready(&FeasibilitySetType) < 0)
- return NULL;
-
- m = PyModule_Create(&polypymodule);
-
- // Initialize the library
- lp_set_output_language(LP_OUTPUT_PYTHON);
-
- Py_INCREF(&CoefficientRingType);
- PyModule_AddObject(m, "CoefficientRing", (PyObject*)&CoefficientRingType);
-
- PyObject* PyZ = PyCoefficientRing_create(lp_Z);
- Py_INCREF(PyZ);
- PyModule_AddObject(m, "Z", PyZ);
-
- Py_INCREF(&VariableType);
- PyModule_AddObject(m, "Variable", (PyObject*)&VariableType);
-
- Py_INCREF(&VariableOrderType);
- PyModule_AddObject(m, "VariableOrder", (PyObject*)&VariableOrderType);
-
- PyObject* variable_order = VariableOrder_create(VariableOrder_get_default_order());
- Py_INCREF(variable_order);
- PyModule_AddObject(m, "variable_order", variable_order);
-
- Py_INCREF(&PolynomialType);
- PyModule_AddObject(m, "Polynomial", (PyObject*)&PolynomialType);
-
- // Sign conditions
- PyObject* Py_SGN_LT_0 = PyLong_FromLong(LP_SGN_LT_0);
- PyObject* Py_SGN_LE_0 = PyLong_FromLong(LP_SGN_LE_0);
- PyObject* Py_SGN_EQ_0 = PyLong_FromLong(LP_SGN_EQ_0);
- PyObject* Py_SGN_NE_0 = PyLong_FromLong(LP_SGN_NE_0);
- PyObject* Py_SGN_GT_0 = PyLong_FromLong(LP_SGN_GT_0);
- PyObject* Py_SGN_GE_0 = PyLong_FromLong(LP_SGN_GE_0);
- PyModule_AddObject(m, "SGN_LT_0", Py_SGN_LT_0);
- PyModule_AddObject(m, "SGN_LE_0", Py_SGN_LE_0);
- PyModule_AddObject(m, "SGN_EQ_0", Py_SGN_EQ_0);
- PyModule_AddObject(m, "SGN_NE_0", Py_SGN_NE_0);
- PyModule_AddObject(m, "SGN_GT_0", Py_SGN_GT_0);
- PyModule_AddObject(m, "SGN_GE_0", Py_SGN_GE_0);
-
- Py_INCREF(&AssignmentType);
- PyModule_AddObject(m, "Assignment", (PyObject*)&AssignmentType);
-
- Py_INCREF(&UPolynomialType);
- PyModule_AddObject(m, "UPolynomial", (PyObject*)&UPolynomialType);
-
- int x_coeff[2] = { 0, 1 };
- lp_upolynomial_t* x_poly = lp_upolynomial_construct_from_int(lp_Z, 1, x_coeff);
- PyObject* x = PyUPolynomial_create(x_poly);
- Py_INCREF(x);
- PyModule_AddObject(m, "x", x);
-
- Py_INCREF(&AlgebraicNumberType);
- PyModule_AddObject(m, "AlgebraicNumber", (PyObject*)&AlgebraicNumberType);
-
- Py_INCREF(&ValueType);
- PyModule_AddObject(m, "Value", (PyObject*)&ValueType);
-
- // Sign conditions
- lp_value_t value_inf_pos, value_inf_neg;
- lp_value_construct(&value_inf_pos, LP_VALUE_PLUS_INFINITY, NULL);
- lp_value_construct(&value_inf_neg, LP_VALUE_MINUS_INFINITY, NULL);
- PyObject* inf_pos = PyValue_create(&value_inf_pos);
- PyObject* inf_neg = PyValue_create(&value_inf_neg);
- PyModule_AddObject(m, "INFINITY_POS", inf_pos);
- PyModule_AddObject(m, "INFINITY_NEG", inf_neg);
- Py_INCREF(inf_pos);
- Py_INCREF(inf_neg);
- lp_value_destruct(&value_inf_pos);
- lp_value_destruct(&value_inf_neg);
-
- Py_INCREF(&IntervalType);
- PyModule_AddObject(m, "Interval", (PyObject*)&IntervalType);
-
- Py_INCREF(&FeasibilitySetType);
- PyModule_AddObject(m, "FeasibilitySet", (PyObject*)&FeasibilitySetType);
-
- return m;
-}
diff --git a/python/polypyAlgebraicNumber.c b/python/polypyAlgebraicNumber.c
index dbaf74db..6b1f1b85 100644
--- a/python/polypyAlgebraicNumber.c
+++ b/python/polypyAlgebraicNumber.c
@@ -17,13 +17,447 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include "Python.h"
+#include "python.h"
-#if PY_MAJOR_VERSION >= 3
- #include "polypyAlgebraicNumber3.c"
-#else
- #include "polypyAlgebraicNumber2.c"
-#endif
+#include "polypyAlgebraicNumber.h"
+#include "polypyUPolynomial.h"
+#include "polypyPolynomial.h"
+#include
+static void
+AlgebraicNumber_dealloc(AlgebraicNumber* self);
+
+static PyObject*
+AlgebraicNumber_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static int
+AlgebraicNumber_init(AlgebraicNumber* self, PyObject* args);
+
+static PyObject*
+AlgebraicNumber_to_double(PyObject* self);
+
+static PyObject*
+AlgebraicNumber_richcompare(PyObject* self, PyObject* other, int op);
+
+static PyObject*
+AlgebraicNumber_str(PyObject* self);
+
+static PyObject*
+AlgebraicNumber_refine(PyObject* self);
+
+static PyObject*
+AlgebraicNumber_add(PyObject* self, PyObject* other);
+
+static PyObject*
+AlgebraicNumber_neg(PyObject* self);
+
+static PyObject*
+AlgebraicNumber_sub(PyObject* self, PyObject* other);
+
+static PyObject*
+AlgebraicNumber_mul(PyObject* self, PyObject* other);
+
+static PyObject*
+AlgebraicNumber_div(PyObject* self, PyObject* other);
+
+static PyObject*
+AlgebraicNumber_pow(PyObject* self, PyObject* other);
+
+static PyObject*
+AlgebraicNumber_positive_root(PyObject* self, PyObject* args);
+
+PyMethodDef AlgebraicNumber_methods[] = {
+ {"refine", (PyCFunction)AlgebraicNumber_refine, METH_NOARGS, "Refines the number to half the interval"},
+ {"to_double", (PyCFunction)AlgebraicNumber_to_double, METH_NOARGS, "Returns the approximation of the algebraic number"},
+ {"positive_root", (PyCFunction)AlgebraicNumber_positive_root, METH_VARARGS, "Returns the positive root of the number is positive"},
+ {NULL} /* Sentinel */
+};
+
+PyNumberMethods AlgebraicNumber_NumberMethods = {
+ AlgebraicNumber_add, // binaryfunc nb_add;
+ AlgebraicNumber_sub, // binaryfunc nb_subtract;
+ AlgebraicNumber_mul, // binaryfunc nb_multiply;
+ NULL, // binaryfunc nb_remainder;
+ NULL, // binaryfunc nb_divmod;
+ (ternaryfunc)AlgebraicNumber_pow, // ternaryfunc nb_power;
+ AlgebraicNumber_neg, // unaryfunc nb_negative;
+ NULL, // unaryfunc nb_positive;
+ NULL, // unaryfunc nb_absolute;
+ NULL, // inquiry nb_bool;
+ NULL, // unaryfunc nb_invert;
+ NULL, // binaryfunc nb_lshift;
+ NULL, // binaryfunc nb_rshift;
+ NULL, // binaryfunc nb_and;
+ NULL, // binaryfunc nb_xor;
+ NULL, // binaryfunc nb_or;
+ NULL, // unaryfunc nb_int;
+ NULL, // void *nb_reserved;
+ NULL, // unaryfunc nb_float;
+ NULL, // binaryfunc nb_inplace_add;
+ NULL, // binaryfunc nb_inplace_subtract;
+ NULL, // binaryfunc nb_inplace_multiply;
+ NULL, // binaryfunc nb_inplace_remainder;
+ NULL, // ternaryfunc nb_inplace_power;
+ NULL, // binaryfunc nb_inplace_lshift;
+ NULL, // binaryfunc nb_inplace_rshift;
+ NULL, // binaryfunc nb_inplace_and;
+ NULL, // binaryfunc nb_inplace_xor;
+ NULL, // binaryfunc nb_inplace_or;
+ NULL, // binaryfunc nb_floor_divide;
+ AlgebraicNumber_div, // binaryfunc nb_true_divide;
+ NULL, // binaryfunc nb_inplace_floor_divide;
+ NULL, // binaryfunc nb_inplace_true_divide;
+ NULL, // unaryfunc nb_index;
+ NULL, // binaryfunc nb_matrix_multiply;
+ NULL, // binaryfunc nb_inplace_matrix_multiply;
+};
+
+PyTypeObject AlgebraicNumberType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.AlgebraicNumber", // const char *tp_name;
+ sizeof(AlgebraicNumber), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)AlgebraicNumber_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async
+ AlgebraicNumber_str, // reprfunc tp_repr;
+ &AlgebraicNumber_NumberMethods, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ NULL, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ AlgebraicNumber_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "Algebraic number objects", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ AlgebraicNumber_richcompare, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ AlgebraicNumber_methods, // struct PyMethodDef *tp_methods;
+ NULL, // struct PyMemberDef *tp_members;
+ NULL, // struct PyGetSetDef *tp_getset;
+ NULL, // struct _typeobject *tp_base;
+ NULL, // PyObject *tp_dict;
+ NULL, // descrgetfunc tp_descr_get;
+ NULL, // descrsetfunc tp_descr_set;
+ 0, // Py_ssize_t tp_dictoffset;
+ (initproc)AlgebraicNumber_init, // initproc tp_init;
+ NULL, // Pallocfunc tp_alloc;
+ AlgebraicNumber_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+static void
+AlgebraicNumber_dealloc(AlgebraicNumber* self)
+{
+ lp_algebraic_number_destruct(&self->a);
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+PyObject*
+PyAlgebraicNumber_create(const lp_algebraic_number_t* a) {
+ AlgebraicNumber *self;
+ self = (AlgebraicNumber*)AlgebraicNumberType.tp_alloc(&AlgebraicNumberType, 0);
+ if (self != NULL) {
+ if (a) {
+ lp_algebraic_number_construct_copy(&self->a, a);
+ } else {
+ lp_dyadic_rational_t zero;
+ lp_dyadic_rational_construct(&zero);
+ lp_algebraic_number_construct_from_dyadic_rational(&self->a, &zero);
+ lp_dyadic_rational_destruct(&zero);
+ }
+ }
+ return (PyObject *)self;
+}
+
+static PyObject*
+AlgebraicNumber_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return PyAlgebraicNumber_create(NULL);
+}
+
+/** Construct an algebraic number from a polynomial and a root index */
+static int
+AlgebraicNumber_init(AlgebraicNumber* self, PyObject* args)
+{
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 2) {
+ PyObject* f_obj = PyTuple_GetItem(args, 0);
+ PyObject* root_index_obj = PyTuple_GetItem(args, 1);
+ if (PyPolynomial_CHECK(f_obj) && PyLong_Check(root_index_obj)) {
+ // Get the polynomial
+ lp_polynomial_t* f = ((Polynomial*) f_obj)->p;
+ long root_index = PyLong_AsLong(root_index_obj);
+ // Get the univariate polynomial
+ lp_upolynomial_t* f_u = lp_polynomial_to_univariate(f);
+ if (f_u == NULL) {
+ // Not univariate
+ return -1;
+ }
+ // Check the roots
+ size_t roots_count = lp_upolynomial_roots_count(f_u, NULL);
+ if (root_index < 0 || root_index >= (long)roots_count) {
+ // Not enough roots
+ lp_upolynomial_delete(f_u);
+ return -1;
+ }
+ lp_algebraic_number_t* roots = malloc(roots_count * sizeof(lp_algebraic_number_t));
+ lp_upolynomial_roots_isolate(f_u, roots, &roots_count);
+ lp_algebraic_number_destruct(&self->a);
+ lp_algebraic_number_construct_copy(&self->a, roots + root_index);
+ for (size_t i = 0; i < roots_count; ++ i) {
+ lp_algebraic_number_destruct(roots + i);
+ }
+ lp_upolynomial_delete(f_u);
+ free(roots);
+ } else if (PyUPolynomial_CHECK(f_obj) && PyLong_Check(root_index_obj)) {
+ lp_upolynomial_t* f = ((UPolynomialObject*) f_obj)->p;
+ long root_index = PyLong_AsLong(root_index_obj);
+ size_t roots_count = lp_upolynomial_roots_count(f, NULL);
+ if (root_index < 0 || root_index >= (long)roots_count) {
+ // Not enough roots
+ return -1;
+ }
+ lp_algebraic_number_t* roots = malloc(roots_count * sizeof(lp_algebraic_number_t));
+ lp_upolynomial_roots_isolate(f, roots, &roots_count);
+ lp_algebraic_number_destruct(&self->a);
+ lp_algebraic_number_construct_copy(&self->a, roots + root_index);
+ for (size_t i = 0; i < roots_count; ++i) {
+ lp_algebraic_number_destruct(roots + i);
+ }
+ free(roots);
+ } else{
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+
+ // All fine, initialized
+ return 0;
+}
+
+static PyObject*
+AlgebraicNumber_to_double(PyObject* self) {
+ AlgebraicNumber* a = (AlgebraicNumber*) self;
+ return algebraic_number_to_PyFloat(&a->a);
+}
+
+static PyObject*
+AlgebraicNumber_refine(PyObject* self) {
+ AlgebraicNumber* a = (AlgebraicNumber*) self;
+ lp_algebraic_number_refine(&a->a);
+ Py_RETURN_NONE;
+}
+
+static PyObject*
+AlgebraicNumber_richcompare(PyObject* self, PyObject* other, int op) {
+ PyObject *result = NULL;
+
+ if (!PyAlgebraicNumber_CHECK(other)) {
+ result = Py_NotImplemented;
+ } else {
+ lp_algebraic_number_t* self_a = &((AlgebraicNumber*) self)->a;
+ lp_algebraic_number_t* other_a = &((AlgebraicNumber*) other)->a;
+ int cmp = lp_algebraic_number_cmp(self_a, other_a);
+
+ switch (op) {
+ case Py_LT:
+ result = cmp < 0 ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ result = cmp <= 0 ? Py_True : Py_False;
+ break;
+ case Py_EQ:
+ result = cmp == 0 ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = cmp != 0 ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ result = cmp > 0 ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ result = cmp >= 0 ? Py_True : Py_False;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ Py_INCREF(result);
+ return result;
+}
+
+static PyObject* AlgebraicNumber_str(PyObject* self) {
+ AlgebraicNumber* a = (AlgebraicNumber*) self;
+ char* cstr = lp_algebraic_number_to_string(&a->a);
+ PyObject* pystr = PyUnicode_FromString(cstr);
+ free(cstr);
+ return pystr;
+}
+
+static PyObject*
+AlgebraicNumber_add(PyObject* self, PyObject* other) {
+
+ if (PyLong_Check(self)) {
+ // To enable summation
+ long x = PyLong_AsLong(self);
+ if (x == 0) {
+ AlgebraicNumber* a = (AlgebraicNumber*) other;
+ return PyAlgebraicNumber_create(&a->a);
+ }
+ }
+
+ if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ AlgebraicNumber* a1 = (AlgebraicNumber*) self;
+ AlgebraicNumber* a2 = (AlgebraicNumber*) other;
+
+ lp_algebraic_number_t sum;
+ lp_algebraic_number_construct_zero(&sum);
+ lp_algebraic_number_add(&sum, &a1->a, &a2->a);
+ PyObject* result = PyAlgebraicNumber_create(&sum);
+ lp_algebraic_number_destruct(&sum);
+
+ return result;
+}
+
+static PyObject*
+AlgebraicNumber_neg(PyObject* self) {
+ if (!PyAlgebraicNumber_CHECK(self)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ AlgebraicNumber* a1 = (AlgebraicNumber*) self;
+
+ lp_algebraic_number_t neg;
+ lp_algebraic_number_construct_zero(&neg);
+ lp_algebraic_number_neg(&neg, &a1->a);
+ PyObject* result = PyAlgebraicNumber_create(&neg);
+ lp_algebraic_number_destruct(&neg);
+
+ return result;
+}
+
+static PyObject*
+AlgebraicNumber_sub(PyObject* self, PyObject* other) {
+ if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ AlgebraicNumber* a1 = (AlgebraicNumber*) self;
+ AlgebraicNumber* a2 = (AlgebraicNumber*) other;
+
+ lp_algebraic_number_t sub;
+ lp_algebraic_number_construct_zero(&sub);
+ lp_algebraic_number_sub(&sub, &a1->a, &a2->a);
+ PyObject* result = PyAlgebraicNumber_create(&sub);
+ lp_algebraic_number_destruct(&sub);
+
+ return result;
+}
+
+static PyObject*
+AlgebraicNumber_mul(PyObject* self, PyObject* other) {
+ if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ AlgebraicNumber* a1 = (AlgebraicNumber*) self;
+ AlgebraicNumber* a2 = (AlgebraicNumber*) other;
+
+ lp_algebraic_number_t mul;
+ lp_algebraic_number_construct_zero(&mul);
+ lp_algebraic_number_mul(&mul, &a1->a, &a2->a);
+ PyObject* result = PyAlgebraicNumber_create(&mul);
+ lp_algebraic_number_destruct(&mul);
+
+ return result;
+}
+
+static PyObject*
+AlgebraicNumber_div(PyObject* self, PyObject* other) {
+ if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ AlgebraicNumber* a1 = (AlgebraicNumber*) self;
+ AlgebraicNumber* a2 = (AlgebraicNumber*) other;
+
+ lp_algebraic_number_t mul;
+ lp_algebraic_number_construct_zero(&mul);
+ lp_algebraic_number_div(&mul, &a1->a, &a2->a);
+ PyObject* result = PyAlgebraicNumber_create(&mul);
+ lp_algebraic_number_destruct(&mul);
+
+ return result;
+}
+
+static PyObject*
+AlgebraicNumber_pow(PyObject* self, PyObject* other) {
+ if (!PyAlgebraicNumber_CHECK(self) || !PyLong_Check(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ AlgebraicNumber* a1 = (AlgebraicNumber*) self;
+ long n = PyLong_AsLong(other);
+
+ lp_algebraic_number_t pow;
+ lp_algebraic_number_construct_zero(&pow);
+ lp_algebraic_number_pow(&pow, &a1->a, n);
+ PyObject* result = PyAlgebraicNumber_create(&pow);
+ lp_algebraic_number_destruct(&pow);
+
+ return result;
+}
+
+static PyObject*
+AlgebraicNumber_positive_root(PyObject* self, PyObject* args) {
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ if (p) {
+ // Get the argument
+ if (PyTuple_Size(args) == 1) {
+ // Get n
+ PyObject* other = PyTuple_GetItem(args, 0);
+ AlgebraicNumber* a1 = (AlgebraicNumber*) self;
+ long n = PyLong_AsLong(other);
+
+ lp_algebraic_number_t root;
+ lp_algebraic_number_construct_zero(&root);
+ lp_algebraic_number_positive_root(&root, &a1->a, n);
+ PyObject* result = PyAlgebraicNumber_create(&root);
+ lp_algebraic_number_destruct(&root);
+
+ return result;
+ } else {
+ Py_RETURN_NONE;
+ }
+ } else {
+ Py_RETURN_NONE;
+ }
+}
diff --git a/python/polypyAlgebraicNumber.h b/python/polypyAlgebraicNumber.h
index 20f950ed..84e8df22 100644
--- a/python/polypyAlgebraicNumber.h
+++ b/python/polypyAlgebraicNumber.h
@@ -19,7 +19,7 @@
#pragma once
-#include
+#include "python.h"
#include "algebraic_number.h"
diff --git a/python/polypyAlgebraicNumber2.c b/python/polypyAlgebraicNumber2.c
deleted file mode 100644
index 293b5a93..00000000
--- a/python/polypyAlgebraicNumber2.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/**
- * 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 "polypyAlgebraicNumber.h"
-#include "polypyUPolynomial.h"
-#include "polypyPolynomial.h"
-
-#include
-
-static void
-AlgebraicNumber_dealloc(AlgebraicNumber* self);
-
-static PyObject*
-AlgebraicNumber_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-AlgebraicNumber_init(AlgebraicNumber* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_to_double(PyObject* self);
-
- static int
-AlgebraicNumber_cmp(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_richcompare(PyObject* self, PyObject* other, int op);
-
-static PyObject*
-AlgebraicNumber_str(PyObject* self);
-
-static PyObject*
-AlgebraicNumber_refine(PyObject* self);
-
-static PyObject*
-AlgebraicNumber_add(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_neg(PyObject* self);
-
-static PyObject*
-AlgebraicNumber_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_div(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_pow(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_positive_root(PyObject* self, PyObject* args);
-
-PyMethodDef AlgebraicNumber_methods[] = {
- {"refine", (PyCFunction)AlgebraicNumber_refine, METH_NOARGS, "Refines the number to half the interval"},
- {"to_double", (PyCFunction)AlgebraicNumber_to_double, METH_NOARGS, "Returns the approximation of the algebraic number"},
- {"positive_root", (PyCFunction)AlgebraicNumber_positive_root, METH_VARARGS, "Returns the positive root of the number is positive"},
- {NULL} /* Sentinel */
-};
-
-PyNumberMethods AlgebraicNumber_NumberMethods = {
- AlgebraicNumber_add, // binaryfunc nb_add;
- AlgebraicNumber_sub, // binaryfunc nb_subtract;
- AlgebraicNumber_mul, // binaryfunc nb_multiply;
- AlgebraicNumber_div, // binaryfunc nb_divide;
- 0, // binaryfunc nb_remainder;
- 0, // binaryfunc nb_divmod;
- (ternaryfunc)AlgebraicNumber_pow, // ternaryfunc nb_power;
- AlgebraicNumber_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- 0, // inquiry nb_nonzero; /* Used by PyObject_IsTrue */
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- 0, // coercion nb_coerce; /* Used by the coerce() function */
- 0, // unaryfunc nb_int;
- 0, // unaryfunc nb_long;
- 0, // unaryfunc nb_float;
- 0, // unaryfunc nb_oct;
- 0, // unaryfunc nb_hex;
-
- /* Added in release 2.0 */
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_divide;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
-
- /* Added in release 2.2 */
- 0, // binaryfunc nb_floor_divide;
- 0, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
-
- /* Added in release 2.5 */
- 0 // unaryfunc nb_index;
-};
-
-PyTypeObject AlgebraicNumberType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.AlgebraicNumber", /*tp_name*/
- sizeof(AlgebraicNumber), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)AlgebraicNumber_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- AlgebraicNumber_cmp, /*tp_compare*/
- AlgebraicNumber_str, /*tp_repr*/
- &AlgebraicNumber_NumberMethods, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- AlgebraicNumber_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "Algebraic number objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- AlgebraicNumber_richcompare,/* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- AlgebraicNumber_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)AlgebraicNumber_init,/* tp_init */
- 0, /* tp_alloc */
- AlgebraicNumber_new, /* tp_new */
-};
-
-static void
-AlgebraicNumber_dealloc(AlgebraicNumber* self)
-{
- lp_algebraic_number_destruct(&self->a);
- self->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyAlgebraicNumber_create(const lp_algebraic_number_t* a) {
- AlgebraicNumber *self;
- self = (AlgebraicNumber*)AlgebraicNumberType.tp_alloc(&AlgebraicNumberType, 0);
- if (self != NULL) {
- if (a) {
- lp_algebraic_number_construct_copy(&self->a, a);
- } else {
- lp_dyadic_rational_t zero;
- lp_dyadic_rational_construct(&zero);
- lp_algebraic_number_construct_from_dyadic_rational(&self->a, &zero);
- lp_dyadic_rational_destruct(&zero);
- }
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-AlgebraicNumber_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyAlgebraicNumber_create(0);
-}
-
-/** Construct an algebraic number from a polynomial and a root index */
-static int
-AlgebraicNumber_init(AlgebraicNumber* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 2) {
- PyObject* f_obj = PyTuple_GetItem(args, 0);
- PyObject* root_index_obj = PyTuple_GetItem(args, 1);
- if (PyPolynomial_CHECK(f_obj) && PyInt_Check(root_index_obj)) {
- // Get the polynomial
- lp_polynomial_t* f = ((Polynomial*) f_obj)->p;
- long root_index = PyInt_AsLong(root_index_obj);
- // Get the univariate polynomial
- lp_upolynomial_t* f_u = lp_polynomial_to_univariate(f);
- if (f_u == 0) {
- // Not univariate
- return -1;
- }
- // Check the roots
- size_t roots_count = lp_upolynomial_roots_count(f_u, 0);
- if (root_index < 0 || root_index >= roots_count) {
- // Not enough roots
- lp_upolynomial_delete(f_u);
- return -1;
- }
- lp_algebraic_number_t* roots = malloc(roots_count * sizeof(lp_algebraic_number_t));
- lp_upolynomial_roots_isolate(f_u, roots, &roots_count);
- lp_algebraic_number_destruct(&self->a);
- lp_algebraic_number_construct_copy(&self->a, roots + root_index);
- int i;
- for (i = 0; i < roots_count; ++ i) {
- lp_algebraic_number_destruct(roots + i);
- }
- lp_upolynomial_delete(f_u);
- free(roots);
- } else if (PyUPolynomial_CHECK(f_obj) && PyInt_Check(root_index_obj)) {
- lp_upolynomial_t* f = ((UPolynomialObject*) f_obj)->p;
- long root_index = PyInt_AsLong(root_index_obj);
- size_t roots_count = lp_upolynomial_roots_count(f, 0);
- if (root_index < 0 || root_index >= roots_count) {
- // Not enough roots
- return -1;
- }
- lp_algebraic_number_t* roots = malloc(roots_count * sizeof(lp_algebraic_number_t));
- lp_upolynomial_roots_isolate(f, roots, &roots_count);
- lp_algebraic_number_destruct(&self->a);
- lp_algebraic_number_construct_copy(&self->a, roots + root_index);
- int i;
- for (i = 0; i < roots_count; ++i) {
- lp_algebraic_number_destruct(roots + i);
- }
- free(roots);
- } else{
- return -1;
- }
- } else {
- return -1;
- }
-
- // All fine, initialized
- return 0;
-}
-
-static PyObject*
-AlgebraicNumber_to_double(PyObject* self) {
- AlgebraicNumber* a = (AlgebraicNumber*) self;
- return algebraic_number_to_PyFloat(&a->a);
-}
-
-static PyObject*
-AlgebraicNumber_refine(PyObject* self) {
- AlgebraicNumber* a = (AlgebraicNumber*) self;
- lp_algebraic_number_refine(&a->a);
- Py_RETURN_NONE;
-}
-
-static int
-AlgebraicNumber_cmp(PyObject* self, PyObject* other) {
- // Check arguments
- if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
- // should return -1 and set an exception condition when an error occurred
- return -1;
- }
- // Get arguments
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- AlgebraicNumber* a2 = (AlgebraicNumber*) other;
- // Compare
- return lp_algebraic_number_cmp(&a1->a, &a2->a);
-}
-
-static PyObject*
-AlgebraicNumber_richcompare(PyObject* self, PyObject* other, int op) {
- PyObject *result = 0;
-
- if (!PyAlgebraicNumber_CHECK(other)) {
- result = Py_NotImplemented;
- } else {
- lp_algebraic_number_t* self_a = &((AlgebraicNumber*) self)->a;
- lp_algebraic_number_t* other_a = &((AlgebraicNumber*) other)->a;
- int cmp = lp_algebraic_number_cmp(self_a, other_a);
-
- switch (op) {
- case Py_LT:
- result = cmp < 0 ? Py_True : Py_False;
- break;
- case Py_LE:
- result = cmp <= 0 ? Py_True : Py_False;
- break;
- case Py_EQ:
- result = cmp == 0 ? Py_True : Py_False;
- break;
- case Py_NE:
- result = cmp != 0 ? Py_True : Py_False;
- break;
- case Py_GT:
- result = cmp > 0 ? Py_True : Py_False;
- break;
- case Py_GE:
- result = cmp >= 0 ? Py_True : Py_False;
- break;
- }
- }
-
- Py_INCREF(result);
- return result;
-}
-
-static PyObject* AlgebraicNumber_str(PyObject* self) {
- AlgebraicNumber* a = (AlgebraicNumber*) self;
- char* cstr = lp_algebraic_number_to_string(&a->a);
- PyObject* pystr = PyString_FromString(cstr);
- free(cstr);
- return pystr;
-}
-
-static PyObject*
-AlgebraicNumber_add(PyObject* self, PyObject* other) {
-
- if (PyInt_Check(self)) {
- // To enable summation
- long x = PyInt_AsLong(self);
- if (x == 0) {
- AlgebraicNumber* a = (AlgebraicNumber*) other;
- return PyAlgebraicNumber_create(&a->a);
- }
- }
-
- if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- AlgebraicNumber* a2 = (AlgebraicNumber*) other;
-
- lp_algebraic_number_t sum;
- lp_algebraic_number_construct_zero(&sum);
- lp_algebraic_number_add(&sum, &a1->a, &a2->a);
- PyObject* result = PyAlgebraicNumber_create(&sum);
- lp_algebraic_number_destruct(&sum);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_neg(PyObject* self) {
- if (!PyAlgebraicNumber_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
-
- lp_algebraic_number_t neg;
- lp_algebraic_number_construct_zero(&neg);
- lp_algebraic_number_neg(&neg, &a1->a);
- PyObject* result = PyAlgebraicNumber_create(&neg);
- lp_algebraic_number_destruct(&neg);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_sub(PyObject* self, PyObject* other) {
- if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- AlgebraicNumber* a2 = (AlgebraicNumber*) other;
-
- lp_algebraic_number_t sub;
- lp_algebraic_number_construct_zero(&sub);
- lp_algebraic_number_sub(&sub, &a1->a, &a2->a);
- PyObject* result = PyAlgebraicNumber_create(&sub);
- lp_algebraic_number_destruct(&sub);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_mul(PyObject* self, PyObject* other) {
- if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- AlgebraicNumber* a2 = (AlgebraicNumber*) other;
-
- lp_algebraic_number_t mul;
- lp_algebraic_number_construct_zero(&mul);
- lp_algebraic_number_mul(&mul, &a1->a, &a2->a);
- PyObject* result = PyAlgebraicNumber_create(&mul);
- lp_algebraic_number_destruct(&mul);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_div(PyObject* self, PyObject* other) {
- if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- AlgebraicNumber* a2 = (AlgebraicNumber*) other;
-
- lp_algebraic_number_t mul;
- lp_algebraic_number_construct_zero(&mul);
- lp_algebraic_number_div(&mul, &a1->a, &a2->a);
- PyObject* result = PyAlgebraicNumber_create(&mul);
- lp_algebraic_number_destruct(&mul);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_pow(PyObject* self, PyObject* other) {
- if (!PyAlgebraicNumber_CHECK(self) || !PyInt_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- long n = PyInt_AsLong(other);
-
- lp_algebraic_number_t pow;
- lp_algebraic_number_construct_zero(&pow);
- lp_algebraic_number_pow(&pow, &a1->a, n);
- PyObject* result = PyAlgebraicNumber_create(&pow);
- lp_algebraic_number_destruct(&pow);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_positive_root(PyObject* self, PyObject* args) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- // Get the argument
- if (PyTuple_Size(args) == 1) {
- // Get n
- PyObject* other = PyTuple_GetItem(args, 0);
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- long n = PyLong_AsLong(other);
-
- lp_algebraic_number_t root;
- lp_algebraic_number_construct_zero(&root);
- lp_algebraic_number_positive_root(&root, &a1->a, n);
- PyObject* result = PyAlgebraicNumber_create(&root);
- lp_algebraic_number_destruct(&root);
-
- return result;
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
-}
diff --git a/python/polypyAlgebraicNumber3.c b/python/polypyAlgebraicNumber3.c
deleted file mode 100644
index 452c3a49..00000000
--- a/python/polypyAlgebraicNumber3.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/**
- * 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 "polypyAlgebraicNumber.h"
-#include "polypyUPolynomial.h"
-#include "polypyPolynomial.h"
-
-#include
-
-static void
-AlgebraicNumber_dealloc(AlgebraicNumber* self);
-
-static PyObject*
-AlgebraicNumber_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-AlgebraicNumber_init(AlgebraicNumber* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_to_double(PyObject* self);
-
-static PyObject*
-AlgebraicNumber_richcompare(PyObject* self, PyObject* other, int op);
-
-static PyObject*
-AlgebraicNumber_str(PyObject* self);
-
-static PyObject*
-AlgebraicNumber_refine(PyObject* self);
-
-static PyObject*
-AlgebraicNumber_add(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_neg(PyObject* self);
-
-static PyObject*
-AlgebraicNumber_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_div(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_pow(PyObject* self, PyObject* args);
-
-static PyObject*
-AlgebraicNumber_positive_root(PyObject* self, PyObject* args);
-
-PyMethodDef AlgebraicNumber_methods[] = {
- {"refine", (PyCFunction)AlgebraicNumber_refine, METH_NOARGS, "Refines the number to half the interval"},
- {"to_double", (PyCFunction)AlgebraicNumber_to_double, METH_NOARGS, "Returns the approximation of the algebraic number"},
- {"positive_root", (PyCFunction)AlgebraicNumber_positive_root, METH_VARARGS, "Returns the positive root of the number is positive"},
- {NULL} /* Sentinel */
-};
-
-PyNumberMethods AlgebraicNumber_NumberMethods = {
- AlgebraicNumber_add, // binaryfunc nb_add;
- AlgebraicNumber_sub, // binaryfunc nb_subtract;
- AlgebraicNumber_mul, // binaryfunc nb_multiply;
- 0, // binaryfunc nb_remainder;
- 0, // binaryfunc nb_divmod;
- (ternaryfunc)AlgebraicNumber_pow, // ternaryfunc nb_power;
- AlgebraicNumber_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- 0, // inquiry nb_bool;
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- 0, // unaryfunc nb_int;
- 0, // void *nb_reserved;
- 0, // unaryfunc nb_float;
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
- 0, // binaryfunc nb_floor_divide;
- AlgebraicNumber_div, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
- 0, // unaryfunc nb_index;
- 0, // binaryfunc nb_matrix_multiply;
- 0, // binaryfunc nb_inplace_matrix_multiply;
-};
-
-PyTypeObject AlgebraicNumberType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.AlgebraicNumber", // const char *tp_name;
- sizeof(AlgebraicNumber), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)AlgebraicNumber_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async
- AlgebraicNumber_str, // reprfunc tp_repr;
- &AlgebraicNumber_NumberMethods, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- 0, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- AlgebraicNumber_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "Algebraic number objects", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- AlgebraicNumber_richcompare, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- AlgebraicNumber_methods, // struct PyMethodDef *tp_methods;
- 0, // struct PyMemberDef *tp_members;
- 0, // struct PyGetSetDef *tp_getset;
- 0, // struct _typeobject *tp_base;
- 0, // PyObject *tp_dict;
- 0, // descrgetfunc tp_descr_get;
- 0, // descrsetfunc tp_descr_set;
- 0, // Py_ssize_t tp_dictoffset;
- (initproc)AlgebraicNumber_init, // initproc tp_init;
- 0, // Pallocfunc tp_alloc;
- AlgebraicNumber_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-static void
-AlgebraicNumber_dealloc(AlgebraicNumber* self)
-{
- lp_algebraic_number_destruct(&self->a);
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyAlgebraicNumber_create(const lp_algebraic_number_t* a) {
- AlgebraicNumber *self;
- self = (AlgebraicNumber*)AlgebraicNumberType.tp_alloc(&AlgebraicNumberType, 0);
- if (self != NULL) {
- if (a) {
- lp_algebraic_number_construct_copy(&self->a, a);
- } else {
- lp_dyadic_rational_t zero;
- lp_dyadic_rational_construct(&zero);
- lp_algebraic_number_construct_from_dyadic_rational(&self->a, &zero);
- lp_dyadic_rational_destruct(&zero);
- }
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-AlgebraicNumber_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyAlgebraicNumber_create(0);
-}
-
-/** Construct an algebraic number from a polynomial and a root index */
-static int
-AlgebraicNumber_init(AlgebraicNumber* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 2) {
- PyObject* f_obj = PyTuple_GetItem(args, 0);
- PyObject* root_index_obj = PyTuple_GetItem(args, 1);
- if (PyPolynomial_CHECK(f_obj) && PyLong_Check(root_index_obj)) {
- // Get the polynomial
- lp_polynomial_t* f = ((Polynomial*) f_obj)->p;
- long root_index = PyLong_AsLong(root_index_obj);
- // Get the univariate polynomial
- lp_upolynomial_t* f_u = lp_polynomial_to_univariate(f);
- if (f_u == 0) {
- // Not univariate
- return -1;
- }
- // Check the roots
- size_t roots_count = lp_upolynomial_roots_count(f_u, 0);
- if (root_index < 0 || root_index >= (long)roots_count) {
- // Not enough roots
- lp_upolynomial_delete(f_u);
- return -1;
- }
- lp_algebraic_number_t* roots = malloc(roots_count * sizeof(lp_algebraic_number_t));
- lp_upolynomial_roots_isolate(f_u, roots, &roots_count);
- lp_algebraic_number_destruct(&self->a);
- lp_algebraic_number_construct_copy(&self->a, roots + root_index);
- size_t i;
- for (i = 0; i < roots_count; ++ i) {
- lp_algebraic_number_destruct(roots + i);
- }
- lp_upolynomial_delete(f_u);
- free(roots);
- } else if (PyUPolynomial_CHECK(f_obj) && PyLong_Check(root_index_obj)) {
- lp_upolynomial_t* f = ((UPolynomialObject*) f_obj)->p;
- long root_index = PyLong_AsLong(root_index_obj);
- size_t roots_count = lp_upolynomial_roots_count(f, 0);
- if (root_index < 0 || root_index >= (long)roots_count) {
- // Not enough roots
- return -1;
- }
- lp_algebraic_number_t* roots = malloc(roots_count * sizeof(lp_algebraic_number_t));
- lp_upolynomial_roots_isolate(f, roots, &roots_count);
- lp_algebraic_number_destruct(&self->a);
- lp_algebraic_number_construct_copy(&self->a, roots + root_index);
- size_t i;
- for (i = 0; i < roots_count; ++i) {
- lp_algebraic_number_destruct(roots + i);
- }
- free(roots);
- } else{
- return -1;
- }
- } else {
- return -1;
- }
-
- // All fine, initialized
- return 0;
-}
-
-static PyObject*
-AlgebraicNumber_to_double(PyObject* self) {
- AlgebraicNumber* a = (AlgebraicNumber*) self;
- return algebraic_number_to_PyFloat(&a->a);
-}
-
-static PyObject*
-AlgebraicNumber_refine(PyObject* self) {
- AlgebraicNumber* a = (AlgebraicNumber*) self;
- lp_algebraic_number_refine(&a->a);
- Py_RETURN_NONE;
-}
-
-static PyObject*
-AlgebraicNumber_richcompare(PyObject* self, PyObject* other, int op) {
- PyObject *result = 0;
-
- if (!PyAlgebraicNumber_CHECK(other)) {
- result = Py_NotImplemented;
- } else {
- lp_algebraic_number_t* self_a = &((AlgebraicNumber*) self)->a;
- lp_algebraic_number_t* other_a = &((AlgebraicNumber*) other)->a;
- int cmp = lp_algebraic_number_cmp(self_a, other_a);
-
- switch (op) {
- case Py_LT:
- result = cmp < 0 ? Py_True : Py_False;
- break;
- case Py_LE:
- result = cmp <= 0 ? Py_True : Py_False;
- break;
- case Py_EQ:
- result = cmp == 0 ? Py_True : Py_False;
- break;
- case Py_NE:
- result = cmp != 0 ? Py_True : Py_False;
- break;
- case Py_GT:
- result = cmp > 0 ? Py_True : Py_False;
- break;
- case Py_GE:
- result = cmp >= 0 ? Py_True : Py_False;
- break;
- }
- }
-
- Py_INCREF(result);
- return result;
-}
-
-static PyObject* AlgebraicNumber_str(PyObject* self) {
- AlgebraicNumber* a = (AlgebraicNumber*) self;
- char* cstr = lp_algebraic_number_to_string(&a->a);
- PyObject* pystr = PyUnicode_FromString(cstr);
- free(cstr);
- return pystr;
-}
-
-static PyObject*
-AlgebraicNumber_add(PyObject* self, PyObject* other) {
-
- if (PyLong_Check(self)) {
- // To enable summation
- long x = PyLong_AsLong(self);
- if (x == 0) {
- AlgebraicNumber* a = (AlgebraicNumber*) other;
- return PyAlgebraicNumber_create(&a->a);
- }
- }
-
- if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- AlgebraicNumber* a2 = (AlgebraicNumber*) other;
-
- lp_algebraic_number_t sum;
- lp_algebraic_number_construct_zero(&sum);
- lp_algebraic_number_add(&sum, &a1->a, &a2->a);
- PyObject* result = PyAlgebraicNumber_create(&sum);
- lp_algebraic_number_destruct(&sum);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_neg(PyObject* self) {
- if (!PyAlgebraicNumber_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
-
- lp_algebraic_number_t neg;
- lp_algebraic_number_construct_zero(&neg);
- lp_algebraic_number_neg(&neg, &a1->a);
- PyObject* result = PyAlgebraicNumber_create(&neg);
- lp_algebraic_number_destruct(&neg);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_sub(PyObject* self, PyObject* other) {
- if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- AlgebraicNumber* a2 = (AlgebraicNumber*) other;
-
- lp_algebraic_number_t sub;
- lp_algebraic_number_construct_zero(&sub);
- lp_algebraic_number_sub(&sub, &a1->a, &a2->a);
- PyObject* result = PyAlgebraicNumber_create(&sub);
- lp_algebraic_number_destruct(&sub);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_mul(PyObject* self, PyObject* other) {
- if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- AlgebraicNumber* a2 = (AlgebraicNumber*) other;
-
- lp_algebraic_number_t mul;
- lp_algebraic_number_construct_zero(&mul);
- lp_algebraic_number_mul(&mul, &a1->a, &a2->a);
- PyObject* result = PyAlgebraicNumber_create(&mul);
- lp_algebraic_number_destruct(&mul);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_div(PyObject* self, PyObject* other) {
- if (!PyAlgebraicNumber_CHECK(self) || !PyAlgebraicNumber_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- AlgebraicNumber* a2 = (AlgebraicNumber*) other;
-
- lp_algebraic_number_t mul;
- lp_algebraic_number_construct_zero(&mul);
- lp_algebraic_number_div(&mul, &a1->a, &a2->a);
- PyObject* result = PyAlgebraicNumber_create(&mul);
- lp_algebraic_number_destruct(&mul);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_pow(PyObject* self, PyObject* other) {
- if (!PyAlgebraicNumber_CHECK(self) || !PyLong_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- long n = PyLong_AsLong(other);
-
- lp_algebraic_number_t pow;
- lp_algebraic_number_construct_zero(&pow);
- lp_algebraic_number_pow(&pow, &a1->a, n);
- PyObject* result = PyAlgebraicNumber_create(&pow);
- lp_algebraic_number_destruct(&pow);
-
- return result;
-}
-
-static PyObject*
-AlgebraicNumber_positive_root(PyObject* self, PyObject* args) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- // Get the argument
- if (PyTuple_Size(args) == 1) {
- // Get n
- PyObject* other = PyTuple_GetItem(args, 0);
- AlgebraicNumber* a1 = (AlgebraicNumber*) self;
- long n = PyLong_AsLong(other);
-
- lp_algebraic_number_t root;
- lp_algebraic_number_construct_zero(&root);
- lp_algebraic_number_positive_root(&root, &a1->a, n);
- PyObject* result = PyAlgebraicNumber_create(&root);
- lp_algebraic_number_destruct(&root);
-
- return result;
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
-}
diff --git a/python/polypyAssignment.c b/python/polypyAssignment.c
index fdecb04c..216854b7 100644
--- a/python/polypyAssignment.c
+++ b/python/polypyAssignment.c
@@ -17,11 +17,268 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include "Python.h"
-
-#if PY_MAJOR_VERSION >= 3
-#include "polypyAssignment3.c"
-#else
-#include "polypyAssignment2.c"
-#endif
+#include "python.h"
+
+#include "polypyAssignment.h"
+#include "polypyVariable.h"
+#include "utils.h"
+#include "polypyAlgebraicNumber.h"
+#include "polypyValue.h"
+
+/** Default variable database */
+static lp_assignment_t* default_assignment = NULL;
+
+lp_assignment_t* Assignment_get_default_assignment(void) {
+ if (!default_assignment) {
+ default_assignment = lp_assignment_new(Variable_get_default_db());
+ }
+ return default_assignment;
+}
+
+static PyObject*
+Assignment_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static int
+Assignment_init(Assignment* self, PyObject* args);
+
+static void
+Assignment_dealloc(Assignment* self);
+
+static PyObject*
+Assignment_str(PyObject* self);
+
+static PyObject*
+Assignment_get_value(PyObject* self, PyObject* args);
+
+static PyObject*
+Assignment_set_value(PyObject* self, PyObject* args);
+
+static PyObject*
+Assignment_unset_value(PyObject* self, PyObject* args);
+
+PyMethodDef Assignment_methods[] = {
+ {"get_value", (PyCFunction)Assignment_get_value, METH_VARARGS, "Returns the value of the variable"},
+ {"set_value", (PyCFunction)Assignment_set_value, METH_VARARGS, "Sets the value of the variable"},
+ {"unset_value", (PyCFunction)Assignment_unset_value, METH_VARARGS, "Marks the variable as unassigned"},
+ {NULL} /* Sentinel */
+};
+
+
+PyTypeObject AssignmentType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.Assignment", // const char *tp_name;
+ sizeof(Variable), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)Assignment_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async;
+ NULL, // reprfunc tp_repr;
+ NULL, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ NULL, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ Assignment_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "Variable objects", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ NULL, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ Assignment_methods, // struct PyMethodDef *tp_methods;
+ NULL, // struct PyMemberDef *tp_members;
+ NULL, // struct PyGetSetDef *tp_getset;
+ NULL, // struct _typeobject *tp_base;
+ NULL, // PyObject *tp_dict;
+ NULL, // descrgetfunc tp_descr_get;
+ NULL, // descrsetfunc tp_descr_set;
+ 0, // Py_ssize_t tp_dictoffset;
+ (initproc)Assignment_init, // initproc tp_init;
+ NULL, // allocfunc tp_alloc;
+ Assignment_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+PyObject*
+PyAssignment_create(lp_assignment_t* assignment) {
+ Assignment *self = (Assignment*)AssignmentType.tp_alloc(&AssignmentType, 0);
+ if (self != NULL) {
+ self->assignment = assignment;
+ }
+ return (PyObject *)self;
+}
+
+static PyObject*
+Assignment_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return PyAssignment_create(NULL);
+}
+
+static int
+Assignment_init(Assignment* self, PyObject* args)
+{
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 0) {
+ self->assignment = lp_assignment_new(Variable_get_default_db());
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static void
+Assignment_dealloc(Assignment* self)
+{
+ if (self->assignment) {
+ lp_assignment_delete(self->assignment);
+ }
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+static PyObject* Assignment_str(PyObject* self) {
+ Assignment* a = (Assignment*) self;
+ char* a_str = lp_assignment_to_string(a->assignment);
+ PyObject* str = PyUnicode_FromString(a_str);
+ free(a_str);
+ return str;
+}
+
+static PyObject*
+Assignment_get_value(PyObject* self, PyObject* args) {
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
+ PyObject* var_obj = PyTuple_GetItem(args, 0);
+ if (PyVariable_CHECK(var_obj)) {
+ Variable* var = (Variable*) var_obj;
+ Assignment* a = (Assignment*) self;
+ const lp_value_t* value = lp_assignment_get_value(a->assignment, var->x);
+ switch (value->type) {
+ case LP_VALUE_DYADIC_RATIONAL:
+ return dyadic_rational_to_PyFloat(&value->value.dy_q);
+ case LP_VALUE_NONE:
+ Py_RETURN_NONE;
+ case LP_VALUE_RATIONAL:
+ case LP_VALUE_ALGEBRAIC:
+ default:
+ return NULL;
+ }
+ }
+ }
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+}
+
+static PyObject*
+Assignment_set_value(PyObject* self, PyObject* args) {
+ if (PyTuple_Check(args)) {
+ if (PyTuple_Size(args) == 2) {
+ PyObject* var_obj = PyTuple_GetItem(args, 0);
+ PyObject* value_obj = PyTuple_GetItem(args, 1);
+ if (PyVariable_CHECK(var_obj)) {
+ Assignment* a = (Assignment*) self;
+ Variable* var = (Variable*) var_obj;
+ if (PyFloat_Check(value_obj)) {
+ lp_dyadic_rational_t value_dyrat;
+ PyFloat_to_dyadic_rational(value_obj, &value_dyrat);
+ lp_value_t value;
+ lp_value_construct(&value, LP_VALUE_DYADIC_RATIONAL, &value_dyrat);
+ lp_assignment_set_value(a->assignment, var->x, &value);
+ lp_value_destruct(&value);
+ lp_dyadic_rational_destruct(&value_dyrat);
+ Py_RETURN_NONE;
+ } else if (PyLong_or_Int_Check(value_obj)) {
+ lp_integer_t value_int;
+ PyLong_or_Int_to_integer(value_obj, lp_Z, &value_int);
+ lp_dyadic_rational_t value_dyrat;
+ lp_dyadic_rational_construct_from_integer(&value_dyrat, &value_int);
+ lp_value_t value;
+ lp_value_construct(&value, LP_VALUE_DYADIC_RATIONAL, &value_dyrat);
+ lp_assignment_set_value(a->assignment, var->x, &value);
+ lp_value_destruct(&value);
+ lp_dyadic_rational_destruct(&value_dyrat);
+ lp_integer_destruct(&value_int);
+ Py_RETURN_NONE;
+ } else if (PyAlgebraicNumber_CHECK(value_obj)) {
+ lp_value_t value;
+ lp_value_construct(&value, LP_VALUE_ALGEBRAIC, &((AlgebraicNumber*) value_obj)->a);
+ lp_assignment_set_value(a->assignment, var->x, &value);
+ lp_value_destruct(&value);
+ Py_RETURN_NONE;
+ } else if (PyValue_CHECK(value_obj)) {
+ Value* value = (Value*) value_obj;
+ lp_assignment_set_value(a->assignment, var->x, &value->v);
+ Py_RETURN_NONE;
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "set_value(): not a value.");
+ return NULL;
+ }
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "set_value(): not a variable.");
+ return NULL;
+ }
+ } else if (PyTuple_Size(args) == 3) {
+ // Three arguments, rational
+ PyObject* var_obj = PyTuple_GetItem(args, 0);
+ PyObject* p_obj = PyTuple_GetItem(args, 1);
+ PyObject* q_obj = PyTuple_GetItem(args, 2);
+ if (PyLong_or_Int_Check(p_obj) && PyLong_or_Int_Check(q_obj)) {
+ Assignment* a = (Assignment*) self;
+ Variable* var = (Variable*) var_obj;
+ lp_integer_t p_int, q_int;
+ PyLong_or_Int_to_integer(p_obj, lp_Z, &p_int);
+ PyLong_or_Int_to_integer(q_obj, lp_Z, &q_int);
+ lp_rational_t value_rat;
+ lp_rational_construct_from_div(&value_rat, &p_int, &q_int);
+ lp_value_t value;
+ lp_value_construct(&value, LP_VALUE_RATIONAL, &value_rat);
+ lp_assignment_set_value(a->assignment, var->x, &value);
+ lp_value_destruct(&value);
+ lp_rational_destruct(&value_rat);
+ lp_integer_destruct(&p_int);
+ lp_integer_destruct(&q_int);
+ Py_RETURN_NONE;
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "set_value(): for rationals, both numerator and denominator must be integer.");
+ return NULL;
+ }
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "set_value(): need two or three arguments.");
+ return NULL;
+ }
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "set_value(): need two or three arguments.");
+ return NULL;
+ }
+}
+
+static PyObject*
+Assignment_unset_value(PyObject* self, PyObject* args) {
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
+ PyObject* var_obj = PyTuple_GetItem(args, 0);
+ if (PyVariable_CHECK(var_obj)) {
+ Variable* var = (Variable*) var_obj;
+ Assignment* a = (Assignment*) self;
+ lp_assignment_set_value(a->assignment, var->x, NULL);
+ Py_RETURN_NONE;
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "set_value(): not a variable.");
+ return NULL;
+ }
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "set_value(): need one argument.");
+ return NULL;
+ }
+}
diff --git a/python/polypyAssignment.h b/python/polypyAssignment.h
index acb86d6d..3d3a33a1 100644
--- a/python/polypyAssignment.h
+++ b/python/polypyAssignment.h
@@ -19,9 +19,7 @@
#pragma once
-
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include "assignment.h"
diff --git a/python/polypyAssignment2.c b/python/polypyAssignment2.c
deleted file mode 100644
index b37b3720..00000000
--- a/python/polypyAssignment2.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/**
- * 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 "polypyAssignment.h"
-#include "polypyVariable.h"
-#include "utils.h"
-#include "polypyAlgebraicNumber.h"
-#include "polypyValue.h"
-
-#include
-
-/** Default variable database */
-static lp_assignment_t* default_assignment = 0;
-
-lp_assignment_t* Assignment_get_default_assignment(void) {
- if (!default_assignment) {
- default_assignment = lp_assignment_new(Variable_get_default_db());
- }
- return default_assignment;
-}
-
-static PyObject*
-Assignment_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-Assignment_init(Assignment* self, PyObject* args);
-
-static void
-Assignment_dealloc(Assignment* self);
-
-static PyObject*
-Assignment_str(PyObject* self);
-
-static PyObject*
-Assignment_get_value(PyObject* self, PyObject* args);
-
-static PyObject*
-Assignment_set_value(PyObject* self, PyObject* args);
-
-static PyObject*
-Assignment_unset_value(PyObject* self, PyObject* args);
-
-PyMethodDef Assignment_methods[] = {
- {"get_value", (PyCFunction)Assignment_get_value, METH_VARARGS, "Returns the value of the variable"},
- {"set_value", (PyCFunction)Assignment_set_value, METH_VARARGS, "Sets the value of the variable"},
- {"unset_value", (PyCFunction)Assignment_unset_value, METH_VARARGS, "Marks the variable as unassigned"},
- {NULL} /* Sentinel */
-};
-
-PyTypeObject AssignmentType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.Assignment", /*tp_name*/
- sizeof(Variable), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)Assignment_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- Assignment_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "Variable objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- Assignment_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)Assignment_init, /* tp_init */
- 0, /* tp_alloc */
- Assignment_new, /* tp_new */
-};
-
-PyObject*
-PyAssignment_create(lp_assignment_t* assignment) {
- Assignment *self;
- self = (Assignment*)AssignmentType.tp_alloc(&AssignmentType, 0);
- if (self != NULL) {
- self->assignment = assignment;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-Assignment_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyAssignment_create(0);
-}
-
-static int
-Assignment_init(Assignment* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 0) {
- self->assignment = lp_assignment_new(Variable_get_default_db());
- } else {
- return -1;
- }
- return 0;
-}
-
-static void
-Assignment_dealloc(Assignment* self)
-{
- if (self->assignment) {
- lp_assignment_delete(self->assignment);
- }
- self->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject* Assignment_str(PyObject* self) {
- Assignment* a = (Assignment*) self;
- char* a_str = lp_assignment_to_string(a->assignment);
- PyObject* str = PyString_FromString(a_str);
- free(a_str);
- return str;
-}
-
-static PyObject*
-Assignment_get_value(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* var_obj = PyTuple_GetItem(args, 0);
- if (PyVariable_CHECK(var_obj)) {
- Variable* var = (Variable*) var_obj;
- Assignment* a = (Assignment*) self;
- const lp_value_t* value = lp_assignment_get_value(a->assignment, var->x);
- switch (value->type) {
- case LP_VALUE_ALGEBRAIC:
- return 0;
- break;
- case LP_VALUE_DYADIC_RATIONAL:
- return dyadic_rational_to_PyFloat(&value->value.dy_q);
- break;
- case LP_VALUE_NONE:
- Py_RETURN_NONE;
- break;
- case LP_VALUE_RATIONAL:
- return 0;
- break;
- default:
- return 0;
- }
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static PyObject*
-Assignment_set_value(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) == 2) {
- PyObject* var_obj = PyTuple_GetItem(args, 0);
- PyObject* value_obj = PyTuple_GetItem(args, 1);
- if (PyVariable_CHECK(var_obj)) {
- Assignment* a = (Assignment*) self;
- Variable* var = (Variable*) var_obj;
- if (PyFloat_Check(value_obj)) {
- lp_dyadic_rational_t value_dyrat;
- PyFloat_to_dyadic_rational(value_obj, &value_dyrat);
- lp_value_t value;
- lp_value_construct(&value, LP_VALUE_DYADIC_RATIONAL, &value_dyrat);
- lp_assignment_set_value(a->assignment, var->x, &value);
- lp_value_destruct(&value);
- lp_dyadic_rational_destruct(&value_dyrat);
- Py_RETURN_NONE;
- } else if (PyLong_or_Int_Check(value_obj)) {
- lp_integer_t value_int;
- PyLong_or_Int_to_integer(value_obj, lp_Z, &value_int);
- lp_dyadic_rational_t value_dyrat;
- lp_dyadic_rational_construct_from_integer(&value_dyrat, &value_int);
- lp_value_t value;
- lp_value_construct(&value, LP_VALUE_DYADIC_RATIONAL, &value_dyrat);
- lp_assignment_set_value(a->assignment, var->x, &value);
- lp_value_destruct(&value);
- lp_dyadic_rational_destruct(&value_dyrat);
- lp_integer_destruct(&value_int);
- Py_RETURN_NONE;
- } else if (PyAlgebraicNumber_CHECK(value_obj)) {
- lp_value_t value;
- lp_value_construct(&value, LP_VALUE_ALGEBRAIC, &((AlgebraicNumber*) value_obj)->a);
- lp_assignment_set_value(a->assignment, var->x, &value);
- lp_value_destruct(&value);
- Py_RETURN_NONE;
- } else if (PyValue_CHECK(value_obj)) {
- Value* value = (Value*) value_obj;
- lp_assignment_set_value(a->assignment, var->x, &value->v);
- Py_RETURN_NONE;
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): not a value.");
- return NULL;
- }
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): not a variable.");
- return NULL;
- }
- } else if (PyTuple_Size(args) == 3) {
- // Three arguments, rational
- PyObject* var_obj = PyTuple_GetItem(args, 0);
- PyObject* p_obj = PyTuple_GetItem(args, 1);
- PyObject* q_obj = PyTuple_GetItem(args, 2);
- if (PyLong_or_Int_Check(p_obj) && PyLong_or_Int_Check(q_obj)) {
- Assignment* a = (Assignment*) self;
- Variable* var = (Variable*) var_obj;
- lp_integer_t p_int, q_int;
- PyLong_or_Int_to_integer(p_obj, lp_Z, &p_int);
- PyLong_or_Int_to_integer(q_obj, lp_Z, &q_int);
- lp_rational_t value_rat;
- lp_rational_construct_from_div(&value_rat, &p_int, &q_int);
- lp_value_t value;
- lp_value_construct(&value, LP_VALUE_RATIONAL, &value_rat);
- lp_assignment_set_value(a->assignment, var->x, &value);
- lp_value_destruct(&value);
- lp_rational_destruct(&value_rat);
- lp_integer_destruct(&p_int);
- lp_integer_destruct(&q_int);
- Py_RETURN_NONE;
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): for rationals, both numerator and denominator must be integer.");
- return NULL;
- }
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): need two or three arguments.");
- return NULL;
- }
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): need two or three arguments.");
- return NULL;
- }
-}
-
-static PyObject*
-Assignment_unset_value(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* var_obj = PyTuple_GetItem(args, 0);
- if (PyVariable_CHECK(var_obj)) {
- Variable* var = (Variable*) var_obj;
- Assignment* a = (Assignment*) self;
- lp_assignment_set_value(a->assignment, var->x, 0);
- Py_RETURN_NONE;
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): not a variable.");
- return NULL;
- }
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): need one argument.");
- return NULL;
- }
-}
diff --git a/python/polypyAssignment3.c b/python/polypyAssignment3.c
deleted file mode 100644
index db5b147c..00000000
--- a/python/polypyAssignment3.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/**
- * 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 "polypyAssignment.h"
-#include "polypyVariable.h"
-#include "utils.h"
-#include "polypyAlgebraicNumber.h"
-#include "polypyValue.h"
-
-#include
-
-/** Default variable database */
-static lp_assignment_t* default_assignment = 0;
-
-lp_assignment_t* Assignment_get_default_assignment(void) {
- if (!default_assignment) {
- default_assignment = lp_assignment_new(Variable_get_default_db());
- }
- return default_assignment;
-}
-
-static PyObject*
-Assignment_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-Assignment_init(Assignment* self, PyObject* args);
-
-static void
-Assignment_dealloc(Assignment* self);
-
-static PyObject*
-Assignment_str(PyObject* self);
-
-static PyObject*
-Assignment_get_value(PyObject* self, PyObject* args);
-
-static PyObject*
-Assignment_set_value(PyObject* self, PyObject* args);
-
-static PyObject*
-Assignment_unset_value(PyObject* self, PyObject* args);
-
-PyMethodDef Assignment_methods[] = {
- {"get_value", (PyCFunction)Assignment_get_value, METH_VARARGS, "Returns the value of the variable"},
- {"set_value", (PyCFunction)Assignment_set_value, METH_VARARGS, "Sets the value of the variable"},
- {"unset_value", (PyCFunction)Assignment_unset_value, METH_VARARGS, "Marks the variable as unassigned"},
- {NULL} /* Sentinel */
-};
-
-
-PyTypeObject AssignmentType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.Assignment", // const char *tp_name;
- sizeof(Variable), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)Assignment_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async;
- 0, // reprfunc tp_repr;
- 0, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- 0, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- Assignment_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "Variable objects", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- 0, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- Assignment_methods, // struct PyMethodDef *tp_methods;
- 0, // struct PyMemberDef *tp_members;
- 0, // struct PyGetSetDef *tp_getset;
- 0, // struct _typeobject *tp_base;
- 0, // PyObject *tp_dict;
- 0, // descrgetfunc tp_descr_get;
- 0, // descrsetfunc tp_descr_set;
- 0, // Py_ssize_t tp_dictoffset;
- (initproc)Assignment_init, // initproc tp_init;
- 0, // allocfunc tp_alloc;
- Assignment_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-PyObject*
-PyAssignment_create(lp_assignment_t* assignment) {
- Assignment *self;
- self = (Assignment*)AssignmentType.tp_alloc(&AssignmentType, 0);
- if (self != NULL) {
- self->assignment = assignment;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-Assignment_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyAssignment_create(0);
-}
-
-static int
-Assignment_init(Assignment* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 0) {
- self->assignment = lp_assignment_new(Variable_get_default_db());
- } else {
- return -1;
- }
- return 0;
-}
-
-static void
-Assignment_dealloc(Assignment* self)
-{
- if (self->assignment) {
- lp_assignment_delete(self->assignment);
- }
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject* Assignment_str(PyObject* self) {
- Assignment* a = (Assignment*) self;
- char* a_str = lp_assignment_to_string(a->assignment);
- PyObject* str = PyUnicode_FromString(a_str);
- free(a_str);
- return str;
-}
-
-static PyObject*
-Assignment_get_value(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* var_obj = PyTuple_GetItem(args, 0);
- if (PyVariable_CHECK(var_obj)) {
- Variable* var = (Variable*) var_obj;
- Assignment* a = (Assignment*) self;
- const lp_value_t* value = lp_assignment_get_value(a->assignment, var->x);
- switch (value->type) {
- case LP_VALUE_ALGEBRAIC:
- return 0;
- break;
- case LP_VALUE_DYADIC_RATIONAL:
- return dyadic_rational_to_PyFloat(&value->value.dy_q);
- break;
- case LP_VALUE_NONE:
- Py_RETURN_NONE;
- break;
- case LP_VALUE_RATIONAL:
- return 0;
- break;
- default:
- return 0;
- }
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static PyObject*
-Assignment_set_value(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) == 2) {
- PyObject* var_obj = PyTuple_GetItem(args, 0);
- PyObject* value_obj = PyTuple_GetItem(args, 1);
- if (PyVariable_CHECK(var_obj)) {
- Assignment* a = (Assignment*) self;
- Variable* var = (Variable*) var_obj;
- if (PyFloat_Check(value_obj)) {
- lp_dyadic_rational_t value_dyrat;
- PyFloat_to_dyadic_rational(value_obj, &value_dyrat);
- lp_value_t value;
- lp_value_construct(&value, LP_VALUE_DYADIC_RATIONAL, &value_dyrat);
- lp_assignment_set_value(a->assignment, var->x, &value);
- lp_value_destruct(&value);
- lp_dyadic_rational_destruct(&value_dyrat);
- Py_RETURN_NONE;
- } else if (PyLong_or_Int_Check(value_obj)) {
- lp_integer_t value_int;
- PyLong_or_Int_to_integer(value_obj, lp_Z, &value_int);
- lp_dyadic_rational_t value_dyrat;
- lp_dyadic_rational_construct_from_integer(&value_dyrat, &value_int);
- lp_value_t value;
- lp_value_construct(&value, LP_VALUE_DYADIC_RATIONAL, &value_dyrat);
- lp_assignment_set_value(a->assignment, var->x, &value);
- lp_value_destruct(&value);
- lp_dyadic_rational_destruct(&value_dyrat);
- lp_integer_destruct(&value_int);
- Py_RETURN_NONE;
- } else if (PyAlgebraicNumber_CHECK(value_obj)) {
- lp_value_t value;
- lp_value_construct(&value, LP_VALUE_ALGEBRAIC, &((AlgebraicNumber*) value_obj)->a);
- lp_assignment_set_value(a->assignment, var->x, &value);
- lp_value_destruct(&value);
- Py_RETURN_NONE;
- } else if (PyValue_CHECK(value_obj)) {
- Value* value = (Value*) value_obj;
- lp_assignment_set_value(a->assignment, var->x, &value->v);
- Py_RETURN_NONE;
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): not a value.");
- return NULL;
- }
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): not a variable.");
- return NULL;
- }
- } else if (PyTuple_Size(args) == 3) {
- // Three arguments, rational
- PyObject* var_obj = PyTuple_GetItem(args, 0);
- PyObject* p_obj = PyTuple_GetItem(args, 1);
- PyObject* q_obj = PyTuple_GetItem(args, 2);
- if (PyLong_or_Int_Check(p_obj) && PyLong_or_Int_Check(q_obj)) {
- Assignment* a = (Assignment*) self;
- Variable* var = (Variable*) var_obj;
- lp_integer_t p_int, q_int;
- PyLong_or_Int_to_integer(p_obj, lp_Z, &p_int);
- PyLong_or_Int_to_integer(q_obj, lp_Z, &q_int);
- lp_rational_t value_rat;
- lp_rational_construct_from_div(&value_rat, &p_int, &q_int);
- lp_value_t value;
- lp_value_construct(&value, LP_VALUE_RATIONAL, &value_rat);
- lp_assignment_set_value(a->assignment, var->x, &value);
- lp_value_destruct(&value);
- lp_rational_destruct(&value_rat);
- lp_integer_destruct(&p_int);
- lp_integer_destruct(&q_int);
- Py_RETURN_NONE;
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): for rationals, both numerator and denominator must be integer.");
- return NULL;
- }
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): need two or three arguments.");
- return NULL;
- }
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): need two or three arguments.");
- return NULL;
- }
-}
-
-static PyObject*
-Assignment_unset_value(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* var_obj = PyTuple_GetItem(args, 0);
- if (PyVariable_CHECK(var_obj)) {
- Variable* var = (Variable*) var_obj;
- Assignment* a = (Assignment*) self;
- lp_assignment_set_value(a->assignment, var->x, 0);
- Py_RETURN_NONE;
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): not a variable.");
- return NULL;
- }
- } else {
- PyErr_SetString(PyExc_RuntimeError, "set_value(): need one argument.");
- return NULL;
- }
-}
diff --git a/python/polypyFeasibilitySet.c b/python/polypyFeasibilitySet.c
index 11d23b92..8b90b201 100644
--- a/python/polypyFeasibilitySet.c
+++ b/python/polypyFeasibilitySet.c
@@ -17,11 +17,199 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include "Python.h"
-
-#if PY_MAJOR_VERSION >= 3
-#include "polypyFeasibilitySet3.c"
-#else
-#include "polypyFeasibilitySet2.c"
-#endif
+#include "python.h"
+
+#include "polypyFeasibilitySet.h"
+#include "polypyValue.h"
+
+static void
+FeasibilitySet_dealloc(FeasibilitySet* self);
+
+static PyObject*
+FeasibilitySet_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static int
+FeasibilitySet_init(FeasibilitySet* self, PyObject* args);
+
+static PyObject*
+FeasibilitySet_str(PyObject* self);
+
+static PyObject*
+FeasibilitySet_pick_value(PyObject* self);
+
+static PyObject*
+FeasibilitySet_intersect(PyObject* self, PyObject* args);
+
+static PyObject*
+FeasibilitySet_contains_value(PyObject* self, PyObject* args);
+
+static PyObject*
+FeasibilitySet_contains_int(PyObject* self);
+
+PyMethodDef FeasibilitySet_methods[] = {
+ {"pick_value", (PyCFunction)FeasibilitySet_pick_value, METH_NOARGS, "Returns a value from the interval."},
+ {"intersect", (PyCFunction)FeasibilitySet_intersect, METH_VARARGS, "Returns the intersection of the set with another one."},
+ {"contains", (PyCFunction)FeasibilitySet_contains_value, METH_VARARGS, "Returns true if the value is in the feasibility set."},
+ {"contains_int", (PyCFunction)FeasibilitySet_contains_int, METH_NOARGS, "Returns true if the set contains an integer value."},
+ {NULL} /* Sentinel */
+};
+
+PyTypeObject FeasibilitySetType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.FeasibilitySet", // const char *tp_name;
+ sizeof(FeasibilitySet), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)FeasibilitySet_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async;
+ FeasibilitySet_str, // reprfunc tp_repr;
+ NULL, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ NULL, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ FeasibilitySet_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "FeasibilitySet objects", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ NULL, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ FeasibilitySet_methods, // struct PyMethodDef *tp_methods;
+ NULL, // struct PyMemberDef *tp_members;
+ NULL, // struct PyGetSetDef *tp_getset;
+ NULL, // struct _typeobject *tp_base;
+ NULL, // PyObject *tp_dict;
+ NULL, // descrgetfunc tp_descr_get;
+ NULL, // descrsetfunc tp_descr_set;
+ 0, // Py_ssize_t tp_dictoffset;
+ (initproc)FeasibilitySet_init, // initproc tp_init;
+ NULL, // allocfunc tp_alloc;
+ FeasibilitySet_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+static void
+FeasibilitySet_dealloc(FeasibilitySet* self) {
+ lp_feasibility_set_delete(self->S);
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+PyObject*
+PyFeasibilitySet_create(lp_feasibility_set_t* S) {
+ FeasibilitySet *self;
+ self = (FeasibilitySet*)FeasibilitySetType.tp_alloc(&FeasibilitySetType, 0);
+ if (self != NULL) {
+ self->S = S;
+ }
+ return (PyObject *)self;
+}
+
+static PyObject*
+FeasibilitySet_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return PyFeasibilitySet_create(NULL);
+}
+
+static int
+FeasibilitySet_init(FeasibilitySet* self, PyObject* args) {
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 0) {
+ // Defaults to (-inf, +inf)
+ self->S = lp_feasibility_set_new_full();
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static PyObject* FeasibilitySet_str(PyObject* self) {
+ FeasibilitySet* S = (FeasibilitySet*) self;
+ char* I_str = lp_feasibility_set_to_string(S->S);
+ PyObject* str = PyUnicode_FromString(I_str);
+ free(I_str);
+ return str;
+}
+
+static PyObject*
+FeasibilitySet_pick_value(PyObject* self) {
+ FeasibilitySet* S = (FeasibilitySet*) self;
+ lp_value_t v;
+ lp_value_construct_none(&v);
+ lp_feasibility_set_pick_value(S->S, &v);
+ PyObject* result = PyValue_create(&v);
+ lp_value_destruct(&v);
+ return result;
+}
+
+static PyObject*
+FeasibilitySet_intersect(PyObject* self, PyObject* args) {
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* feasibility_set_obj = PyTuple_GetItem(args, 0);
+ if (!PyFeasibilitySet_CHECK(feasibility_set_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Get the arguments
+ lp_feasibility_set_t* S1 = ((FeasibilitySet*) self)->S;
+ lp_feasibility_set_t* S2 = ((FeasibilitySet*) feasibility_set_obj)->S;
+
+ // The intersection
+ lp_feasibility_set_t* P = lp_feasibility_set_intersect(S1, S2);
+ PyObject* P_obj = PyFeasibilitySet_create(P);
+
+ return P_obj;
+}
+
+static PyObject*
+FeasibilitySet_contains_value(PyObject* self, PyObject* args) {
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* value_obj = PyTuple_GetItem(args, 0);
+
+ if (!PyValue_CHECK(value_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ lp_feasibility_set_t* S = ((FeasibilitySet*) self)->S;
+ lp_value_t* v = &((Value*) value_obj)->v;
+
+ int result = lp_feasibility_set_contains(S, v);
+
+ PyObject* result_object = result ? Py_True : Py_False;
+ Py_INCREF(result_object);
+ return result_object;
+}
+
+static PyObject*
+FeasibilitySet_contains_int(PyObject* self) {
+ lp_feasibility_set_t* S = ((FeasibilitySet*) self)->S;
+ PyObject* result_object = lp_feasibility_set_contains_int(S) ? Py_True : Py_False;
+ Py_INCREF(result_object);
+ return result_object;
+}
diff --git a/python/polypyFeasibilitySet.h b/python/polypyFeasibilitySet.h
index 94b7d51d..b937237b 100644
--- a/python/polypyFeasibilitySet.h
+++ b/python/polypyFeasibilitySet.h
@@ -19,8 +19,7 @@
#pragma once
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include "feasibility_set.h"
diff --git a/python/polypyFeasibilitySet2.c b/python/polypyFeasibilitySet2.c
deleted file mode 100644
index 3705d8c1..00000000
--- a/python/polypyFeasibilitySet2.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/**
- * 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 "polypyFeasibilitySet.h"
-#include "polypyValue.h"
-
-#include
-
-static void
-FeasibilitySet_dealloc(FeasibilitySet* self);
-
-static PyObject*
-FeasibilitySet_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-FeasibilitySet_init(FeasibilitySet* self, PyObject* args);
-
-static PyObject*
-FeasibilitySet_str(PyObject* self);
-
-static PyObject*
-FeasibilitySet_pick_value(PyObject* self);
-
-static PyObject*
-FeasibilitySet_intersect(PyObject* self, PyObject* args);
-
-static PyObject*
-FeasibilitySet_contains_value(PyObject* self, PyObject* args);
-
-static PyObject*
-FeasibilitySet_contains_int(PyObject* self);
-
-PyMethodDef FeasibilitySet_methods[] = {
- {"pick_value", (PyCFunction)FeasibilitySet_pick_value, METH_NOARGS, "Returns a value from the interval."},
- {"intersect", (PyCFunction)FeasibilitySet_intersect, METH_VARARGS, "Returns the intersection of the set with another one."},
- {"contains", (PyCFunction)FeasibilitySet_contains_value, METH_VARARGS, "Returns true if the value is in the feasibility set."},
- {"contains_int", (PyCFunction)FeasibilitySet_contains_int, METH_NOARGS, "Returns true if the set contains an integer value."},
- {NULL} /* Sentinel */
-};
-
-PyTypeObject FeasibilitySetType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.FeasibilitySet", /*tp_name*/
- sizeof(FeasibilitySet), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)FeasibilitySet_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0 , /*tp_compare*/
- FeasibilitySet_str, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- FeasibilitySet_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "FeasibilitySet objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- FeasibilitySet_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)FeasibilitySet_init,/* tp_init */
- 0, /* tp_alloc */
- FeasibilitySet_new, /* tp_new */
-};
-
-static void
-FeasibilitySet_dealloc(FeasibilitySet* self)
-{
- lp_feasibility_set_delete(self->S);
- self->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyFeasibilitySet_create(lp_feasibility_set_t* S) {
- FeasibilitySet *self;
- self = (FeasibilitySet*)FeasibilitySetType.tp_alloc(&FeasibilitySetType, 0);
- if (self != NULL) {
- self->S = S;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-FeasibilitySet_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyFeasibilitySet_create(0);
-}
-
-static int
-FeasibilitySet_init(FeasibilitySet* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 0) {
- // Defaults to (-inf, +inf)
- self->S = lp_feasibility_set_new_full();
- } else {
- return -1;
- }
- return 0;
-}
-
-static PyObject* FeasibilitySet_str(PyObject* self) {
- FeasibilitySet* S = (FeasibilitySet*) self;
- char* I_str = lp_feasibility_set_to_string(S->S);
- PyObject* str = PyString_FromString(I_str);
- free(I_str);
- return str;
-}
-
-static PyObject*
-FeasibilitySet_pick_value(PyObject* self) {
- FeasibilitySet* S = (FeasibilitySet*) self;
- lp_value_t v;
- lp_value_construct_none(&v);
- lp_feasibility_set_pick_value(S->S, &v);
- PyObject* result = PyValue_create(&v);
- lp_value_destruct(&v);
- return result;
-}
-
-static PyObject*
-FeasibilitySet_intersect(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* feasibility_set_obj = PyTuple_GetItem(args, 0);
- if (!PyFeasibilitySet_CHECK(feasibility_set_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Get the arguments
- lp_feasibility_set_t* S1 = ((FeasibilitySet*) self)->S;
- lp_feasibility_set_t* S2 = ((FeasibilitySet*) feasibility_set_obj)->S;
-
- // The intersection
- lp_feasibility_set_t* P = lp_feasibility_set_intersect(S1, S2);
- PyObject* P_obj = PyFeasibilitySet_create(P);
-
- return P_obj;
-}
-
-static PyObject*
-FeasibilitySet_contains_value(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* value_obj = PyTuple_GetItem(args, 0);
-
- if (!PyValue_CHECK(value_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_feasibility_set_t* S = ((FeasibilitySet*) self)->S;
- lp_value_t* v = &((Value*) value_obj)->v;
-
- int result = lp_feasibility_set_contains(S, v);
-
- PyObject* result_object = result ? Py_True : Py_False;
- Py_INCREF(result_object);
- return result_object;
-}
-
-static PyObject*
-FeasibilitySet_contains_int(PyObject* self) {
- lp_feasibility_set_t* S = ((FeasibilitySet*) self)->S;
- PyObject* result_object = lp_feasibility_set_contains_int(S) ? Py_True : Py_False;
- Py_INCREF(result_object);
- return result_object;
-}
diff --git a/python/polypyFeasibilitySet3.c b/python/polypyFeasibilitySet3.c
deleted file mode 100644
index 979d4f11..00000000
--- a/python/polypyFeasibilitySet3.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * 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 "polypyFeasibilitySet.h"
-#include "polypyValue.h"
-
-#include
-
-static void
-FeasibilitySet_dealloc(FeasibilitySet* self);
-
-static PyObject*
-FeasibilitySet_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-FeasibilitySet_init(FeasibilitySet* self, PyObject* args);
-
-static PyObject*
-FeasibilitySet_str(PyObject* self);
-
-static PyObject*
-FeasibilitySet_pick_value(PyObject* self);
-
-static PyObject*
-FeasibilitySet_intersect(PyObject* self, PyObject* args);
-
-static PyObject*
-FeasibilitySet_contains_value(PyObject* self, PyObject* args);
-
-static PyObject*
-FeasibilitySet_contains_int(PyObject* self);
-
-PyMethodDef FeasibilitySet_methods[] = {
- {"pick_value", (PyCFunction)FeasibilitySet_pick_value, METH_NOARGS, "Returns a value from the interval."},
- {"intersect", (PyCFunction)FeasibilitySet_intersect, METH_VARARGS, "Returns the intersection of the set with another one."},
- {"contains", (PyCFunction)FeasibilitySet_contains_value, METH_VARARGS, "Returns true if the value is in the feasibility set."},
- {"contains_int", (PyCFunction)FeasibilitySet_contains_int, METH_NOARGS, "Returns true if the set contains an integer value."},
- {NULL} /* Sentinel */
-};
-
-PyTypeObject FeasibilitySetType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.FeasibilitySet", // const char *tp_name;
- sizeof(FeasibilitySet), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)FeasibilitySet_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async;
- FeasibilitySet_str, // reprfunc tp_repr;
- 0, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- 0, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- FeasibilitySet_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "FeasibilitySet objects", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- 0, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- FeasibilitySet_methods, // struct PyMethodDef *tp_methods;
- 0, // struct PyMemberDef *tp_members;
- 0, // struct PyGetSetDef *tp_getset;
- 0, // struct _typeobject *tp_base;
- 0, // PyObject *tp_dict;
- 0, // descrgetfunc tp_descr_get;
- 0, // descrsetfunc tp_descr_set;
- 0, // Py_ssize_t tp_dictoffset;
- (initproc)FeasibilitySet_init, // initproc tp_init;
- 0, // allocfunc tp_alloc;
- FeasibilitySet_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-static void
-FeasibilitySet_dealloc(FeasibilitySet* self) {
- lp_feasibility_set_delete(self->S);
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyFeasibilitySet_create(lp_feasibility_set_t* S) {
- FeasibilitySet *self;
- self = (FeasibilitySet*)FeasibilitySetType.tp_alloc(&FeasibilitySetType, 0);
- if (self != NULL) {
- self->S = S;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-FeasibilitySet_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyFeasibilitySet_create(0);
-}
-
-static int
-FeasibilitySet_init(FeasibilitySet* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 0) {
- // Defaults to (-inf, +inf)
- self->S = lp_feasibility_set_new_full();
- } else {
- return -1;
- }
- return 0;
-}
-
-static PyObject* FeasibilitySet_str(PyObject* self) {
- FeasibilitySet* S = (FeasibilitySet*) self;
- char* I_str = lp_feasibility_set_to_string(S->S);
- PyObject* str = PyUnicode_FromString(I_str);
- free(I_str);
- return str;
-}
-
-static PyObject*
-FeasibilitySet_pick_value(PyObject* self) {
- FeasibilitySet* S = (FeasibilitySet*) self;
- lp_value_t v;
- lp_value_construct_none(&v);
- lp_feasibility_set_pick_value(S->S, &v);
- PyObject* result = PyValue_create(&v);
- lp_value_destruct(&v);
- return result;
-}
-
-static PyObject*
-FeasibilitySet_intersect(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* feasibility_set_obj = PyTuple_GetItem(args, 0);
- if (!PyFeasibilitySet_CHECK(feasibility_set_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Get the arguments
- lp_feasibility_set_t* S1 = ((FeasibilitySet*) self)->S;
- lp_feasibility_set_t* S2 = ((FeasibilitySet*) feasibility_set_obj)->S;
-
- // The intersection
- lp_feasibility_set_t* P = lp_feasibility_set_intersect(S1, S2);
- PyObject* P_obj = PyFeasibilitySet_create(P);
-
- return P_obj;
-}
-
-static PyObject*
-FeasibilitySet_contains_value(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* value_obj = PyTuple_GetItem(args, 0);
-
- if (!PyValue_CHECK(value_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_feasibility_set_t* S = ((FeasibilitySet*) self)->S;
- lp_value_t* v = &((Value*) value_obj)->v;
-
- int result = lp_feasibility_set_contains(S, v);
-
- PyObject* result_object = result ? Py_True : Py_False;
- Py_INCREF(result_object);
- return result_object;
-}
-
-static PyObject*
-FeasibilitySet_contains_int(PyObject* self) {
- lp_feasibility_set_t* S = ((FeasibilitySet*) self)->S;
- PyObject* result_object = lp_feasibility_set_contains_int(S) ? Py_True : Py_False;
- Py_INCREF(result_object);
- return result_object;
-}
diff --git a/python/polypyInteger.c b/python/polypyInteger.c
index f782b964..1c9aa4b8 100644
--- a/python/polypyInteger.c
+++ b/python/polypyInteger.c
@@ -17,11 +17,248 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include
-
-#if PY_MAJOR_VERSION >= 3
-#include "polypyInteger3.c"
-#else
-#include "polypyInteger2.c"
-#endif
+#include "python.h"
+
+#include "polypyInteger.h"
+#include "utils.h"
+
+static void
+CoefficientRing_dealloc(CoefficientRing* self);
+
+static PyObject*
+CoefficientRing_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static int
+CoefficientRing_init(CoefficientRing* self, PyObject* args);
+
+static PyObject*
+CoefficientRing_modulus(PyObject* self);
+
+static PyObject*
+CoefficientRing_str(PyObject* self);
+
+static PyObject *
+CoefficientRing_richcompare(PyObject *self, PyObject *other, int op);
+
+PyMethodDef CoefficientRing_methods[] = {
+ {"modulus", (PyCFunction)CoefficientRing_modulus, METH_NOARGS, "Returns the degree of the polynomial"},
+ {NULL} /* Sentinel */
+};
+
+PyTypeObject CoefficientRingType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.CoefficientRing", // const char *tp_name;
+ sizeof(CoefficientRing), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)CoefficientRing_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async;
+ NULL, // reprfunc tp_repr;
+ NULL, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ NULL, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ CoefficientRing_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "Coefficient ring objects", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ CoefficientRing_richcompare, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ CoefficientRing_methods, // struct PyMethodDef *tp_methods;
+ NULL, // struct PyMemberDef *tp_members;
+ NULL, // struct PyGetSetDef *tp_getset;
+ NULL, // struct _typeobject *tp_base;
+ NULL, // PyObject *tp_dict;
+ NULL, // descrgetfunc tp_descr_get;
+ NULL, // descrsetfunc tp_descr_set;
+ 0, // Py_ssize_t tp_dictoffset;
+ (initproc)CoefficientRing_init, // initproc tp_init;
+ NULL, // allocfunc tp_alloc;
+ CoefficientRing_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+static void
+CoefficientRing_dealloc(CoefficientRing* self)
+{
+ if (self->K) lp_int_ring_detach(self->K);
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+PyObject*
+PyCoefficientRing_create(lp_int_ring_t* K) {
+ CoefficientRing *self;
+ self = (CoefficientRing*)CoefficientRingType.tp_alloc(&CoefficientRingType, 0);
+ if (self != NULL) {
+ self->K = (lp_int_ring_t*)K;
+ }
+ return (PyObject *)self;
+}
+
+static PyObject*
+CoefficientRing_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return PyCoefficientRing_create(NULL);
+}
+
+
+static int
+CoefficientRing_init(CoefficientRing* self, PyObject* args)
+{
+ if (PyTuple_Check(args)) {
+ if (PyTuple_Size(args) == 0) {
+ // Defaults to Z
+ self->K = lp_Z;
+ } else if (PyTuple_Size(args) == 1) {
+ // Get the list of coefficients
+ PyObject* modulus = PyTuple_GetItem(args, 0);
+ if (!PyLong_Check(modulus)) {
+ if (!PyLong_Check(modulus)) {
+ return -1;
+ } else {
+ long M_int = PyLong_AsLong(modulus);
+ lp_integer_t M;
+ lp_integer_construct_from_int(lp_Z, &M, M_int);
+ int is_prime = lp_integer_is_prime(&M);
+ self->K = lp_int_ring_create(&M, is_prime);
+ lp_integer_destruct(&M);
+ }
+ } else {
+ int overflow = 0;
+ long M_int = PyLong_AsLongAndOverflow(modulus, &overflow);
+ if (overflow) {
+ const char* M_cstr = pythonObject2CharStar(modulus);
+ lp_integer_t M;
+ lp_integer_construct_from_string(lp_Z, &M, M_cstr, 10);
+ int is_prime = lp_integer_is_prime(&M);
+ self->K = lp_int_ring_create(&M, is_prime);
+ } else if (M_int > 0) {
+ lp_integer_t M;
+ lp_integer_construct_from_int(lp_Z, &M, M_int);
+ int is_prime = lp_integer_is_prime(&M);
+ self->K = lp_int_ring_create(&M, is_prime);
+ } else {
+ return -1;
+ }
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
+
+static PyObject*
+CoefficientRing_modulus(PyObject* self) {
+ CoefficientRing* K = (CoefficientRing*) self;
+ if (K && K->K) {
+ char* K_str = lp_integer_to_string(&K->K->M);
+ char* p = NULL;
+ PyObject* M = PyLong_FromString(K_str, &p, 10);
+ free(K_str);
+ return M;
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject* CoefficientRing_str(PyObject* self) {
+ CoefficientRing* K = (CoefficientRing*) self;
+ if (K) {
+ if (K->K) {
+ char* K_str = lp_int_ring_to_string(K->K);
+ PyObject* str = PyUnicode_FromString(K_str);
+ free(K_str);
+ return str;
+ } else {
+ return PyUnicode_FromString("Z");
+ }
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject *
+CoefficientRing_richcompare(PyObject *self, PyObject *other, int op){
+ PyObject *result = Py_NotImplemented;
+
+ if(!PyCoefficientRing_CHECK(other)){
+ //IAM: Unless I am violating some sacrosanct python contract, this seems like a no-brainer.
+ if(op == Py_EQ){ return Py_False; }
+ if(op == Py_NE){ return Py_True; }
+ } else {
+ // Get arguments
+ CoefficientRing* K1 = (CoefficientRing*) self;
+ CoefficientRing* K2 = (CoefficientRing*) other;
+
+ //Are they equal?
+ if (K1->K == K2->K) {
+ if( op == Py_LE || op == Py_EQ || op == Py_GE){
+ return Py_True;
+ }
+ return Py_False;
+ }
+
+ // Is one of them Z
+ if (K1->K == lp_Z) {
+ // self > other
+ if( op == Py_LT || op == Py_LE || op == Py_EQ){
+ return Py_False;
+ }
+ return Py_True;
+ }
+ if (K2->K == lp_Z) {
+ //self < other
+ if( op == Py_LT || op == Py_LE){
+ return Py_True;
+ }
+ return Py_False;
+ }
+
+ int cmp = lp_integer_cmp(lp_Z, &K1->K->M, &K2->K->M);
+
+ switch (op) {
+ case Py_LT:
+ result = cmp < 0 ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ result = cmp <= 0 ? Py_True : Py_False;
+ break;
+ case Py_EQ:
+ result = cmp == 0 ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = cmp != 0 ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ result = cmp > 0 ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ result = cmp >= 0 ? Py_True : Py_False;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ return result;
+}
diff --git a/python/polypyInteger.h b/python/polypyInteger.h
index e4485145..bb872119 100644
--- a/python/polypyInteger.h
+++ b/python/polypyInteger.h
@@ -19,8 +19,7 @@
#pragma once
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include "integer.h"
diff --git a/python/polypyInteger2.c b/python/polypyInteger2.c
deleted file mode 100644
index 06c369f3..00000000
--- a/python/polypyInteger2.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * 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 "polypyInteger.h"
-
-#include
-
-static void
-CoefficientRing_dealloc(CoefficientRing* self);
-
-static PyObject*
-CoefficientRing_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-CoefficientRing_init(CoefficientRing* self, PyObject* args);
-
-static int
-CoefficientRing_cmp(PyObject* self, PyObject* args);
-
-static PyObject*
-CoefficientRing_modulus(PyObject* self);
-
-static PyObject*
-CoefficientRing_str(PyObject* self);
-
-PyMethodDef CoefficientRing_methods[] = {
- {"modulus", (PyCFunction)CoefficientRing_modulus, METH_NOARGS, "Returns the degree of the polynomial"},
- {NULL} /* Sentinel */
-};
-
-PyTypeObject CoefficientRingType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.CoefficientRing", /*tp_name*/
- sizeof(CoefficientRing), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)CoefficientRing_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- CoefficientRing_cmp, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- CoefficientRing_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "Coefficient ring objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- CoefficientRing_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)CoefficientRing_init,/* tp_init */
- 0, /* tp_alloc */
- CoefficientRing_new, /* tp_new */
-};
-
-static void
-CoefficientRing_dealloc(CoefficientRing* self)
-{
- if (self->K) lp_int_ring_detach(self->K);
- self->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyCoefficientRing_create(lp_int_ring_t* K) {
- CoefficientRing *self;
- self = (CoefficientRing*)CoefficientRingType.tp_alloc(&CoefficientRingType, 0);
- if (self != NULL) {
- self->K = K;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-CoefficientRing_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyCoefficientRing_create(0);
-}
-
-static int
-CoefficientRing_init(CoefficientRing* self, PyObject* args)
-{
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) == 0) {
- // Defaults to Z
- self->K = lp_Z;
- } else if (PyTuple_Size(args) == 1) {
- // Get the list of coefficients
- PyObject* modulus = PyTuple_GetItem(args, 0);
- if (!PyLong_Check(modulus)) {
- if (!PyInt_Check(modulus)) {
- return -1;
- } else {
- long M_int = PyInt_AsLong(modulus);
- lp_integer_t M;
- lp_integer_construct_from_int(lp_Z, &M, M_int);
- int is_prime = lp_integer_is_prime(&M);
- self->K = lp_int_ring_create(&M, is_prime);
- lp_integer_destruct(&M);
- }
- } else {
- int overflow = 0;
- long M_int = PyLong_AsLongAndOverflow(modulus, &overflow);
- if (overflow) {
- PyObject* M_str = PyObject_Str(modulus);
- char* M_cstr = PyString_AsString(M_str);
- lp_integer_t M;
- lp_integer_construct_from_string(lp_Z, &M, M_cstr, 10);
- int is_prime = lp_integer_is_prime(&M);
- self->K = lp_int_ring_create(&M, is_prime);
- Py_DECREF(M_str);
- } else if (M_int > 0) {
- lp_integer_t M;
- lp_integer_construct_from_int(lp_Z, &M, M_int);
- int is_prime = lp_integer_is_prime(&M);
- self->K = lp_int_ring_create(&M, is_prime);
- } else {
- return -1;
- }
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-
- return 0;
-}
-
-static int
-CoefficientRing_cmp(PyObject* self, PyObject* other) {
- // Check arguments
- if (!PyCoefficientRing_CHECK(self) || !PyCoefficientRing_CHECK(other)) {
- // should return -1 and set an exception condition when an error occurred
- return -1;
- }
- // Get arguments
- CoefficientRing* K1 = (CoefficientRing*) self;
- CoefficientRing* K2 = (CoefficientRing*) other;
- // Are they equal
- if (K1->K == K2->K) {
- return 0;
- }
- // Is one of them Z
- if (K1->K == lp_Z) {
- return 1;
- }
- if (K2->K == lp_Z) {
- return -1;
- }
- // Compare
- return lp_integer_cmp(lp_Z, &K1->K->M, &K2->K->M);
-}
-
-static PyObject*
-CoefficientRing_modulus(PyObject* self) {
- CoefficientRing* K = (CoefficientRing*) self;
- if (K && K->K) {
- char* K_str = lp_integer_to_string(&K->K->M);
- char* p = 0;
- PyObject* M = PyLong_FromString(K_str, &p, 10);
- free(K_str);
- return M;
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject* CoefficientRing_str(PyObject* self) {
- CoefficientRing* K = (CoefficientRing*) self;
- if (K) {
- if (K->K) {
- char* K_str = lp_int_ring_to_string(K->K);
- PyObject* str = PyString_FromString(K_str);
- free(K_str);
- return str;
- } else {
- return PyString_FromString("Z");
- }
- } else {
- Py_RETURN_NONE;
- }
-}
diff --git a/python/polypyInteger3.c b/python/polypyInteger3.c
deleted file mode 100644
index 12d5ace0..00000000
--- a/python/polypyInteger3.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/**
- * 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 "polypyInteger.h"
-#include "utils.h"
-
-#include
-
-static void
-CoefficientRing_dealloc(CoefficientRing* self);
-
-static PyObject*
-CoefficientRing_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-CoefficientRing_init(CoefficientRing* self, PyObject* args);
-
-static PyObject*
-CoefficientRing_modulus(PyObject* self);
-
-static PyObject*
-CoefficientRing_str(PyObject* self);
-
-static PyObject *
-CoefficientRing_richcompare(PyObject *self, PyObject *other, int op);
-
-PyMethodDef CoefficientRing_methods[] = {
- {"modulus", (PyCFunction)CoefficientRing_modulus, METH_NOARGS, "Returns the degree of the polynomial"},
- {NULL} /* Sentinel */
-};
-
-PyTypeObject CoefficientRingType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.CoefficientRing", // const char *tp_name;
- sizeof(CoefficientRing), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)CoefficientRing_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async;
- 0, // reprfunc tp_repr;
- 0, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- 0, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- CoefficientRing_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "Coefficient ring objects", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- CoefficientRing_richcompare, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- CoefficientRing_methods, // struct PyMethodDef *tp_methods;
- 0, // struct PyMemberDef *tp_members;
- 0, // struct PyGetSetDef *tp_getset;
- 0, // struct _typeobject *tp_base;
- 0, // PyObject *tp_dict;
- 0, // descrgetfunc tp_descr_get;
- 0, // descrsetfunc tp_descr_set;
- 0, // Py_ssize_t tp_dictoffset;
- (initproc)CoefficientRing_init, // initproc tp_init;
- 0, // allocfunc tp_alloc;
- CoefficientRing_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-static void
-CoefficientRing_dealloc(CoefficientRing* self)
-{
- if (self->K) lp_int_ring_detach(self->K);
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyCoefficientRing_create(lp_int_ring_t* K) {
- CoefficientRing *self;
- self = (CoefficientRing*)CoefficientRingType.tp_alloc(&CoefficientRingType, 0);
- if (self != NULL) {
- self->K = (lp_int_ring_t*)K;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-CoefficientRing_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyCoefficientRing_create(0);
-}
-
-
-static int
-CoefficientRing_init(CoefficientRing* self, PyObject* args)
-{
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) == 0) {
- // Defaults to Z
- self->K = lp_Z;
- } else if (PyTuple_Size(args) == 1) {
- // Get the list of coefficients
- PyObject* modulus = PyTuple_GetItem(args, 0);
- if (!PyLong_Check(modulus)) {
- if (!PyLong_Check(modulus)) {
- return -1;
- } else {
- long M_int = PyLong_AsLong(modulus);
- lp_integer_t M;
- lp_integer_construct_from_int(lp_Z, &M, M_int);
- int is_prime = lp_integer_is_prime(&M);
- self->K = lp_int_ring_create(&M, is_prime);
- lp_integer_destruct(&M);
- }
- } else {
- int overflow = 0;
- long M_int = PyLong_AsLongAndOverflow(modulus, &overflow);
- if (overflow) {
- const char* M_cstr = pythonObject2CharStar(modulus);
- lp_integer_t M;
- lp_integer_construct_from_string(lp_Z, &M, M_cstr, 10);
- int is_prime = lp_integer_is_prime(&M);
- self->K = lp_int_ring_create(&M, is_prime);
- } else if (M_int > 0) {
- lp_integer_t M;
- lp_integer_construct_from_int(lp_Z, &M, M_int);
- int is_prime = lp_integer_is_prime(&M);
- self->K = lp_int_ring_create(&M, is_prime);
- } else {
- return -1;
- }
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-
- return 0;
-}
-
-static PyObject*
-CoefficientRing_modulus(PyObject* self) {
- CoefficientRing* K = (CoefficientRing*) self;
- if (K && K->K) {
- char* K_str = lp_integer_to_string(&K->K->M);
- char* p = 0;
- PyObject* M = PyLong_FromString(K_str, &p, 10);
- free(K_str);
- return M;
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject* CoefficientRing_str(PyObject* self) {
- CoefficientRing* K = (CoefficientRing*) self;
- if (K) {
- if (K->K) {
- char* K_str = lp_int_ring_to_string(K->K);
- PyObject* str = PyUnicode_FromString(K_str);
- free(K_str);
- return str;
- } else {
- return PyUnicode_FromString("Z");
- }
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject *
-CoefficientRing_richcompare(PyObject *self, PyObject *other, int op){
- PyObject *result = Py_NotImplemented;
-
- if(!PyCoefficientRing_CHECK(other)){
- //IAM: Unless I am violating some sacrosanct python contract, this seems like a no-brainer.
- if(op == Py_EQ){ return Py_False; }
- if(op == Py_NE){ return Py_True; }
- } else {
- // Get arguments
- CoefficientRing* K1 = (CoefficientRing*) self;
- CoefficientRing* K2 = (CoefficientRing*) other;
-
- //Are they equal?
- if (K1->K == K2->K) {
- if( op == Py_LE || op == Py_EQ || op == Py_GE){
- return Py_True;
- }
- return Py_False;
- }
-
- // Is one of them Z
- if (K1->K == lp_Z) {
- // self > other
- if( op == Py_LT || op == Py_LE || op == Py_EQ){
- return Py_False;
- }
- return Py_True;
- }
- if (K2->K == lp_Z) {
- //self < other
- if( op == Py_LT || op == Py_LE){
- return Py_True;
- }
- return Py_False;
- }
-
- int cmp = lp_integer_cmp(lp_Z, &K1->K->M, &K2->K->M);
-
- switch (op) {
- case Py_LT:
- result = cmp < 0 ? Py_True : Py_False;
- break;
- case Py_LE:
- result = cmp <= 0 ? Py_True : Py_False;
- break;
- case Py_EQ:
- result = cmp == 0 ? Py_True : Py_False;
- break;
- case Py_NE:
- result = cmp != 0 ? Py_True : Py_False;
- break;
- case Py_GT:
- result = cmp > 0 ? Py_True : Py_False;
- break;
- case Py_GE:
- result = cmp >= 0 ? Py_True : Py_False;
- break;
- }
- }
- return result;
-}
diff --git a/python/polypyInterval.c b/python/polypyInterval.c
index 87673d84..5150817b 100644
--- a/python/polypyInterval.c
+++ b/python/polypyInterval.c
@@ -17,11 +17,169 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include
-
-#if PY_MAJOR_VERSION >= 3
-#include "polypyInterval3.c"
-#else
-#include "polypyInterval2.c"
-#endif
+#include "python.h"
+
+#include "polypyInterval.h"
+#include "polypyValue.h"
+
+static void
+Interval_dealloc(Interval* self);
+
+static PyObject*
+Interval_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static int
+Interval_init(Interval* self, PyObject* args);
+
+static PyObject*
+Interval_str(PyObject* self);
+
+static PyObject*
+Interval_pick_value(PyObject* self);
+
+static PyObject*
+Interval_contains_value(PyObject* self, PyObject* args);
+
+static PyObject*
+Interval_contains_int(PyObject* self);
+
+PyMethodDef Interval_methods[] = {
+ {"pick_value", (PyCFunction)Interval_pick_value, METH_NOARGS, "Returns a value from the interval."},
+ {"contains", (PyCFunction)Interval_contains_value, METH_VARARGS, "Returns true if the value is in the interval."},
+ {"contains_int", (PyCFunction)Interval_contains_int, METH_NOARGS, "Returns true if the interval contains an integer value."},
+ {NULL} /* Sentinel */
+};
+
+PyTypeObject IntervalType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.Interval", // const char *tp_name;
+ sizeof(Interval), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)Interval_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async;
+ Interval_str, // reprfunc tp_repr;
+ NULL, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ NULL, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ Interval_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "Interval objects", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ NULL, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ Interval_methods, // struct PyMethodDef *tp_methods;
+ NULL, // struct PyMemberDef *tp_members;
+ NULL, // struct PyGetSetDef *tp_getset;
+ NULL, // struct _typeobject *tp_base;
+ NULL, // PyObject *tp_dict;
+ NULL, // descrgetfunc tp_descr_get;
+ NULL, // descrsetfunc tp_descr_set;
+ 0, // Py_ssize_t tp_dictoffset;
+ (initproc)Interval_init, // initproc tp_init;
+ NULL, // allocfunc tp_alloc;
+ Interval_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+static void
+Interval_dealloc(Interval* self) {
+ lp_interval_destruct(&self->I);
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+PyObject*
+PyInterval_create(const lp_interval_t* I) {
+ Interval *self = (Interval*)IntervalType.tp_alloc(&IntervalType, 0);
+ if (self != NULL && I) {
+ lp_interval_construct_copy(&self->I, I);
+ }
+ return (PyObject *)self;
+}
+
+static PyObject*
+Interval_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return PyInterval_create(NULL);
+}
+
+static int
+Interval_init(Interval* self, PyObject* args) {
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 0) {
+ // Defaults to (-inf, +inf)
+ lp_interval_construct_full(&self->I);
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static PyObject* Interval_str(PyObject* self) {
+ Interval* I = (Interval*) self;
+ char* I_str = lp_interval_to_string(&I->I);
+ PyObject* str = PyUnicode_FromString(I_str);
+ free(I_str);
+ return str;
+}
+
+static PyObject*
+Interval_pick_value(PyObject* self) {
+ Interval* I = (Interval*) self;
+ lp_value_t v;
+ lp_value_construct_none(&v);
+ lp_interval_pick_value(&I->I, &v);
+ PyObject* result = PyValue_create(&v);
+ lp_value_destruct(&v);
+ return result;
+}
+
+static PyObject*
+Interval_contains_value(PyObject* self, PyObject* args) {
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* value_obj = PyTuple_GetItem(args, 0);
+
+ if (!PyValue_CHECK(value_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ lp_interval_t* I = &((Interval*) self)->I;
+ lp_value_t* v = &((Value*) value_obj)->v;
+
+ int result = lp_interval_contains(I, v);
+
+ PyObject* result_object = result ? Py_True : Py_False;
+ Py_INCREF(result_object);
+ return result_object;
+}
+
+static PyObject*
+Interval_contains_int(PyObject* self) {
+ Interval* I = (Interval*) self;
+ PyObject* result_object = lp_interval_contains_int(&I->I) ? Py_True : Py_False;
+ Py_INCREF(result_object);
+ return result_object;
+}
diff --git a/python/polypyInterval.h b/python/polypyInterval.h
index 4431fabb..bda15a3f 100644
--- a/python/polypyInterval.h
+++ b/python/polypyInterval.h
@@ -19,8 +19,7 @@
#pragma once
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include "interval.h"
diff --git a/python/polypyInterval2.c b/python/polypyInterval2.c
deleted file mode 100644
index 8dbdca0b..00000000
--- a/python/polypyInterval2.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/**
- * 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 "polypyInterval.h"
-#include "polypyValue.h"
-
-#include
-
-static void
-Interval_dealloc(Interval* self);
-
-static PyObject*
-Interval_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-Interval_init(Interval* self, PyObject* args);
-
-static PyObject*
-Interval_str(PyObject* self);
-
-static PyObject*
-Interval_pick_value(PyObject* self);
-
-static PyObject*
-Interval_contains_value(PyObject* self, PyObject* args);
-
-static PyObject*
-Interval_contains_int(PyObject* self);
-
-PyMethodDef Interval_methods[] = {
- {"pick_value", (PyCFunction)Interval_pick_value, METH_NOARGS, "Returns a value from the interval."},
- {"contains", (PyCFunction)Interval_contains_value, METH_VARARGS, "Returns true if the value is in the interval."},
- {"contains_int", (PyCFunction)Interval_contains_int, METH_NOARGS, "Returns true if the interval contains an integer value."},
- {NULL} /* Sentinel */
-};
-
-PyTypeObject IntervalType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.Interval", /*tp_name*/
- sizeof(Interval), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)Interval_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0 , /*tp_compare*/
- Interval_str, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- Interval_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "Interval objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- Interval_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)Interval_init,/* tp_init */
- 0, /* tp_alloc */
- Interval_new, /* tp_new */
-};
-
-static void
-Interval_dealloc(Interval* self) {
- lp_interval_destruct(&self->I);
- self->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyInterval_create(const lp_interval_t* I) {
- Interval *self;
- self = (Interval*)IntervalType.tp_alloc(&IntervalType, 0);
- if (self != NULL && I) {
- lp_interval_construct_copy(&self->I, I);
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-Interval_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyInterval_create(0);
-}
-
-static int
-Interval_init(Interval* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 0) {
- // Defaults to (-inf, +inf)
- lp_interval_construct_full(&self->I);
- } else {
- return -1;
- }
- return 0;
-}
-
-static PyObject* Interval_str(PyObject* self) {
- Interval* I = (Interval*) self;
- char* I_str = lp_interval_to_string(&I->I);
- PyObject* str = PyString_FromString(I_str);
- free(I_str);
- return str;
-}
-
-static PyObject*
-Interval_pick_value(PyObject* self) {
- Interval* I = (Interval*) self;
- lp_value_t v;
- lp_value_construct_none(&v);
- lp_interval_pick_value(&I->I, &v);
- PyObject* result = PyValue_create(&v);
- lp_value_destruct(&v);
- return result;
-}
-
-static PyObject*
-Interval_contains_value(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* value_obj = PyTuple_GetItem(args, 0);
-
- if (!PyValue_CHECK(value_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_interval_t* I = &((Interval*) self)->I;
- lp_value_t* v = &((Value*) value_obj)->v;
-
- int result = lp_interval_contains(I, v);
-
- PyObject* result_object = result ? Py_True : Py_False;
- Py_INCREF(result_object);
- return result_object;
-}
-
-static PyObject*
-Interval_contains_int(PyObject* self) {
- Interval* I = (Interval*) self;
- PyObject* result_object = lp_interval_contains_int(&I->I) ? Py_True : Py_False;
- Py_INCREF(result_object);
- return result_object;
-}
diff --git a/python/polypyInterval3.c b/python/polypyInterval3.c
deleted file mode 100644
index adf34c11..00000000
--- a/python/polypyInterval3.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/**
- * 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 "polypyInterval.h"
-#include "polypyValue.h"
-
-#include
-
-static void
-Interval_dealloc(Interval* self);
-
-static PyObject*
-Interval_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-Interval_init(Interval* self, PyObject* args);
-
-static PyObject*
-Interval_str(PyObject* self);
-
-static PyObject*
-Interval_pick_value(PyObject* self);
-
-static PyObject*
-Interval_contains_value(PyObject* self, PyObject* args);
-
-static PyObject*
-Interval_contains_int(PyObject* self);
-
-PyMethodDef Interval_methods[] = {
- {"pick_value", (PyCFunction)Interval_pick_value, METH_NOARGS, "Returns a value from the interval."},
- {"contains", (PyCFunction)Interval_contains_value, METH_VARARGS, "Returns true if the value is in the interval."},
- {"contains_int", (PyCFunction)Interval_contains_int, METH_NOARGS, "Returns true if the interval contains an integer value."},
- {NULL} /* Sentinel */
-};
-
-PyTypeObject IntervalType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.Interval", // const char *tp_name;
- sizeof(Interval), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)Interval_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async;
- Interval_str, // reprfunc tp_repr;
- 0, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- 0, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- Interval_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "Interval objects", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- 0, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- Interval_methods, // struct PyMethodDef *tp_methods;
- 0, // struct PyMemberDef *tp_members;
- 0, // struct PyGetSetDef *tp_getset;
- 0, // struct _typeobject *tp_base;
- 0, // PyObject *tp_dict;
- 0, // descrgetfunc tp_descr_get;
- 0, // descrsetfunc tp_descr_set;
- 0, // Py_ssize_t tp_dictoffset;
- (initproc)Interval_init, // initproc tp_init;
- 0, // allocfunc tp_alloc;
- Interval_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-static void
-Interval_dealloc(Interval* self) {
- lp_interval_destruct(&self->I);
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyInterval_create(const lp_interval_t* I) {
- Interval *self;
- self = (Interval*)IntervalType.tp_alloc(&IntervalType, 0);
- if (self != NULL && I) {
- lp_interval_construct_copy(&self->I, I);
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-Interval_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyInterval_create(0);
-}
-
-static int
-Interval_init(Interval* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 0) {
- // Defaults to (-inf, +inf)
- lp_interval_construct_full(&self->I);
- } else {
- return -1;
- }
- return 0;
-}
-
-static PyObject* Interval_str(PyObject* self) {
- Interval* I = (Interval*) self;
- char* I_str = lp_interval_to_string(&I->I);
- PyObject* str = PyUnicode_FromString(I_str);
- free(I_str);
- return str;
-}
-
-static PyObject*
-Interval_pick_value(PyObject* self) {
- Interval* I = (Interval*) self;
- lp_value_t v;
- lp_value_construct_none(&v);
- lp_interval_pick_value(&I->I, &v);
- PyObject* result = PyValue_create(&v);
- lp_value_destruct(&v);
- return result;
-}
-
-static PyObject*
-Interval_contains_value(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* value_obj = PyTuple_GetItem(args, 0);
-
- if (!PyValue_CHECK(value_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_interval_t* I = &((Interval*) self)->I;
- lp_value_t* v = &((Value*) value_obj)->v;
-
- int result = lp_interval_contains(I, v);
-
- PyObject* result_object = result ? Py_True : Py_False;
- Py_INCREF(result_object);
- return result_object;
-}
-
-static PyObject*
-Interval_contains_int(PyObject* self) {
- Interval* I = (Interval*) self;
- PyObject* result_object = lp_interval_contains_int(&I->I) ? Py_True : Py_False;
- Py_INCREF(result_object);
- return result_object;
-}
diff --git a/python/polypyPolynomial.c b/python/polypyPolynomial.c
index 96f0e1a2..1fc71a80 100644
--- a/python/polypyPolynomial.c
+++ b/python/polypyPolynomial.c
@@ -17,12 +17,1668 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
-#if PY_MAJOR_VERSION >= 3
-#include "polypyPolynomial3.c"
-#else
-#include "polypyPolynomial2.c"
-#endif
+#include "polypyPolynomial.h"
+#include "polypyInteger.h"
+#include "polypyVariable.h"
+#include "polypyVariableOrder.h"
+#include "polypyAssignment.h"
+#include "polypyValue.h"
+#include "polypyInterval.h"
+#include "polypyFeasibilitySet.h"
+
+#include "utils.h"
+#include "variable_list.h"
+#include "sign_condition.h"
+#include "feasibility_set.h"
+#include "value.h"
+#include "polynomial_vector.h"
+
+#include
+
+static lp_polynomial_context_t* default_ctx = NULL;
+
+const lp_polynomial_context_t* Polynomial_get_default_context(void) {
+ if (!default_ctx) {
+ default_ctx = lp_polynomial_context_new(NULL, Variable_get_default_db(), (lp_variable_order_t*) VariableOrder_get_default_order());
+ }
+ return default_ctx;
+}
+
+static void
+Polynomial_dealloc(Polynomial* self);
+
+static PyObject*
+Polynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static PyObject*
+Polynomial_richcompare(PyObject* self, PyObject* other, int op);
+
+static Py_hash_t
+Polynomial_hash(PyObject* self);
+
+static PyObject*
+Polynomial_degree(PyObject* self);
+
+static PyObject*
+Polynomial_coefficients(PyObject* self);
+
+static PyObject*
+Polynomial_reductum(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_sgn(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_sgn_check(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_rem(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_prem(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_sprem(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_pdivrem(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_spdivrem(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_gcd(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_lcm(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_derivative(PyObject* self);
+
+static PyObject*
+Polynomial_extended_gcd(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_factor(PyObject* self);
+
+static PyObject*
+Polynomial_factor_square_free(PyObject* self);
+
+static PyObject*
+Polynomial_roots_count(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_roots_isolate(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_sturm_sequence(PyObject* self);
+
+static PyObject*
+Polynomial_str(PyObject* self);
+
+static int
+Polynomial_nonzero(PyObject* self);
+
+static PyObject*
+Polynomial_add(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_neg(PyObject* self);
+
+static PyObject*
+Polynomial_sub(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_mul(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_div(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_rem_operator(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_divmod(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_pow(PyObject* self, PyObject* other);
+
+static PyObject*
+Polynomial_resultant(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_psc(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_subres(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_mgcd(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_evaluate(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_vars(PyObject* self);
+
+static PyObject*
+Polynomial_var(PyObject* self);
+
+static PyObject*
+Polynomial_pp(PyObject* self);
+
+static PyObject*
+Polynomial_cont(PyObject* self);
+
+static PyObject*
+Polynomial_pp_cont(PyObject* self);
+
+static PyObject*
+Polynomial_feasible_intervals(PyObject* self, PyObject* args);
+
+static PyObject*
+Polynomial_feasible_set(PyObject* self, PyObject* args);
+
+PyMethodDef Polynomial_methods[] = {
+ {"degree", (PyCFunction)Polynomial_degree, METH_NOARGS, "Returns the degree of the polynomial in its top variable"},
+ {"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 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"},
+ {"pdivrem", (PyCFunction)Polynomial_pdivrem, METH_VARARGS, "Returns the pseudo quotient and pseudo remainder of current and given polynomial"},
+ {"spdivprem", (PyCFunction)Polynomial_spdivrem, METH_VARARGS, "Returns the sparse pseudo quotient and sparse pseudo remainder of current and given polynomial"},
+ {"gcd", (PyCFunction)Polynomial_gcd, METH_VARARGS, "Returns the gcd of current and given polynomial"},
+ {"lcm", (PyCFunction)Polynomial_lcm, METH_VARARGS, "Returns the lcm of current and given polynomial"},
+ {"extended_gcd", (PyCFunction)Polynomial_extended_gcd, METH_VARARGS, "Returns the extended gcd, i.e. (gcd, u, v), of current and given polynomial"},
+ {"factor", (PyCFunction)Polynomial_factor, METH_NOARGS, "Returns the factorization of the polynomial"},
+ {"factor_square_free", (PyCFunction)Polynomial_factor_square_free, METH_NOARGS, "Returns the square-free factorization of the polynomial"},
+ {"roots_count", (PyCFunction)Polynomial_roots_count, METH_VARARGS, "Returns the number of real roots in the given interval"},
+ {"roots_isolate", (PyCFunction)Polynomial_roots_isolate, METH_VARARGS, "Returns the list of real roots (has to be univariate modulo the assignment)"},
+ {"sturm_sequence", (PyCFunction)Polynomial_sturm_sequence, METH_NOARGS, "Returns the Sturm sequence"},
+ {"derivative", (PyCFunction)Polynomial_derivative, METH_NOARGS, "Returns the derivative of the polynomial"},
+ {"resultant", (PyCFunction)Polynomial_resultant, METH_VARARGS, "Returns the resultant of the current and given polynomial"},
+ {"psc", (PyCFunction)Polynomial_psc, METH_VARARGS, "Returns the principal subresultant coefficients of the current and given polynomial"},
+ {"subres", (PyCFunction) Polynomial_subres, METH_VARARGS, "Returns the subresultant chain of the current and given polynomial"},
+ {"mgcd", (PyCFunction)Polynomial_mgcd, METH_VARARGS, "Returns assumptions that the GCD of two polynomials is of same degree"},
+ {"factor_square_free", (PyCFunction)Polynomial_factor_square_free, METH_NOARGS, "Returns the square-free factorization of the polynomial"},
+ {"evaluate", (PyCFunction)Polynomial_evaluate, METH_VARARGS, "Returns the value of the polynomial in the given assignment (or null if it doesn't fully evaluate"},
+ {"vars", (PyCFunction)Polynomial_vars, METH_NOARGS, "Returns the list of variables in the polynomial"},
+ {"var", (PyCFunction)Polynomial_var, METH_NOARGS, "Returns the top variable of the polynomial"},
+ {"pp", (PyCFunction)Polynomial_pp, METH_NOARGS, "Returns the primitive part of the polynomial"},
+ {"cont", (PyCFunction)Polynomial_cont, METH_NOARGS, "Returns the content of the polynomial"},
+ {"pp_cont", (PyCFunction)Polynomial_pp_cont, METH_NOARGS, "Returns the tuple (pp, cont) of the polynomial"},
+ {"feasible_intervals", (PyCFunction)Polynomial_feasible_intervals, METH_VARARGS, "Returns feasible intervals (list) of the polynomial (has to be univariate modulo the assignment)"},
+ {"feasible_set", (PyCFunction)Polynomial_feasible_set, METH_VARARGS, "Returns feasible set of the polynomial (has to be univariate modulo the assignment)"},
+ {NULL} /* Sentinel */
+};
+
+PyNumberMethods Polynomial_NumberMethods = {
+ Polynomial_add, // binaryfunc nb_add;
+ Polynomial_sub, // binaryfunc nb_subtract;
+ Polynomial_mul, // binaryfunc nb_multiply;
+ Polynomial_rem_operator, // binaryfunc nb_remainder;
+ Polynomial_divmod, // binaryfunc nb_divmod;
+ (ternaryfunc)Polynomial_pow, // ternaryfunc nb_power;
+ Polynomial_neg, // unaryfunc nb_negative;
+ NULL, // unaryfunc nb_positive;
+ NULL, // unaryfunc nb_absolute;
+ Polynomial_nonzero, // inquiry nb_bool;
+ NULL, // unaryfunc nb_invert;
+ NULL, // binaryfunc nb_lshift;
+ NULL, // binaryfunc nb_rshift;
+ NULL, // binaryfunc nb_and;
+ NULL, // binaryfunc nb_xor;
+ NULL, // binaryfunc nb_or;
+ NULL, // unaryfunc nb_int;
+ NULL, // void *nb_reserved;
+ NULL, // unaryfunc nb_float;
+ NULL, // binaryfunc nb_inplace_add;
+ NULL, // binaryfunc nb_inplace_subtract;
+ NULL, // binaryfunc nb_inplace_multiply;
+ NULL, // binaryfunc nb_inplace_remainder;
+ NULL, // ternaryfunc nb_inplace_power;
+ NULL, // binaryfunc nb_inplace_lshift;
+ NULL, // binaryfunc nb_inplace_rshift;
+ NULL, // binaryfunc nb_inplace_and;
+ NULL, // binaryfunc nb_inplace_xor;
+ NULL, // binaryfunc nb_inplace_or;
+ NULL, // binaryfunc nb_floor_divide;
+ Polynomial_div, // binaryfunc nb_true_divide;
+ NULL, // binaryfunc nb_inplace_floor_divide;
+ NULL, // binaryfunc nb_inplace_true_divide;
+ NULL, // unaryfunc nb_index;
+ NULL, // binaryfunc nb_matrix_multiply;
+ NULL, // binaryfunc nb_inplace_matrix_multiply;
+};
+
+PyTypeObject PolynomialType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.Polynomial", // const char *tp_name;
+ sizeof(Polynomial), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)Polynomial_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async;
+ Polynomial_str, // reprfunc tp_repr;
+ &Polynomial_NumberMethods, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ Polynomial_hash, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ Polynomial_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "Polynomial objects", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ Polynomial_richcompare, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ Polynomial_methods, // struct PyMethodDef *tp_methods;
+ NULL, // struct PyMemberDef *tp_members;
+ NULL, // struct PyGetSetDef *tp_getset;
+ NULL, // struct _typeobject *tp_base;
+ NULL, // PyObject *tp_dict;
+ NULL, // descrgetfunc tp_descr_get;
+ NULL, // descrsetfunc tp_descr_set;
+ 0, // Py_ssize_t tp_dictoffset;
+ NULL, // initproc tp_init;
+ NULL, // allocfunc tp_alloc;
+ Polynomial_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+static void
+Polynomial_dealloc(Polynomial* self)
+{
+ if (self->p) {
+ lp_polynomial_destruct(self->p);
+ free(self->p);
+ }
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+PyObject*
+Polynomial_create(lp_polynomial_t* p) {
+ Polynomial *self = (Polynomial*)PolynomialType.tp_alloc(&PolynomialType, 0);
+ lp_polynomial_set_external(p);
+ self->p = p;
+ return (PyObject*) self;
+}
+
+static PyObject*
+Polynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return Polynomial_create(NULL);
+}
+
+static PyObject*
+Polynomial_richcompare(PyObject* self, PyObject* other, int op) {
+ PyObject *result = NULL;
+
+ const lp_polynomial_context_t* ctx = NULL;
+
+ // One of them is a polynomial
+ if (PyPolynomial_CHECK(self)) {
+ ctx = lp_polynomial_get_context(((Polynomial*) self)->p);
+ } else {
+ ctx = lp_polynomial_get_context(((Polynomial*) other)->p);
+ }
+
+ int dec_other = 0;
+ int dec_self = 0;
+
+ // Check arguments
+ if (!PyPolynomial_CHECK(self)) {
+ if (PyVariable_CHECK(self)) {
+ self = PyPolynomial_FromVariable(self, ctx);
+ dec_self = 1;
+ } else if (PyLong_or_Int_Check(self)) {
+ self = PyPolynomial_FromLong_or_Int(self, ctx);
+ dec_self = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // Check arguments
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ lp_polynomial_t* self_p = ((Polynomial*) self)->p;
+ lp_polynomial_t* other_p = ((Polynomial*) other)->p;
+
+ int cmp = lp_polynomial_cmp(self_p, other_p);
+
+ switch (op) {
+ case Py_LT:
+ result = cmp < 0 ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ result = cmp <= 0 ? Py_True : Py_False;
+ break;
+ case Py_EQ:
+ result = cmp == 0 ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = cmp != 0 ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ result = cmp > 0 ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ result = cmp >= 0 ? Py_True : Py_False;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (dec_self) {
+ Py_DECREF(self);
+ }
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ Py_INCREF(result);
+ return result;
+}
+
+static Py_hash_t
+Polynomial_hash(PyObject* self) {
+ Polynomial* p = (Polynomial*) self;
+ Py_hash_t hash = lp_polynomial_hash(p->p);
+ if (hash == -1) {
+ // value -1 should not be returned as a normal return value
+ hash = 0;
+ }
+ return hash;
+}
+
+static PyObject* Polynomial_str(PyObject* self) {
+ Polynomial* p = (Polynomial*) self;
+ if (p) {
+ char* p_str = lp_polynomial_to_string(p->p);
+ PyObject* str = PyUnicode_FromString(p_str);
+ free(p_str);
+ return str;
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+PyObject*
+PyPolynomial_FromVariable(PyObject* variable, const lp_polynomial_context_t* ctx) {
+ // The variable
+ lp_variable_t x = ((Variable*) variable)->x;
+
+ // The constant
+ lp_integer_t one;
+ lp_integer_construct_from_int(ctx->K, &one, 1);
+
+ // The x polynomial
+ lp_polynomial_t* p_x = lp_polynomial_alloc();
+ lp_polynomial_construct_simple(p_x, ctx, &one, x, 1);
+
+ // Remove temps
+ lp_integer_destruct(&one);
+
+ // Return the polynomial
+ PyObject* result = Polynomial_create(p_x);
+ Py_INCREF(result);
+ return result;
+}
+
+PyObject*
+PyPolynomial_FromLong_or_Int(PyObject* number, const lp_polynomial_context_t* ctx) {
+ // The constants
+ lp_integer_t c;
+ PyLong_or_Int_to_integer(number, NULL, &c);
+
+ // The c polynomial
+ lp_polynomial_t* p_c = lp_polynomial_alloc();
+ lp_polynomial_construct_simple(p_c, ctx, &c, 0, 0);
+
+ // Remove temps
+ lp_integer_destruct(&c);
+
+ // Return the polynomial
+ PyObject* result = Polynomial_create(p_c);
+ Py_INCREF(result);
+ return result;
+}
+
+static PyObject*
+Polynomial_add(PyObject* self, PyObject* other) {
+
+ int dec_other = 0;
+
+ if (!PyPolynomial_CHECK(self)) {
+ return Polynomial_add(other, self);
+ }
+
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ // Check argument
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // Get arguments
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (p1_ctx != p2_ctx) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Add the polynomials
+ lp_polynomial_t* sum = lp_polynomial_new(p1_ctx);
+ lp_polynomial_add(sum, p1->p, p2->p);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return Polynomial_create(sum);
+}
+
+static PyObject*
+Polynomial_neg(PyObject* self) {
+ Polynomial* p = (Polynomial*) self;
+ const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p->p);
+ lp_polynomial_t* neg = lp_polynomial_new(p_ctx);
+ lp_polynomial_neg(neg, p->p);
+ return Polynomial_create(neg);
+}
+
+static PyObject*
+Polynomial_sub(PyObject* self, PyObject* other) {
+
+ int dec_other = 0;
+
+ if (!PyPolynomial_CHECK(self)) {
+ Polynomial* sub = (Polynomial*) Polynomial_sub(other, self);
+ lp_polynomial_neg(sub->p, sub->p);
+ return (PyObject*) sub;
+ }
+
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ // Check argument
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // Get arguments
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (p1_ctx != p2_ctx) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Subtract the polynomials
+ lp_polynomial_t* sub = lp_polynomial_new(p1_ctx);
+ lp_polynomial_sub(sub, p1->p, p2->p);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return Polynomial_create(sub);
+}
+
+static PyObject*
+Polynomial_mul(PyObject* self, PyObject* other) {
+
+ int dec_other = 0;
+
+ if (!PyPolynomial_CHECK(self)) {
+ return Polynomial_mul(other, self);
+ }
+
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ // Check argument
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // Get arguments
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Multiply the polynomials
+ lp_polynomial_t* mul = lp_polynomial_new(p1_ctx);
+ lp_polynomial_mul(mul, p1->p, p2->p);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return Polynomial_create(mul);
+}
+
+
+static PyObject*
+Polynomial_pow(PyObject* self, PyObject* other) {
+ // Check arguments
+ if (!PyPolynomial_CHECK(self) || !PyLong_Check(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ // Get arguments
+ Polynomial* p = (Polynomial*) self;
+ long n = PyLong_AsLong(other);
+ if (n < 0) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p->p);
+ // Compute
+ lp_polynomial_t* pow = lp_polynomial_new(p_ctx);
+ lp_polynomial_pow(pow, p->p, n);
+ // Return the result
+ return Polynomial_create(pow);
+}
+
+static PyObject*
+Polynomial_div(PyObject* self, PyObject* other) {
+
+ int dec_other = 0;
+
+ if (!PyPolynomial_CHECK(self)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // self is always a polynomial
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ // Make sure other is a polynomial
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // other can be a variable or a number
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Multiply the polynomials
+ lp_polynomial_t* div = lp_polynomial_new(p1_ctx);
+ lp_polynomial_div(div, p1->p, p2->p);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return Polynomial_create(div);
+}
+
+static PyObject*
+Polynomial_rem_operator(PyObject* self, PyObject* other) {
+ int dec_other = 0;
+
+ if (!PyPolynomial_CHECK(self)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // self is always a polynomial
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ // Make sure other is a polynomial
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // other can be a variable or a number
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Multiply the polynomials
+ lp_polynomial_t* rem = lp_polynomial_new(p1_ctx);
+ lp_polynomial_rem(rem, p1->p, p2->p);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return Polynomial_create(rem);
+}
+
+enum rem_type {
+ REM_EXACT,
+ REM_PSEUDO,
+ REM_SPARSE_PSEUDO
+};
+
+static PyObject*
+Polynomial_divmod_general(PyObject* self, PyObject* args, enum rem_type type) {
+
+ int dec_other = 0;
+
+ if (!PyPolynomial_CHECK(self)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // self is always a polynomial
+ Polynomial *p1 = (Polynomial *) self;
+ const lp_polynomial_context_t *p1_ctx = lp_polynomial_get_context(p1->p);
+
+ // check that there is only one other
+ PyObject *other;
+ if (PyTuple_Check(args)) {
+ if (PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ other = PyTuple_GetItem(args, 0);
+ } else {
+ other = args;
+ }
+ // make sure other is a polynomial
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // other can be a variable or a number
+ Polynomial *p2 = (Polynomial *) other;
+ const lp_polynomial_context_t *p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Divide the polynomials
+ lp_polynomial_t *rem = lp_polynomial_new(p1_ctx);
+ lp_polynomial_t *div = lp_polynomial_new(p1_ctx);
+ switch (type) {
+ case REM_EXACT:
+ lp_polynomial_divrem(div, rem, p1->p, p2->p);
+ break;
+ case REM_PSEUDO:
+ lp_polynomial_pdivrem(div, rem, p1->p, p2->p);
+ break;
+ case REM_SPARSE_PSEUDO:
+ lp_polynomial_spdivrem(div, rem, p1->p, p2->p);
+ break;
+ }
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ PyObject *pair = PyTuple_New(2);
+ PyObject *divObj = Polynomial_create(div);
+ PyObject *remObj = Polynomial_create(rem);
+ Py_INCREF(divObj);
+ Py_INCREF(remObj);
+ PyTuple_SetItem(pair, 0, divObj);
+ PyTuple_SetItem(pair, 1, remObj);
+ return pair;
+}
+
+static PyObject*
+Polynomial_divmod(PyObject* self, PyObject* other) {
+ return Polynomial_divmod_general(self, other, REM_EXACT);
+}
+
+static PyObject*
+Polynomial_pdivrem(PyObject* self, PyObject* other) {
+ return Polynomial_divmod_general(self, other, REM_PSEUDO);
+}
+
+static PyObject*
+Polynomial_spdivrem(PyObject* self, PyObject* other) {
+ return Polynomial_divmod_general(self, other, REM_SPARSE_PSEUDO);
+}
+
+static int
+Polynomial_nonzero(PyObject* self) {
+ // Get arguments
+ Polynomial* p = (Polynomial*) self;
+ // Return the result
+ return !lp_polynomial_is_zero(p->p);
+}
+
+static PyObject*
+Polynomial_rem_general(PyObject* self, PyObject* args, enum rem_type type) {
+ int dec_other = 0;
+
+ if (!PyPolynomial_CHECK(self)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // self is always a polynomial
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* other = PyTuple_GetItem(args, 0);
+
+ // Make sure other is a polynomial
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // other can be a variable or a number
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Multiply the polynomials
+ lp_polynomial_t* rem = lp_polynomial_new(p1_ctx);
+ switch (type) {
+ case REM_EXACT:
+ lp_polynomial_rem(rem, p1->p, p2->p);
+ break;
+ case REM_PSEUDO:
+ lp_polynomial_prem(rem, p1->p, p2->p);
+ break;
+ case REM_SPARSE_PSEUDO:
+ lp_polynomial_sprem(rem, p1->p, p2->p);
+ break;
+ }
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return Polynomial_create(rem);
+}
+
+static PyObject*
+Polynomial_rem(PyObject* self, PyObject* other) {
+ return Polynomial_rem_general(self, other, REM_EXACT);
+}
+
+static PyObject*
+Polynomial_prem(PyObject* self, PyObject* other) {
+ return Polynomial_rem_general(self, other, REM_PSEUDO);
+}
+
+static PyObject*
+Polynomial_sprem(PyObject* self, PyObject* other) {
+ return Polynomial_rem_general(self, other, REM_SPARSE_PSEUDO);
+}
+
+static PyObject*
+Polynomial_gcd(PyObject* self, PyObject* args) {
+
+ int dec_other = 0;
+
+ // self is always a polynomial
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* other = PyTuple_GetItem(args, 0);
+
+ // Make sure other is a polynomial
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // other can be a variable or a number
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Multiply the polynomials
+ lp_polynomial_t* gcd = lp_polynomial_new(p1_ctx);
+ lp_polynomial_gcd(gcd, p1->p, p2->p);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return Polynomial_create(gcd);
+}
+
+static PyObject*
+Polynomial_lcm(PyObject* self, PyObject* args) {
+
+ int dec_other = 0;
+
+ // self is always a polynomial
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* other = PyTuple_GetItem(args, 0);
+
+ // Make sure other is a polynomial
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // other can be a variable or a number
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Multiply the polynomials
+ lp_polynomial_t* lcm = lp_polynomial_new(p1_ctx);
+ lp_polynomial_lcm(lcm, p1->p, p2->p);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return Polynomial_create(lcm);
+}
+
+enum subres_type {
+ SUBRES,
+ SUBRES_PSC
+};
+
+static PyObject*
+Polynomial_subres_impl(PyObject* self, PyObject* args, enum subres_type type) {
+
+ // self is always a polynomial
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* other = PyTuple_GetItem(args, 0);
+
+ int dec_other = 0;
+
+ // Make sure other is a polynomial
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // Other polynomial
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Check the arguments (must be same top variable)
+ if (lp_polynomial_is_constant(p1->p) || lp_polynomial_is_constant(p2->p)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ if (lp_polynomial_top_variable(p1->p) != lp_polynomial_top_variable(p2->p)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Allocate the polynomials for the sequence
+ size_t p1_deg = lp_polynomial_degree(p1->p);
+ size_t p2_deg = lp_polynomial_degree(p2->p);
+ size_t size = p1_deg > p2_deg ? p2_deg + 1 : p1_deg + 1;
+
+ lp_polynomial_t** S = malloc(sizeof(lp_polynomial_t*)*size);
+ for (size_t i = 0; i < size; ++ i) {
+ S[i] = lp_polynomial_new(p1_ctx);
+ }
+
+ switch (type) {
+ case SUBRES:
+ // Compute the full subres
+ lp_polynomial_subres(S, p1->p, p2->p);
+ break;
+ case SUBRES_PSC:
+ // Compute the psc
+ lp_polynomial_psc(S, p1->p, p2->p);
+ break;
+ }
+
+ // Copy the polynomials into a list
+ PyObject* list = PyList_New(size);
+ for (size_t i = 0; i < size; ++i) {
+ PyObject* p = Polynomial_create(S[i]);
+ PyList_SetItem(list, i, p);
+ }
+ free(S);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return list;
+}
+
+static PyObject*
+Polynomial_psc(PyObject* self, PyObject* args) {
+ return Polynomial_subres_impl(self, args, SUBRES_PSC);
+}
+
+static PyObject*
+Polynomial_subres(PyObject* self, PyObject* args) {
+ return Polynomial_subres_impl(self, args, SUBRES);
+}
+
+static PyObject*
+Polynomial_mgcd(PyObject* self, PyObject* args) {
+
+ // self is always a polynomial
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
+ PyErr_SetString(PyExc_RuntimeError, "mgcd(): Need two arguments.");
+ return NULL;
+ }
+
+ // Assignment
+ PyObject* py_assignment = PyTuple_GetItem(args, 1);
+ if (!PyAssignment_CHECK(py_assignment)) {
+ PyErr_SetString(PyExc_RuntimeError, "mgcd(): Second argument should be an assignment.");
+ return NULL;
+ }
+ const lp_assignment_t* assignment = ((Assignment*) py_assignment)->assignment;
+
+ // Other polynomial
+ PyObject* other = PyTuple_GetItem(args, 0);
+
+ int dec_other = 0;
+
+ // Make sure other is a polynomial
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "mgcd(): First argument should be a polynomial.");
+ return NULL;
+ }
+ }
+
+ // Othe polynomial
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ PyErr_SetString(PyExc_RuntimeError, "mgcd(): Polynomials should be over the same context.");
+ return NULL;
+ }
+
+ // Check the arguments (must be same top variable)
+ if (lp_polynomial_is_constant(p1->p) || lp_polynomial_is_constant(p2->p)) {
+ PyErr_SetString(PyExc_RuntimeError, "mgcd(): Polynomials should be over the same top variables.");
+ return NULL;
+ }
+
+ if (lp_polynomial_top_variable(p1->p) != lp_polynomial_top_variable(p2->p)) {
+ PyErr_SetString(PyExc_RuntimeError, "mgcd(): Polynomials should be over the same top variables.");
+ return NULL;
+ }
+
+ // Compute the gcd
+ lp_polynomial_vector_t* mgcd = lp_polynomial_mgcd(p1->p, p2->p, assignment);
+
+ // Copy the polynomials into a list
+ size_t size = lp_polynomial_vector_size(mgcd);
+ PyObject* list = PyList_New(size);
+ for (size_t i = 0; i < size; ++i) {
+ lp_polynomial_t* mgcd_i = lp_polynomial_vector_at(mgcd, i);
+ PyObject* p = Polynomial_create(mgcd_i);
+ PyList_SetItem(list, i, p);
+ }
+ lp_polynomial_vector_delete(mgcd);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return list;
+}
+
+static PyObject*
+Polynomial_resultant(PyObject* self, PyObject* args) {
+
+ // self is always a polynomial
+ Polynomial* p1 = (Polynomial*) self;
+ const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* other = PyTuple_GetItem(args, 0);
+
+ int dec_other = 0;
+
+ // Make sure other is a polynomial
+ if (!PyPolynomial_CHECK(other)) {
+ if (PyVariable_CHECK(other)) {
+ other = PyPolynomial_FromVariable(other, p1_ctx);
+ dec_other = 1;
+ } else if (PyLong_or_Int_Check(other)) {
+ other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
+ dec_other = 1;
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+
+ // Other polynomial
+ Polynomial* p2 = (Polynomial*) other;
+ const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
+ if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Check the arguments (must be same top variable)
+ if (lp_polynomial_is_constant(p1->p) || lp_polynomial_is_constant(p2->p)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ if (lp_polynomial_top_variable(p1->p) != lp_polynomial_top_variable(p2->p)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Allocate the resultant
+ lp_polynomial_t* resultant = lp_polynomial_new(p1_ctx);
+
+ // Compute the psc
+ lp_polynomial_resultant(resultant, p1->p, p2->p);
+
+ if (dec_other) {
+ Py_DECREF(other);
+ }
+
+ // Return the result
+ return Polynomial_create(resultant);
+}
+
+static PyObject*
+Polynomial_extended_gcd(PyObject* self, PyObject* args) {
+ return NULL;
+}
+
+static PyObject*
+Polynomial_factor(PyObject* self) {
+ return NULL;
+}
+
+// Creates a python list from the factors, taking over the polynomials
+PyObject* factors_to_PyList(lp_polynomial_t** factors, size_t* multiplicities, size_t size) {
+ // Construct the result
+ PyObject* factors_list = PyList_New(size);
+
+ // Copy the constant
+ // Copy over the factors
+ for (size_t i = 0; i < size; ++ i) {
+ PyObject* p_i = Polynomial_create(factors[i]);
+ Py_INCREF(p_i);
+ PyObject* d = PyLong_FromSize_t(multiplicities[i]);
+ PyObject* pair = PyTuple_New(2);
+ PyTuple_SetItem(pair, 0, p_i);
+ PyTuple_SetItem(pair, 1, d);
+ PyList_SetItem(factors_list, i, pair);
+ }
+
+ // Return the list
+ return factors_list;
+}
+
+static PyObject*
+Polynomial_factor_square_free(PyObject* self) {
+ // Get arguments
+ Polynomial* p = (Polynomial*) self;
+ // Factor
+ lp_polynomial_t** factors = NULL;
+ size_t* multiplicities = NULL;
+ size_t factors_size = 0;
+ lp_polynomial_factor_square_free(p->p, &factors, &multiplicities, &factors_size);
+ // Create the list
+ PyObject* factors_list = factors_to_PyList(factors, multiplicities, factors_size);
+ // Get rid of the factors (not the polynomials)
+ free(factors);
+ free(multiplicities);
+ // Return the list
+ return factors_list;
+}
+
+static PyObject*
+Polynomial_roots_count(PyObject* self, PyObject* args) {
+ return NULL;
+}
+
+static PyObject*
+Polynomial_roots_isolate(PyObject* self, PyObject* args) {
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* assignment_obj = PyTuple_GetItem(args, 0);
+
+ if (!PyAssignment_CHECK(assignment_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
+
+ // Check that the top variable is the only unassigned
+ if (!lp_polynomial_is_univariate_m(p, assignment)) {
+ PyErr_SetString(PyExc_RuntimeError, "roots_count(): Polynomial must be univariate modulo the assignment.");
+ return NULL;
+ }
+
+ // Get the degree of the polynomial and allocate the values
+ lp_value_t* roots = malloc(sizeof(lp_value_t)*lp_polynomial_degree(p));
+ size_t roots_size = 0;
+
+ // Get the roots
+ lp_polynomial_roots_isolate(p, assignment, roots, &roots_size);
+
+ // Generate a list of roots
+ PyObject* list = PyList_New(roots_size);
+
+ for (size_t i = 0; i < roots_size; ++ i) {
+ PyObject* c = PyValue_create(roots + i);
+ PyList_SetItem(list, i, c);
+ }
+
+ // Get rid of the temporaries
+ for (size_t i = 0; i < roots_size; ++ i) {
+ lp_value_destruct(roots + i);
+ }
+ free(roots);
+
+ // Return the list
+ return list;
+}
+
+static PyObject*
+Polynomial_derivative(PyObject* self) {
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ lp_polynomial_t* p_derivative = lp_polynomial_new(lp_polynomial_get_context(p));
+ lp_polynomial_derivative(p_derivative, p);
+ return Polynomial_create(p_derivative);
+}
+
+static PyObject*
+Polynomial_sturm_sequence(PyObject* self) {
+ return NULL;
+}
+
+static PyObject*
+Polynomial_degree(PyObject* self) {
+ Polynomial* p = (Polynomial*) self;
+ return PyLong_FromUnsignedLong(lp_polynomial_degree(p->p));
+}
+
+static PyObject*
+Polynomial_coefficients(PyObject* self) {
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ size_t size = lp_polynomial_degree(p) + 1;
+
+ // Get the coefficients
+ const lp_polynomial_context_t* ctx = lp_polynomial_get_context(p);
+
+ // Copy the polynomials into a list
+ PyObject* list = PyList_New(size);
+ for (size_t i = 0; i < size; ++i) {
+ lp_polynomial_t* c_p = lp_polynomial_new(ctx);
+ lp_polynomial_get_coefficient(c_p, p, i);
+ PyObject* c = Polynomial_create(c_p);
+ PyList_SetItem(list, i, c);
+ }
+
+ return list;
+}
+
+static PyObject*
+Polynomial_vars(PyObject* self) {
+
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+
+ lp_variable_list_t p_vars;
+ lp_variable_list_construct(&p_vars);
+
+ // Get the variables
+ lp_polynomial_get_variables(p, &p_vars);
+
+ // Copy the polynomials into a list
+ PyObject* list = PyList_New(p_vars.list_size);
+ for (size_t i = 0; i < p_vars.list_size; ++i) {
+ PyObject* c = PyVariable_create(p_vars.list[i]);
+ PyList_SetItem(list, i, c);
+ }
+
+ lp_variable_list_destruct(&p_vars);
+
+ return list;
+}
+
+static PyObject*
+Polynomial_var(PyObject* self) {
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ return PyVariable_create(lp_polynomial_top_variable(p));
+}
+
+
+static PyObject*
+Polynomial_reductum(PyObject* self, PyObject* args) {
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ const lp_polynomial_context_t* ctx = lp_polynomial_get_context(p);
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) > 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ lp_assignment_t* assignment = NULL;
+
+ if (PyTuple_Size(args) == 1) {
+ PyObject* assignment_obj = PyTuple_GetItem(args, 0);
+ if (!PyAssignment_CHECK(assignment_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ } else {
+ assignment = ((Assignment*) assignment_obj)->assignment;
+ }
+ }
+
+ lp_polynomial_t* result = lp_polynomial_new(ctx);
+ if (assignment) {
+ lp_polynomial_reductum_m(result, p, assignment);
+ } else {
+ lp_polynomial_reductum(result, p);
+ }
+
+ return Polynomial_create(result);
+}
+
+static PyObject*
+Polynomial_sgn(PyObject* self, PyObject* args) {
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* assignment_obj = PyTuple_GetItem(args, 0);
+
+ if (!PyAssignment_CHECK(assignment_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
+
+ int sgn = lp_polynomial_sgn(p, assignment);
+
+ return PyLong_FromLong(sgn);
+}
+
+
+static PyObject*
+Polynomial_evaluate(PyObject* self, PyObject* args) {
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* assignment_obj = PyTuple_GetItem(args, 0);
+
+ if (!PyAssignment_CHECK(assignment_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
+
+ lp_value_t* value = lp_polynomial_evaluate(p, assignment);
+ PyObject* value_obj = PyValue_create(value);
+ lp_value_delete(value);
+
+ return value_obj;
+}
+
+static PyObject*
+Polynomial_feasible_intervals(PyObject* self, PyObject* args) {
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
+ PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): Needs two arguments, an assignment and a sign condition.");
+ return NULL;
+ }
+
+ PyObject* assignment_obj = PyTuple_GetItem(args, 0);
+ if (!PyAssignment_CHECK(assignment_obj)) {
+ PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): First argument must be an assignment.");
+ return NULL;
+ }
+
+ PyObject* sgn_condition_obj = PyTuple_GetItem(args, 1);
+ if (!PyLong_Check(sgn_condition_obj)) {
+ PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): Second argument must be a sign-condition.");
+ return NULL;
+ }
+
+ // Get the arguments
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
+ lp_sign_condition_t sgn_condition = PyLong_AsLong(sgn_condition_obj);
+
+ // Check if all but the top variable are unassigned
+ if (!lp_polynomial_is_univariate_m(p, assignment)) {
+ PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): Polynomial must be univariate modulo the assignment.");
+ return NULL;
+ }
+
+ // Get the feasible intervals
+ lp_feasibility_set_t* feasible = lp_polynomial_constraint_get_feasible_set(p, sgn_condition, 0, assignment);
+
+ // The list where we return the arguments
+ PyObject* list = PyList_New(feasible->size);
+ // Copy over to the list
+ for (size_t i = 0; i < feasible->size; ++i) {
+ PyObject* pp = PyInterval_create(feasible->intervals + i);
+ PyList_SetItem(list, i, pp);
+ }
+ // Remove temp
+ lp_feasibility_set_delete(feasible);
+
+ // Return the list
+ return list;
+}
+
+static PyObject*
+Polynomial_feasible_set(PyObject* self, PyObject* args) {
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* assignment_obj = PyTuple_GetItem(args, 0);
+ if (!PyAssignment_CHECK(assignment_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* sgn_condition_obj = PyTuple_GetItem(args, 1);
+ if (!PyLong_Check(sgn_condition_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Get the arguments
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
+ lp_sign_condition_t sgn_condition = PyLong_AsLong(sgn_condition_obj);
+
+ // Check if all but the top variable are unassigned
+ if (!lp_polynomial_is_univariate_m(p, assignment)) {
+ PyErr_SetString(PyExc_RuntimeError, "feasible_set(): Polynomial must be univariate modulo the assignment.");
+ return NULL;
+ }
+
+ // Get the feasible intervals
+ lp_feasibility_set_t* feasible = lp_polynomial_constraint_get_feasible_set(p, sgn_condition, 0, assignment);
+
+ // Return the list
+ return PyFeasibilitySet_create(feasible);
+}
+
+static PyObject*
+Polynomial_sgn_check(PyObject* self, PyObject* args) {
+
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* assignment_obj = PyTuple_GetItem(args, 0);
+ if (!PyAssignment_CHECK(assignment_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ PyObject* sgn_condition_obj = PyTuple_GetItem(args, 1);
+ if (!PyLong_Check(sgn_condition_obj)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ // Get the arguments
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
+ lp_sign_condition_t sgn_condition = PyLong_AsLong(sgn_condition_obj);
+
+ // Check if all but the top variable are unassigned
+ if (!lp_polynomial_is_assigned(p, assignment)) {
+ PyErr_SetString(PyExc_RuntimeError, "sgn_check(): All polynomial variables should be assigned by the given assignment.");
+ return NULL;
+ }
+
+ // Check the sign
+ int sgn = lp_polynomial_sgn(p, assignment);
+ if (lp_sign_condition_consistent(sgn_condition, sgn)) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+static PyObject*
+Polynomial_pp(PyObject* self) {
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p);
+ lp_polynomial_t* pp = lp_polynomial_new(p_ctx);
+ lp_polynomial_pp(pp, p);
+ PyObject* pp_py = Polynomial_create(pp);
+ return pp_py;
+}
+
+static PyObject*
+Polynomial_cont(PyObject* self) {
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p);
+ lp_polynomial_t* cont = lp_polynomial_new(p_ctx);
+ lp_polynomial_cont(cont, p);
+ PyObject* cont_py = Polynomial_create(cont);
+ return cont_py;
+}
+
+static PyObject*
+Polynomial_pp_cont(PyObject* self) {
+ lp_polynomial_t* p = ((Polynomial*) self)->p;
+ const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p);
+ lp_polynomial_t* pp = lp_polynomial_new(p_ctx);
+ lp_polynomial_t* cont = lp_polynomial_new(p_ctx);
+ lp_polynomial_pp_cont(pp, cont, p);
+ PyObject* pp_py = Polynomial_create(pp);
+ PyObject* cont_py = Polynomial_create(cont);
+ PyObject* tuple = PyTuple_New(2);
+ PyTuple_SetItem(tuple, 0, pp_py);
+ PyTuple_SetItem(tuple, 1, cont_py);
+ return tuple;
+}
diff --git a/python/polypyPolynomial.h b/python/polypyPolynomial.h
index 2ac1213c..e0fbd9d2 100644
--- a/python/polypyPolynomial.h
+++ b/python/polypyPolynomial.h
@@ -19,8 +19,7 @@
#pragma once
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include "utils.h"
#include "polynomial.h"
diff --git a/python/polypyPolynomial2.c b/python/polypyPolynomial2.c
deleted file mode 100644
index da42fa68..00000000
--- a/python/polypyPolynomial2.c
+++ /dev/null
@@ -1,1678 +0,0 @@
-/**
- * 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 "polypyPolynomial.h"
-
-#include "polypyInteger.h"
-#include "polypyVariable.h"
-#include "polypyVariableOrder.h"
-#include "polypyAssignment.h"
-#include "polypyValue.h"
-#include "polypyInterval.h"
-#include "polypyFeasibilitySet.h"
-
-#include "utils.h"
-#include "variable_list.h"
-#include "sign_condition.h"
-#include "feasibility_set.h"
-#include "value.h"
-#include "polynomial_vector.h"
-
-#include
-
-static lp_polynomial_context_t* default_ctx = 0;
-
-const lp_polynomial_context_t* Polynomial_get_default_context(void) {
- if (!default_ctx) {
- default_ctx = lp_polynomial_context_new(0, Variable_get_default_db(), (lp_variable_order_t*) VariableOrder_get_default_order());
- }
- return default_ctx;
-}
-
-static void
-Polynomial_dealloc(Polynomial* self);
-
-static PyObject*
-Polynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-Polynomial_cmp(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_richcompare(PyObject* self, PyObject* args, int op);
-
-static long
-Polynomial_hash(PyObject* self);
-
-static PyObject*
-Polynomial_degree(PyObject* self);
-
-static PyObject*
-Polynomial_coefficients(PyObject* self);
-
-static PyObject*
-Polynomial_reductum(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_sgn(PyObject* self, PyObject* arguments);
-
-static PyObject*
-Polynomial_sgn_check(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_rem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_prem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_sprem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_pdivrem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_spdivrem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_gcd(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_lcm(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_derivative(PyObject* self);
-
-static PyObject*
-Polynomial_extended_gcd(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_factor(PyObject* self);
-
-static PyObject*
-Polynomial_factor_square_free(PyObject* self);
-
-static PyObject*
-Polynomial_roots_count(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_roots_isolate(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_sturm_sequence(PyObject* self);
-
-static PyObject*
-Polynomial_str(PyObject* self);
-
-static int
-Polynomial_nonzero(PyObject* self);
-
-static PyObject*
-Polynomial_add(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_neg(PyObject* self);
-
-static PyObject*
-Polynomial_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_div(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_rem_operator(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_divmod(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_pow(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_resultant(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_psc(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_mgcd(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_evaluate(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_vars(PyObject* self);
-
-static PyObject*
-Polynomial_var(PyObject* self);
-
-static PyObject*
-Polynomial_pp(PyObject* self);
-
-static PyObject*
-Polynomial_cont(PyObject* self);
-
-static PyObject*
-Polynomial_pp_cont(PyObject* self);
-
-static PyObject*
-Polynomial_feasible_intervals(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_feasible_set(PyObject* self, PyObject* args);
-
-PyMethodDef Polynomial_methods[] = {
- {"degree", (PyCFunction)Polynomial_degree, METH_NOARGS, "Returns the degree of the polynomial in its top variable"},
- {"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."},
- {"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"},
- {"pdivrem", (PyCFunction)Polynomial_pdivrem, METH_VARARGS, "Returns the pseudo quotient and pseudo remainder of current and given polynomial"},
- {"spdivprem", (PyCFunction)Polynomial_spdivrem, METH_VARARGS, "Returns the sparse pseudo quotient and sparse pseudo remainder of current and given polynomial"},
- {"gcd", (PyCFunction)Polynomial_gcd, METH_VARARGS, "Returns the gcd of current and given polynomial"},
- {"lcm", (PyCFunction)Polynomial_lcm, METH_VARARGS, "Returns the lcm of current and given polynomial"},
- {"extended_gcd", (PyCFunction)Polynomial_extended_gcd, METH_VARARGS, "Returns the extended gcd, i.e. (gcd, u, v), of current and given polynomial"},
- {"factor", (PyCFunction)Polynomial_factor, METH_NOARGS, "Returns the factorization of the polynomial"},
- {"factor_square_free", (PyCFunction)Polynomial_factor_square_free, METH_NOARGS, "Returns the square-free factorization of the polynomial"},
- {"roots_count", (PyCFunction)Polynomial_roots_count, METH_VARARGS, "Returns the number of real roots in the given interval"},
- {"roots_isolate", (PyCFunction)Polynomial_roots_isolate, METH_VARARGS, "Returns the list of real roots (has to be univariate modulo the assignment)"},
- {"sturm_sequence", (PyCFunction)Polynomial_sturm_sequence, METH_NOARGS, "Returns the Sturm sequence"},
- {"derivative", (PyCFunction)Polynomial_derivative, METH_NOARGS, "Returns the derivative of the polynomial"},
- {"resultant", (PyCFunction)Polynomial_resultant, METH_VARARGS, "Returns the resultant of the current and given polynomial"},
- {"psc", (PyCFunction)Polynomial_psc, METH_VARARGS, "Returns the principal subresultant coefficients of the current and given polynomial"},
- {"mgcd", (PyCFunction)Polynomial_mgcd, METH_VARARGS, "Returns assumptions that the GCD of two polynomials is of same degree"},
- {"factor_square_free", (PyCFunction)Polynomial_factor_square_free, METH_NOARGS, "Returns the square-free factorization of the polynomial"},
- {"evaluate", (PyCFunction)Polynomial_evaluate, METH_VARARGS, "Returns the value of the polynomial in the given assignment (or null if it doesn't fully evaluate"},
- {"vars", (PyCFunction)Polynomial_vars, METH_NOARGS, "Returns the list of variables in the polynomial"},
- {"var", (PyCFunction)Polynomial_var, METH_NOARGS, "Returns the top variable of the polynomial"},
- {"pp", (PyCFunction)Polynomial_pp, METH_NOARGS, "Returns the primitive part of the polynomial"},
- {"cont", (PyCFunction)Polynomial_cont, METH_NOARGS, "Returns the content of the polynomial"},
- {"pp_cont", (PyCFunction)Polynomial_pp_cont, METH_NOARGS, "Returns the tuple (pp, cont) of the polynomial"},
- {"feasible_intervals", (PyCFunction)Polynomial_feasible_intervals, METH_VARARGS, "Returns feasible intervals (list) of the polynomial (has to be univariate modulo the assignment)"},
- {"feasible_set", (PyCFunction)Polynomial_feasible_set, METH_VARARGS, "Returns feasible set of the polynomial (has to be univariate modulo the assignment)"},
- {NULL} /* Sentinel */
-};
-
-PyNumberMethods Polynomial_NumberMethods = {
- Polynomial_add, // binaryfunc nb_add;
- Polynomial_sub, // binaryfunc nb_subtract;
- Polynomial_mul, // binaryfunc nb_multiply;
- Polynomial_div, // binaryfunc nb_divide;
- Polynomial_rem_operator, // binaryfunc nb_remainder;
- Polynomial_divmod, // binaryfunc nb_divmod;
- (ternaryfunc)Polynomial_pow, // ternaryfunc nb_power;
- Polynomial_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- Polynomial_nonzero, // inquiry nb_nonzero; /* Used by PyObject_IsTrue */
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- 0, // coercion nb_coerce; /* Used by the coerce() function */
- 0, // unaryfunc nb_int;
- 0, // unaryfunc nb_long;
- 0, // unaryfunc nb_float;
- 0, // unaryfunc nb_oct;
- 0, // unaryfunc nb_hex;
-
- /* Added in release 2.0 */
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_divide;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
-
- /* Added in release 2.2 */
- 0, // binaryfunc nb_floor_divide;
- 0, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
-
- /* Added in release 2.5 */
- 0 // unaryfunc nb_index;
-};
-
-PyTypeObject PolynomialType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.Polynomial", /*tp_name*/
- sizeof(Polynomial), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)Polynomial_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- Polynomial_cmp, /*tp_compare*/
- Polynomial_str, /*tp_repr*/
- &Polynomial_NumberMethods, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- Polynomial_hash, /*tp_hash */
- 0, /*tp_call*/
- Polynomial_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "Polynomial objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- Polynomial_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- Polynomial_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- Polynomial_new, /* tp_new */
-};
-
-static void
-Polynomial_dealloc(Polynomial* self)
-{
- if (self->p) {
- lp_polynomial_destruct(self->p);
- free(self->p);
- }
- self->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-Polynomial_create(lp_polynomial_t* p) {
- Polynomial *self;
- self = (Polynomial*)PolynomialType.tp_alloc(&PolynomialType, 0);
- lp_polynomial_set_external(p);
- self->p = p;
- return (PyObject*) self;
-}
-
-static PyObject*
-Polynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return Polynomial_create(0);
-}
-
-static PyObject*
-Polynomial_richcompare(PyObject* self, PyObject* other, int op) {
- PyObject *result = 0;
-
- const lp_polynomial_context_t* ctx = 0;
-
- // One of them is a polynomial
- if (PyPolynomial_CHECK(self)) {
- ctx = lp_polynomial_get_context(((Polynomial*) self)->p);
- } else {
- ctx = lp_polynomial_get_context(((Polynomial*) other)->p);
- }
-
- int dec_other = 0;
- int dec_self = 0;
-
- // Check arguments
- if (!PyPolynomial_CHECK(self)) {
- if (PyVariable_CHECK(self)) {
- self = PyPolynomial_FromVariable(self, ctx);
- dec_self = 1;
- } else if (PyLong_or_Int_Check(self)) {
- self = PyPolynomial_FromLong_or_Int(self, ctx);
- dec_self = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Check arguments
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- lp_polynomial_t* self_p = ((Polynomial*) self)->p;
- lp_polynomial_t* other_p = ((Polynomial*) other)->p;
-
- int cmp = lp_polynomial_cmp(self_p, other_p);
-
- switch (op) {
- case Py_LT:
- result = cmp < 0 ? Py_True : Py_False;
- break;
- case Py_LE:
- result = cmp <= 0 ? Py_True : Py_False;
- break;
- case Py_EQ:
- result = cmp == 0 ? Py_True : Py_False;
- break;
- case Py_NE:
- result = cmp != 0 ? Py_True : Py_False;
- break;
- case Py_GT:
- result = cmp > 0 ? Py_True : Py_False;
- break;
- case Py_GE:
- result = cmp >= 0 ? Py_True : Py_False;
- break;
- }
-
- if (dec_self) {
- Py_DECREF(self);
- }
- if (dec_other) {
- Py_DECREF(other);
- }
-
- Py_INCREF(result);
- return result;
-}
-
-static int
-Polynomial_cmp(PyObject* self, PyObject* other) {
-
- // Check arguments
- if (!PyPolynomial_CHECK(self) || !PyPolynomial_CHECK(other)) {
- // should return -1 and set an exception condition when an error occurred
- return -1;
- }
- // Get arguments
- Polynomial* p1 = (Polynomial*) self;
- Polynomial* p2 = (Polynomial*) other;
- // Compare
- int cmp = lp_polynomial_cmp(p1->p, p2->p);
- return cmp > 0 ? 1 : cmp < 0 ? -1 : 0;
-}
-
-static long
-Polynomial_hash(PyObject* self) {
- Polynomial* p = (Polynomial*) self;
- long hash = lp_polynomial_hash(p->p);
- if (hash == -1) {
- // value -1 should not be returned as a normal return value
- hash = 0;
- }
- return hash;
-}
-
-static PyObject* Polynomial_str(PyObject* self) {
- Polynomial* p = (Polynomial*) self;
- if (p) {
- char* p_str = lp_polynomial_to_string(p->p);
- PyObject* str = PyString_FromString(p_str);
- free(p_str);
- return str;
- } else {
- Py_RETURN_NONE;
- }
-}
-
-PyObject*
-PyPolynomial_FromVariable(PyObject* variable, const lp_polynomial_context_t* ctx) {
- // The variable
- lp_variable_t x = ((Variable*) variable)->x;
-
- // The constant
- lp_integer_t one;
- lp_integer_construct_from_int(ctx->K, &one, 1);
-
- // The x polynomial
- lp_polynomial_t* p_x = lp_polynomial_alloc();
- lp_polynomial_construct_simple(p_x, ctx, &one, x, 1);
-
- // Remove temps
- lp_integer_destruct(&one);
-
- // Return the polynomial
- PyObject* result = Polynomial_create(p_x);
- Py_INCREF(result);
- return result;
-}
-
-PyObject*
-PyPolynomial_FromLong_or_Int(PyObject* number, const lp_polynomial_context_t* ctx) {
- // The constants
- lp_integer_t c;
- PyLong_or_Int_to_integer(number, 0, &c);
-
- // The c polynomial
- lp_polynomial_t* p_c = lp_polynomial_alloc();
- lp_polynomial_construct_simple(p_c, ctx, &c, 0, 0);
-
- // Remove temps
- lp_integer_destruct(&c);
-
- // Return the polynomial
- PyObject* result = Polynomial_create(p_c);
- Py_INCREF(result);
- return result;
-}
-
-static PyObject*
-Polynomial_add(PyObject* self, PyObject* other) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- return Polynomial_add(other, self);
- }
-
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Check argument
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Get arguments
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (p1_ctx != p2_ctx) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Add the polynomials
- lp_polynomial_t* sum = lp_polynomial_new(p1_ctx);
- lp_polynomial_add(sum, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(sum);
-}
-
-static PyObject*
-Polynomial_neg(PyObject* self) {
- Polynomial* p = (Polynomial*) self;
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p->p);
- lp_polynomial_t* neg = lp_polynomial_new(p_ctx);
- lp_polynomial_neg(neg, p->p);
- return Polynomial_create(neg);
-}
-
-static PyObject*
-Polynomial_sub(PyObject* self, PyObject* other) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- Polynomial* sub = (Polynomial*) Polynomial_sub(other, self);
- lp_polynomial_neg(sub->p, sub->p);
- return (PyObject*) sub;
- }
-
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Check argument
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Get arguments
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (p1_ctx != p2_ctx) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Subtract the polynomials
- lp_polynomial_t* sub = lp_polynomial_new(p1_ctx);
- lp_polynomial_sub(sub, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(sub);
-}
-
-static PyObject*
-Polynomial_mul(PyObject* self, PyObject* other) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- return Polynomial_mul(other, self);
- }
-
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Check argument
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Get arguments
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* mul = lp_polynomial_new(p1_ctx);
- lp_polynomial_mul(mul, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(mul);
-}
-
-
-static PyObject*
-Polynomial_pow(PyObject* self, PyObject* other) {
- // Check arguments
- if (!PyPolynomial_CHECK(self) || !PyInt_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- Polynomial* p = (Polynomial*) self;
- long n = PyInt_AsLong(other);
- if (n < 0) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p->p);
- // Compute
- lp_polynomial_t* pow = lp_polynomial_new(p_ctx);
- lp_polynomial_pow(pow, p->p, n);
- // Return the result
- return Polynomial_create(pow);
-}
-
-static PyObject*
-Polynomial_div(PyObject* self, PyObject* other) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* div = lp_polynomial_new(p1_ctx);
- lp_polynomial_div(div, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(div);
-}
-
-static PyObject*
-Polynomial_rem_operator(PyObject* self, PyObject* other) {
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* rem = lp_polynomial_new(p1_ctx);
- lp_polynomial_rem(rem, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(rem);
-}
-
-enum rem_type {
- REM_EXACT,
- REM_PSEUDO,
- REM_SPARSE_PSEUDO
-};
-
-static PyObject*
-Polynomial_divmod_general(PyObject* self, PyObject* args, enum rem_type type) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // check that there is only one other
- PyObject *other;
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- other = PyTuple_GetItem(args, 0);
- } else {
- other = args;
- }
- // make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Divide the polynomials
- lp_polynomial_t* rem = lp_polynomial_new(p1_ctx);
- lp_polynomial_t* div = lp_polynomial_new(p1_ctx);
- switch (type) {
- case REM_EXACT:
- lp_polynomial_divrem(div, rem, p1->p, p2->p);
- break;
- case REM_PSEUDO:
- lp_polynomial_pdivrem(div, rem, p1->p, p2->p);
- break;
- case REM_SPARSE_PSEUDO:
- lp_polynomial_spdivrem(div, rem, p1->p, p2->p);
- break;
- }
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- PyObject* pair = PyTuple_New(2);
- PyObject* divObj = Polynomial_create(div);
- PyObject* remObj = Polynomial_create(rem);
- Py_INCREF(divObj);
- Py_INCREF(remObj);
- PyTuple_SetItem(pair, 0, divObj);
- PyTuple_SetItem(pair, 1, remObj);
- return pair;
-}
-
-static PyObject*
-Polynomial_divmod(PyObject* self, PyObject* other) {
- return Polynomial_divmod_general(self, other, REM_EXACT);
-}
-
-static PyObject*
-Polynomial_pdivrem(PyObject* self, PyObject* other) {
- return Polynomial_divmod_general(self, other, REM_PSEUDO);
-}
-
-static PyObject*
-Polynomial_spdivrem(PyObject* self, PyObject* other) {
- return Polynomial_divmod_general(self, other, REM_SPARSE_PSEUDO);
-}
-
-static int
-Polynomial_nonzero(PyObject* self) {
- // Get arguments
- Polynomial* p = (Polynomial*) self;
- // Return the result
- return !lp_polynomial_is_zero(p->p);
-}
-
-static PyObject*
-Polynomial_rem_general(PyObject* self, PyObject* args, enum rem_type type) {
- int dec_other = 0;
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* rem = lp_polynomial_new(p1_ctx);
- switch (type) {
- case REM_EXACT:
- lp_polynomial_rem(rem, p1->p, p2->p);
- break;
- case REM_PSEUDO:
- lp_polynomial_prem(rem, p1->p, p2->p);
- break;
- case REM_SPARSE_PSEUDO:
- lp_polynomial_sprem(rem, p1->p, p2->p);
- break;
- }
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(rem);
-}
-
-static PyObject*
-Polynomial_rem(PyObject* self, PyObject* other) {
- return Polynomial_rem_general(self, other, REM_EXACT);
-}
-
-static PyObject*
-Polynomial_prem(PyObject* self, PyObject* other) {
- return Polynomial_rem_general(self, other, REM_PSEUDO);
-}
-
-static PyObject*
-Polynomial_sprem(PyObject* self, PyObject* other) {
- return Polynomial_rem_general(self, other, REM_SPARSE_PSEUDO);
-}
-
-static PyObject*
-Polynomial_gcd(PyObject* self, PyObject* args) {
-
- int dec_other = 0;
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* gcd = lp_polynomial_new(p1_ctx);
- lp_polynomial_gcd(gcd, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(gcd);
-}
-
-static PyObject*
-Polynomial_lcm(PyObject* self, PyObject* args) {
-
- int dec_other = 0;
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* lcm = lp_polynomial_new(p1_ctx);
- lp_polynomial_lcm(lcm, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(lcm);
-}
-
-static PyObject*
-Polynomial_psc(PyObject* self, PyObject* args) {
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- int dec_other = 0;
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Othe polynomial
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Check the arguments (must be same top variable)
- if (lp_polynomial_is_constant(p1->p) || lp_polynomial_is_constant(p2->p)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- if (lp_polynomial_top_variable(p1->p) != lp_polynomial_top_variable(p2->p)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Allocate the polynomials for the sequence
- size_t p1_deg = lp_polynomial_degree(p1->p);
- size_t p2_deg = lp_polynomial_degree(p2->p);
- int size = p1_deg > p2_deg ? p2_deg + 1 : p1_deg + 1;
-
- lp_polynomial_t** psc = malloc(sizeof(lp_polynomial_t*)*size);
- int i;
- for (i = 0; i < size; ++ i) {
- psc[i] = lp_polynomial_new(p1_ctx);
- }
-
- // Compute the psc
- lp_polynomial_psc(psc, p1->p, p2->p);
-
- // Copy the polynomials into a list
- PyObject* list = PyList_New(size);
- for (i = 0; i < size; ++i) {
- PyObject* p = Polynomial_create(psc[i]);
- PyList_SetItem(list, i, p);
- }
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return list;
-}
-
-static PyObject*
-Polynomial_mgcd(PyObject* self, PyObject* args) {
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Need two arguments.");
- return NULL;
- }
-
- // Assignment
- PyObject* py_assignment = PyTuple_GetItem(args, 1);
- if (!PyAssignment_CHECK(py_assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Second argument should be an assignment.");
- return NULL;
- }
- const lp_assignment_t* assignment = ((Assignment*) py_assignment)->assignment;
-
- // Other polynomial
- PyObject* other = PyTuple_GetItem(args, 0);
-
- int dec_other = 0;
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): First argument should be a polynomial.");
- return NULL;
- }
- }
-
- // Othe polynomial
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Polynomials should be over the same context.");
- return NULL;
- }
-
- // Check the arguments (must be same top variable)
- if (lp_polynomial_is_constant(p1->p) || lp_polynomial_is_constant(p2->p)) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Polynomials should be over the same top variables.");
- return NULL;
- }
-
- if (lp_polynomial_top_variable(p1->p) != lp_polynomial_top_variable(p2->p)) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Polynomials should be over the same top variables.");
- return NULL;
- }
-
- // Compute the gcd
- lp_polynomial_vector_t* mgcd = lp_polynomial_mgcd(p1->p, p2->p, assignment);
-
- // Copy the polynomials into a list
- size_t size = lp_polynomial_vector_size(mgcd);
- PyObject* list = PyList_New(size);
- size_t i;
- for (i = 0; i < size; ++i) {
- lp_polynomial_t* mgcd_i = lp_polynomial_vector_at(mgcd, i);
- PyObject* p = Polynomial_create(mgcd_i);
- PyList_SetItem(list, i, p);
- }
- lp_polynomial_vector_delete(mgcd);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return list;
-}
-
-static PyObject*
-Polynomial_resultant(PyObject* self, PyObject* args) {
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- int dec_other = 0;
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Othe polynomial
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Check the arguments (must be same top variable)
- if (lp_polynomial_is_constant(p1->p) || lp_polynomial_is_constant(p2->p)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- if (lp_polynomial_top_variable(p1->p) != lp_polynomial_top_variable(p2->p)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Allocate the resultant
- lp_polynomial_t* resultant = lp_polynomial_new(p1_ctx);
-
- // Compute the psc
- lp_polynomial_resultant(resultant, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(resultant);
-}
-
-
-static PyObject*
-Polynomial_extended_gcd(PyObject* self, PyObject* args) {
- return 0;
-}
-
-static PyObject*
-Polynomial_factor(PyObject* self) {
- return 0;
-}
-
-// Creates a python list from the factors, taking over the polynomials
-PyObject* factors_to_PyList(lp_polynomial_t** factors, size_t* multiplicities, size_t size) {
- // Construct the result
- PyObject* factors_list = PyList_New(size);
-
- // Copy the constant
- // Copy over the factors
- int i;
- for (i = 0; i < size; ++ i) {
- PyObject* p_i = Polynomial_create(factors[i]);
- Py_INCREF(p_i);
- PyObject* d = PyInt_FromSize_t(multiplicities[i]);
- PyObject* pair = PyTuple_New(2);
- PyTuple_SetItem(pair, 0, p_i);
- PyTuple_SetItem(pair, 1, d);
- PyList_SetItem(factors_list, i, pair);
- }
-
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-Polynomial_factor_square_free(PyObject* self) {
- // Get arguments
- Polynomial* p = (Polynomial*) self;
- // Factor
- lp_polynomial_t** factors = 0;
- size_t* multiplicities = 0;
- size_t factors_size = 0;
- lp_polynomial_factor_square_free(p->p, &factors, &multiplicities, &factors_size);
- // Create the list
- PyObject* factors_list = factors_to_PyList(factors, multiplicities, factors_size);
- // Get rid of the factors (not the polynomials)
- free(factors);
- free(multiplicities);
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-Polynomial_roots_count(PyObject* self, PyObject* args) {
- return 0;
-}
-
-static PyObject*
-Polynomial_roots_isolate(PyObject* self, PyObject* args) {
-
- int i;
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
-
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
-
- // Check that the top variable is the only unassigned
- if (!lp_polynomial_is_univariate_m(p, assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "roots_count(): Polynomial must be univariate modulo the assignment.");
- return NULL;
- }
-
- // Get the degree of the polynomial and allocate the values
- lp_value_t* roots = malloc(sizeof(lp_value_t)*lp_polynomial_degree(p));
- size_t roots_size = 0;
-
- // Get the roots
- lp_polynomial_roots_isolate(p, assignment, roots, &roots_size);
-
- // Generate a list of roots
- PyObject* list = PyList_New(roots_size);
-
- for (i = 0; i < roots_size; ++ i) {
- PyObject* c = PyValue_create(roots + i);
- PyList_SetItem(list, i, c);
- }
-
- // Get rid of the temporaries
- for (i = 0; i < roots_size; ++ i) {
- lp_value_destruct(roots + i);
- }
- free(roots);
-
- // Return the list
- return list;
-}
-
-static PyObject*
-Polynomial_derivative(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_polynomial_t* p_derivative = lp_polynomial_new(lp_polynomial_get_context(p));
- lp_polynomial_derivative(p_derivative, p);
- return Polynomial_create(p_derivative);
-}
-
-static PyObject*
-Polynomial_sturm_sequence(PyObject* self) {
- return 0;
-}
-
-static PyObject*
-Polynomial_degree(PyObject* self) {
- Polynomial* p = (Polynomial*) self;
- return PyInt_FromLong(lp_polynomial_degree(p->p));
-}
-
-static PyObject*
-Polynomial_coefficients(PyObject* self) {
- int i;
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- size_t size = lp_polynomial_degree(p) + 1;
-
- // Get the coefficients
- const lp_polynomial_context_t* ctx = lp_polynomial_get_context(p);
-
- // Copy the polynomials into a list
- PyObject* list = PyList_New(size);
- for (i = 0; i < size; ++i) {
- lp_polynomial_t* c_p = lp_polynomial_new(ctx);
- lp_polynomial_get_coefficient(c_p, p, i);
- PyObject* c = Polynomial_create(c_p);
- PyList_SetItem(list, i, c);
- }
-
- return list;
-}
-
-static PyObject*
-Polynomial_vars(PyObject* self) {
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
-
- lp_variable_list_t p_vars;
- lp_variable_list_construct(&p_vars);
-
- // Get the variables
- lp_polynomial_get_variables(p, &p_vars);
-
- // Copy the polynomials into a list
- PyObject* list = PyList_New(p_vars.list_size);
- size_t i;
- for (i = 0; i < p_vars.list_size; ++i) {
- PyObject* c = PyVariable_create(p_vars.list[i]);
- PyList_SetItem(list, i, c);
- }
-
- lp_variable_list_destruct(&p_vars);
-
- return list;
-}
-
-static PyObject*
-Polynomial_var(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- return PyVariable_create(lp_polynomial_top_variable(p));
-}
-
-
-static PyObject*
-Polynomial_reductum(PyObject* self, PyObject* args) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- const lp_polynomial_context_t* ctx = lp_polynomial_get_context(p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) > 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_assignment_t* assignment = 0;
-
- if (PyTuple_Size(args) == 1) {
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- } else {
- assignment = ((Assignment*) assignment_obj)->assignment;
- }
- }
-
- lp_polynomial_t* result = lp_polynomial_new(ctx);
- if (assignment) {
- lp_polynomial_reductum_m(result, p, assignment);
- } else {
- lp_polynomial_reductum(result, p);
- }
-
- return Polynomial_create(result);
-}
-
-static PyObject*
-Polynomial_sgn(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
-
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
-
- int sgn = lp_polynomial_sgn(p, assignment);
-
- return PyInt_FromLong(sgn);
-}
-
-
-static PyObject*
-Polynomial_evaluate(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
-
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
-
- lp_value_t* value = lp_polynomial_evaluate(p, assignment);
- PyObject* value_obj = PyValue_create(value);
- lp_value_delete(value);
-
- return value_obj;
-}
-
-static PyObject*
-Polynomial_feasible_intervals(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): Needs two arguments, an assignment and a sign condition.");
- return NULL;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
- if (!PyAssignment_CHECK(assignment_obj)) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): First argument must be an assignment.");
- return NULL;
- }
-
- PyObject* sgn_condition_obj = PyTuple_GetItem(args, 1);
- if (!PyInt_Check(sgn_condition_obj)) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): Second argument must be a sign-condition.");
- return NULL;
- }
-
- // Get the arguments
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
- lp_sign_condition_t sgn_condition = PyInt_AsLong(sgn_condition_obj);
-
- // Check if all but the top variable are unassigned
- if (!lp_polynomial_is_univariate_m(p, assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): Polynomial must be univariate modulo the assignment.");
- return NULL;
- }
-
- // Get the feasible intervals
- lp_feasibility_set_t* feasible = lp_polynomial_constraint_get_feasible_set(p, sgn_condition, 0, assignment);
-
- // The list where we return the arguments
- PyObject* list = PyList_New(feasible->size);
- // Copy over to the list
- size_t i;
- for (i = 0; i < feasible->size; ++i) {
- PyObject* p = PyInterval_create(feasible->intervals + i);
- PyList_SetItem(list, i, p);
- }
- // Remove temp
- lp_feasibility_set_delete(feasible);
-
- // Return the list
- return list;
-}
-
-static PyObject*
-Polynomial_feasible_set(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* sgn_condition_obj = PyTuple_GetItem(args, 1);
- if (!PyInt_Check(sgn_condition_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Get the arguments
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
- lp_sign_condition_t sgn_condition = PyInt_AsLong(sgn_condition_obj);
-
- // Check if all but the top variable are unassigned
- if (!lp_polynomial_is_univariate_m(p, assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_set(): Polynomial must be univariate modulo the assignment.");
- return NULL;
- }
-
- // Get the feasible intervals
- lp_feasibility_set_t* feasible = lp_polynomial_constraint_get_feasible_set(p, sgn_condition, 0, assignment);
-
- // Return the list
- return PyFeasibilitySet_create(feasible);
-}
-
-static PyObject*
-Polynomial_sgn_check(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* sgn_condition_obj = PyTuple_GetItem(args, 1);
- if (!PyInt_Check(sgn_condition_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Get the arguments
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
- lp_sign_condition_t sgn_condition = PyInt_AsLong(sgn_condition_obj);
-
- // Check if all but the top variable are unassigned
- if (!lp_polynomial_is_assigned(p, assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "sgn_check(): All polynomial variables should be assigned by the given assignment.");
- return NULL;
- }
-
- // Check the sign
- int sgn = lp_polynomial_sgn(p, assignment);
- if (lp_sign_condition_consistent(sgn_condition, sgn)) {
- Py_RETURN_TRUE;
- } else {
- Py_RETURN_FALSE;
- }
-}
-
-static PyObject*
-Polynomial_pp(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p);
- lp_polynomial_t* pp = lp_polynomial_new(p_ctx);
- lp_polynomial_pp(pp, p);
- PyObject* pp_py = Polynomial_create(pp);
- return pp_py;
-}
-
-static PyObject*
-Polynomial_cont(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p);
- lp_polynomial_t* cont = lp_polynomial_new(p_ctx);
- lp_polynomial_cont(cont, p);
- PyObject* cont_py = Polynomial_create(cont);
- return cont_py;
-}
-
-static PyObject*
-Polynomial_pp_cont(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p);
- lp_polynomial_t* pp = lp_polynomial_new(p_ctx);
- lp_polynomial_t* cont = lp_polynomial_new(p_ctx);
- lp_polynomial_pp_cont(pp, cont, p);
- PyObject* pp_py = Polynomial_create(pp);
- PyObject* cont_py = Polynomial_create(cont);
- PyObject* tuple = PyTuple_New(2);
- PyTuple_SetItem(tuple, 0, pp_py);
- PyTuple_SetItem(tuple, 1, cont_py);
- return tuple;
-}
diff --git a/python/polypyPolynomial3.c b/python/polypyPolynomial3.c
deleted file mode 100644
index f76bd98e..00000000
--- a/python/polypyPolynomial3.c
+++ /dev/null
@@ -1,1691 +0,0 @@
-/**
- * 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 "polypyPolynomial.h"
-
-#include "polypyInteger.h"
-#include "polypyVariable.h"
-#include "polypyVariableOrder.h"
-#include "polypyAssignment.h"
-#include "polypyValue.h"
-#include "polypyInterval.h"
-#include "polypyFeasibilitySet.h"
-
-#include "utils.h"
-#include "variable_list.h"
-#include "sign_condition.h"
-#include "feasibility_set.h"
-#include "value.h"
-#include "polynomial_vector.h"
-
-#include
-
-static lp_polynomial_context_t* default_ctx = 0;
-
-const lp_polynomial_context_t* Polynomial_get_default_context(void) {
- if (!default_ctx) {
- default_ctx = lp_polynomial_context_new(0, Variable_get_default_db(), (lp_variable_order_t*) VariableOrder_get_default_order());
- }
- return default_ctx;
-}
-
-static void
-Polynomial_dealloc(Polynomial* self);
-
-static PyObject*
-Polynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static PyObject*
-Polynomial_richcompare(PyObject* self, PyObject* args, int op);
-
-static Py_hash_t
-Polynomial_hash(PyObject* self);
-
-static PyObject*
-Polynomial_degree(PyObject* self);
-
-static PyObject*
-Polynomial_coefficients(PyObject* self);
-
-static PyObject*
-Polynomial_reductum(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_sgn(PyObject* self, PyObject* arguments);
-
-static PyObject*
-Polynomial_sgn_check(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_rem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_prem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_sprem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_pdivrem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_spdivrem(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_gcd(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_lcm(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_derivative(PyObject* self);
-
-static PyObject*
-Polynomial_extended_gcd(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_factor(PyObject* self);
-
-static PyObject*
-Polynomial_factor_square_free(PyObject* self);
-
-static PyObject*
-Polynomial_roots_count(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_roots_isolate(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_sturm_sequence(PyObject* self);
-
-static PyObject*
-Polynomial_str(PyObject* self);
-
-static int
-Polynomial_nonzero(PyObject* self);
-
-static PyObject*
-Polynomial_add(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_neg(PyObject* self);
-
-static PyObject*
-Polynomial_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_div(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_rem_operator(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_divmod(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_pow(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_resultant(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_psc(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_subres(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_mgcd(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_evaluate(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_vars(PyObject* self);
-
-static PyObject*
-Polynomial_var(PyObject* self);
-
-static PyObject*
-Polynomial_pp(PyObject* self);
-
-static PyObject*
-Polynomial_cont(PyObject* self);
-
-static PyObject*
-Polynomial_pp_cont(PyObject* self);
-
-static PyObject*
-Polynomial_feasible_intervals(PyObject* self, PyObject* args);
-
-static PyObject*
-Polynomial_feasible_set(PyObject* self, PyObject* args);
-
-PyMethodDef Polynomial_methods[] = {
- {"degree", (PyCFunction)Polynomial_degree, METH_NOARGS, "Returns the degree of the polynomial in its top variable"},
- {"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 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"},
- {"pdivrem", (PyCFunction)Polynomial_pdivrem, METH_VARARGS, "Returns the pseudo quotient and pseudo remainder of current and given polynomial"},
- {"spdivprem", (PyCFunction)Polynomial_spdivrem, METH_VARARGS, "Returns the sparse pseudo quotient and sparse pseudo remainder of current and given polynomial"},
- {"gcd", (PyCFunction)Polynomial_gcd, METH_VARARGS, "Returns the gcd of current and given polynomial"},
- {"lcm", (PyCFunction)Polynomial_lcm, METH_VARARGS, "Returns the lcm of current and given polynomial"},
- {"extended_gcd", (PyCFunction)Polynomial_extended_gcd, METH_VARARGS, "Returns the extended gcd, i.e. (gcd, u, v), of current and given polynomial"},
- {"factor", (PyCFunction)Polynomial_factor, METH_NOARGS, "Returns the factorization of the polynomial"},
- {"factor_square_free", (PyCFunction)Polynomial_factor_square_free, METH_NOARGS, "Returns the square-free factorization of the polynomial"},
- {"roots_count", (PyCFunction)Polynomial_roots_count, METH_VARARGS, "Returns the number of real roots in the given interval"},
- {"roots_isolate", (PyCFunction)Polynomial_roots_isolate, METH_VARARGS, "Returns the list of real roots (has to be univariate modulo the assignment)"},
- {"sturm_sequence", (PyCFunction)Polynomial_sturm_sequence, METH_NOARGS, "Returns the Sturm sequence"},
- {"derivative", (PyCFunction)Polynomial_derivative, METH_NOARGS, "Returns the derivative of the polynomial"},
- {"resultant", (PyCFunction)Polynomial_resultant, METH_VARARGS, "Returns the resultant of the current and given polynomial"},
- {"psc", (PyCFunction)Polynomial_psc, METH_VARARGS, "Returns the principal subresultant coefficients of the current and given polynomial"},
- {"subres", (PyCFunction) Polynomial_subres, METH_VARARGS, "Returns the subresultant chain of the current and given polynomial"},
- {"mgcd", (PyCFunction)Polynomial_mgcd, METH_VARARGS, "Returns assumptions that the GCD of two polynomials is of same degree"},
- {"factor_square_free", (PyCFunction)Polynomial_factor_square_free, METH_NOARGS, "Returns the square-free factorization of the polynomial"},
- {"evaluate", (PyCFunction)Polynomial_evaluate, METH_VARARGS, "Returns the value of the polynomial in the given assignment (or null if it doesn't fully evaluate"},
- {"vars", (PyCFunction)Polynomial_vars, METH_NOARGS, "Returns the list of variables in the polynomial"},
- {"var", (PyCFunction)Polynomial_var, METH_NOARGS, "Returns the top variable of the polynomial"},
- {"pp", (PyCFunction)Polynomial_pp, METH_NOARGS, "Returns the primitive part of the polynomial"},
- {"cont", (PyCFunction)Polynomial_cont, METH_NOARGS, "Returns the content of the polynomial"},
- {"pp_cont", (PyCFunction)Polynomial_pp_cont, METH_NOARGS, "Returns the tuple (pp, cont) of the polynomial"},
- {"feasible_intervals", (PyCFunction)Polynomial_feasible_intervals, METH_VARARGS, "Returns feasible intervals (list) of the polynomial (has to be univariate modulo the assignment)"},
- {"feasible_set", (PyCFunction)Polynomial_feasible_set, METH_VARARGS, "Returns feasible set of the polynomial (has to be univariate modulo the assignment)"},
- {NULL} /* Sentinel */
-};
-
-PyNumberMethods Polynomial_NumberMethods = {
- Polynomial_add, // binaryfunc nb_add;
- Polynomial_sub, // binaryfunc nb_subtract;
- Polynomial_mul, // binaryfunc nb_multiply;
- Polynomial_rem_operator, // binaryfunc nb_remainder;
- Polynomial_divmod, // binaryfunc nb_divmod;
- (ternaryfunc)Polynomial_pow, // ternaryfunc nb_power;
- Polynomial_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- Polynomial_nonzero, // inquiry nb_bool;
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- 0, // unaryfunc nb_int;
- 0, // void *nb_reserved;
- 0, // unaryfunc nb_float;
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
- 0, // binaryfunc nb_floor_divide;
- Polynomial_div, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
- 0, // unaryfunc nb_index;
- 0, // binaryfunc nb_matrix_multiply;
- 0, // binaryfunc nb_inplace_matrix_multiply;
-};
-
-PyTypeObject PolynomialType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.Polynomial", // const char *tp_name;
- sizeof(Polynomial), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)Polynomial_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async;
- Polynomial_str, // reprfunc tp_repr;
- &Polynomial_NumberMethods, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- Polynomial_hash, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- Polynomial_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "Polynomial objects", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- Polynomial_richcompare, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- Polynomial_methods, // struct PyMethodDef *tp_methods;
- 0, // struct PyMemberDef *tp_members;
- 0, // struct PyGetSetDef *tp_getset;
- 0, // struct _typeobject *tp_base;
- 0, // PyObject *tp_dict;
- 0, // descrgetfunc tp_descr_get;
- 0, // descrsetfunc tp_descr_set;
- 0, // Py_ssize_t tp_dictoffset;
- 0, // initproc tp_init;
- 0, // allocfunc tp_alloc;
- Polynomial_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-static void
-Polynomial_dealloc(Polynomial* self)
-{
- if (self->p) {
- lp_polynomial_destruct(self->p);
- free(self->p);
- }
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-Polynomial_create(lp_polynomial_t* p) {
- Polynomial *self;
- self = (Polynomial*)PolynomialType.tp_alloc(&PolynomialType, 0);
- lp_polynomial_set_external(p);
- self->p = p;
- return (PyObject*) self;
-}
-
-static PyObject*
-Polynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return Polynomial_create(0);
-}
-
-static PyObject*
-Polynomial_richcompare(PyObject* self, PyObject* other, int op) {
- PyObject *result = 0;
-
- const lp_polynomial_context_t* ctx = 0;
-
- // One of them is a polynomial
- if (PyPolynomial_CHECK(self)) {
- ctx = lp_polynomial_get_context(((Polynomial*) self)->p);
- } else {
- ctx = lp_polynomial_get_context(((Polynomial*) other)->p);
- }
-
- int dec_other = 0;
- int dec_self = 0;
-
- // Check arguments
- if (!PyPolynomial_CHECK(self)) {
- if (PyVariable_CHECK(self)) {
- self = PyPolynomial_FromVariable(self, ctx);
- dec_self = 1;
- } else if (PyLong_or_Int_Check(self)) {
- self = PyPolynomial_FromLong_or_Int(self, ctx);
- dec_self = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Check arguments
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- lp_polynomial_t* self_p = ((Polynomial*) self)->p;
- lp_polynomial_t* other_p = ((Polynomial*) other)->p;
-
- int cmp = lp_polynomial_cmp(self_p, other_p);
-
- switch (op) {
- case Py_LT:
- result = cmp < 0 ? Py_True : Py_False;
- break;
- case Py_LE:
- result = cmp <= 0 ? Py_True : Py_False;
- break;
- case Py_EQ:
- result = cmp == 0 ? Py_True : Py_False;
- break;
- case Py_NE:
- result = cmp != 0 ? Py_True : Py_False;
- break;
- case Py_GT:
- result = cmp > 0 ? Py_True : Py_False;
- break;
- case Py_GE:
- result = cmp >= 0 ? Py_True : Py_False;
- break;
- }
-
- if (dec_self) {
- Py_DECREF(self);
- }
- if (dec_other) {
- Py_DECREF(other);
- }
-
- Py_INCREF(result);
- return result;
-}
-
-static Py_hash_t
-Polynomial_hash(PyObject* self) {
- Polynomial* p = (Polynomial*) self;
- Py_hash_t hash = lp_polynomial_hash(p->p);
- if (hash == -1) {
- // value -1 should not be returned as a normal return value
- hash = 0;
- }
- return hash;
-}
-
-static PyObject* Polynomial_str(PyObject* self) {
- Polynomial* p = (Polynomial*) self;
- if (p) {
- char* p_str = lp_polynomial_to_string(p->p);
- PyObject* str = PyUnicode_FromString(p_str);
- free(p_str);
- return str;
- } else {
- Py_RETURN_NONE;
- }
-}
-
-PyObject*
-PyPolynomial_FromVariable(PyObject* variable, const lp_polynomial_context_t* ctx) {
- // The variable
- lp_variable_t x = ((Variable*) variable)->x;
-
- // The constant
- lp_integer_t one;
- lp_integer_construct_from_int(ctx->K, &one, 1);
-
- // The x polynomial
- lp_polynomial_t* p_x = lp_polynomial_alloc();
- lp_polynomial_construct_simple(p_x, ctx, &one, x, 1);
-
- // Remove temps
- lp_integer_destruct(&one);
-
- // Return the polynomial
- PyObject* result = Polynomial_create(p_x);
- Py_INCREF(result);
- return result;
-}
-
-PyObject*
-PyPolynomial_FromLong_or_Int(PyObject* number, const lp_polynomial_context_t* ctx) {
- // The constants
- lp_integer_t c;
- PyLong_or_Int_to_integer(number, 0, &c);
-
- // The c polynomial
- lp_polynomial_t* p_c = lp_polynomial_alloc();
- lp_polynomial_construct_simple(p_c, ctx, &c, 0, 0);
-
- // Remove temps
- lp_integer_destruct(&c);
-
- // Return the polynomial
- PyObject* result = Polynomial_create(p_c);
- Py_INCREF(result);
- return result;
-}
-
-static PyObject*
-Polynomial_add(PyObject* self, PyObject* other) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- return Polynomial_add(other, self);
- }
-
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Check argument
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Get arguments
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (p1_ctx != p2_ctx) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Add the polynomials
- lp_polynomial_t* sum = lp_polynomial_new(p1_ctx);
- lp_polynomial_add(sum, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(sum);
-}
-
-static PyObject*
-Polynomial_neg(PyObject* self) {
- Polynomial* p = (Polynomial*) self;
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p->p);
- lp_polynomial_t* neg = lp_polynomial_new(p_ctx);
- lp_polynomial_neg(neg, p->p);
- return Polynomial_create(neg);
-}
-
-static PyObject*
-Polynomial_sub(PyObject* self, PyObject* other) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- Polynomial* sub = (Polynomial*) Polynomial_sub(other, self);
- lp_polynomial_neg(sub->p, sub->p);
- return (PyObject*) sub;
- }
-
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Check argument
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Get arguments
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (p1_ctx != p2_ctx) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Subtract the polynomials
- lp_polynomial_t* sub = lp_polynomial_new(p1_ctx);
- lp_polynomial_sub(sub, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(sub);
-}
-
-static PyObject*
-Polynomial_mul(PyObject* self, PyObject* other) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- return Polynomial_mul(other, self);
- }
-
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Check argument
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Get arguments
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* mul = lp_polynomial_new(p1_ctx);
- lp_polynomial_mul(mul, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(mul);
-}
-
-
-static PyObject*
-Polynomial_pow(PyObject* self, PyObject* other) {
- // Check arguments
- if (!PyPolynomial_CHECK(self) || !PyLong_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- Polynomial* p = (Polynomial*) self;
- long n = PyLong_AsLong(other);
- if (n < 0) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p->p);
- // Compute
- lp_polynomial_t* pow = lp_polynomial_new(p_ctx);
- lp_polynomial_pow(pow, p->p, n);
- // Return the result
- return Polynomial_create(pow);
-}
-
-static PyObject*
-Polynomial_div(PyObject* self, PyObject* other) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* div = lp_polynomial_new(p1_ctx);
- lp_polynomial_div(div, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(div);
-}
-
-static PyObject*
-Polynomial_rem_operator(PyObject* self, PyObject* other) {
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* rem = lp_polynomial_new(p1_ctx);
- lp_polynomial_rem(rem, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(rem);
-}
-
-enum rem_type {
- REM_EXACT,
- REM_PSEUDO,
- REM_SPARSE_PSEUDO
-};
-
-static PyObject*
-Polynomial_divmod_general(PyObject* self, PyObject* args, enum rem_type type) {
-
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // self is always a polynomial
- Polynomial *p1 = (Polynomial *) self;
- const lp_polynomial_context_t *p1_ctx = lp_polynomial_get_context(p1->p);
-
- // check that there is only one other
- PyObject *other;
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- other = PyTuple_GetItem(args, 0);
- } else {
- other = args;
- }
- // make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial *p2 = (Polynomial *) other;
- const lp_polynomial_context_t *p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Divide the polynomials
- lp_polynomial_t *rem = lp_polynomial_new(p1_ctx);
- lp_polynomial_t *div = lp_polynomial_new(p1_ctx);
- switch (type) {
- case REM_EXACT:
- lp_polynomial_divrem(div, rem, p1->p, p2->p);
- break;
- case REM_PSEUDO:
- lp_polynomial_pdivrem(div, rem, p1->p, p2->p);
- break;
- case REM_SPARSE_PSEUDO:
- lp_polynomial_spdivrem(div, rem, p1->p, p2->p);
- break;
- }
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- PyObject *pair = PyTuple_New(2);
- PyObject *divObj = Polynomial_create(div);
- PyObject *remObj = Polynomial_create(rem);
- Py_INCREF(divObj);
- Py_INCREF(remObj);
- PyTuple_SetItem(pair, 0, divObj);
- PyTuple_SetItem(pair, 1, remObj);
- return pair;
-}
-
-static PyObject*
-Polynomial_divmod(PyObject* self, PyObject* other) {
- return Polynomial_divmod_general(self, other, REM_EXACT);
-}
-
-static PyObject*
-Polynomial_pdivrem(PyObject* self, PyObject* other) {
- return Polynomial_divmod_general(self, other, REM_PSEUDO);
-}
-
-static PyObject*
-Polynomial_spdivrem(PyObject* self, PyObject* other) {
- return Polynomial_divmod_general(self, other, REM_SPARSE_PSEUDO);
-}
-
-static int
-Polynomial_nonzero(PyObject* self) {
- // Get arguments
- Polynomial* p = (Polynomial*) self;
- // Return the result
- return !lp_polynomial_is_zero(p->p);
-}
-
-static PyObject*
-Polynomial_rem_general(PyObject* self, PyObject* args, enum rem_type type) {
- int dec_other = 0;
-
- if (!PyPolynomial_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* rem = lp_polynomial_new(p1_ctx);
- switch (type) {
- case REM_EXACT:
- lp_polynomial_rem(rem, p1->p, p2->p);
- break;
- case REM_PSEUDO:
- lp_polynomial_prem(rem, p1->p, p2->p);
- break;
- case REM_SPARSE_PSEUDO:
- lp_polynomial_sprem(rem, p1->p, p2->p);
- break;
- }
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(rem);
-}
-
-static PyObject*
-Polynomial_rem(PyObject* self, PyObject* other) {
- return Polynomial_rem_general(self, other, REM_EXACT);
-}
-
-static PyObject*
-Polynomial_prem(PyObject* self, PyObject* other) {
- return Polynomial_rem_general(self, other, REM_PSEUDO);
-}
-
-static PyObject*
-Polynomial_sprem(PyObject* self, PyObject* other) {
- return Polynomial_rem_general(self, other, REM_SPARSE_PSEUDO);
-}
-
-static PyObject*
-Polynomial_gcd(PyObject* self, PyObject* args) {
-
- int dec_other = 0;
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* gcd = lp_polynomial_new(p1_ctx);
- lp_polynomial_gcd(gcd, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(gcd);
-}
-
-static PyObject*
-Polynomial_lcm(PyObject* self, PyObject* args) {
-
- int dec_other = 0;
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // other can be a variable or a number
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Multiply the polynomials
- lp_polynomial_t* lcm = lp_polynomial_new(p1_ctx);
- lp_polynomial_lcm(lcm, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(lcm);
-}
-
-enum subres_type {
- SUBRES,
- SUBRES_PSC
-};
-
-static PyObject*
-Polynomial_subres_impl(PyObject* self, PyObject* args, enum subres_type type) {
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- int dec_other = 0;
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Other polynomial
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Check the arguments (must be same top variable)
- if (lp_polynomial_is_constant(p1->p) || lp_polynomial_is_constant(p2->p)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- if (lp_polynomial_top_variable(p1->p) != lp_polynomial_top_variable(p2->p)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Allocate the polynomials for the sequence
- size_t p1_deg = lp_polynomial_degree(p1->p);
- size_t p2_deg = lp_polynomial_degree(p2->p);
- int size = p1_deg > p2_deg ? p2_deg + 1 : p1_deg + 1;
-
- lp_polynomial_t** S = malloc(sizeof(lp_polynomial_t*)*size);
- int i;
- for (i = 0; i < size; ++ i) {
- S[i] = lp_polynomial_new(p1_ctx);
- }
-
- switch (type) {
- case SUBRES:
- // Compute the full subres
- lp_polynomial_subres(S, p1->p, p2->p);
- break;
- case SUBRES_PSC:
- // Compute the psc
- lp_polynomial_psc(S, p1->p, p2->p);
- break;
- }
-
- // Copy the polynomials into a list
- PyObject* list = PyList_New(size);
- for (i = 0; i < size; ++i) {
- PyObject* p = Polynomial_create(S[i]);
- PyList_SetItem(list, i, p);
- }
- free(S);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return list;
-}
-
-static PyObject*
-Polynomial_psc(PyObject* self, PyObject* args) {
- return Polynomial_subres_impl(self, args, SUBRES_PSC);
-}
-
-static PyObject*
-Polynomial_subres(PyObject* self, PyObject* args) {
- return Polynomial_subres_impl(self, args, SUBRES);
-}
-
-static PyObject*
-Polynomial_mgcd(PyObject* self, PyObject* args) {
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Need two arguments.");
- return NULL;
- }
-
- // Assignment
- PyObject* py_assignment = PyTuple_GetItem(args, 1);
- if (!PyAssignment_CHECK(py_assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Second argument should be an assignment.");
- return NULL;
- }
- const lp_assignment_t* assignment = ((Assignment*) py_assignment)->assignment;
-
- // Other polynomial
- PyObject* other = PyTuple_GetItem(args, 0);
-
- int dec_other = 0;
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): First argument should be a polynomial.");
- return NULL;
- }
- }
-
- // Othe polynomial
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Polynomials should be over the same context.");
- return NULL;
- }
-
- // Check the arguments (must be same top variable)
- if (lp_polynomial_is_constant(p1->p) || lp_polynomial_is_constant(p2->p)) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Polynomials should be over the same top variables.");
- return NULL;
- }
-
- if (lp_polynomial_top_variable(p1->p) != lp_polynomial_top_variable(p2->p)) {
- PyErr_SetString(PyExc_RuntimeError, "mgcd(): Polynomials should be over the same top variables.");
- return NULL;
- }
-
- // Compute the gcd
- lp_polynomial_vector_t* mgcd = lp_polynomial_mgcd(p1->p, p2->p, assignment);
-
- // Copy the polynomials into a list
- size_t size = lp_polynomial_vector_size(mgcd);
- PyObject* list = PyList_New(size);
- size_t i;
- for (i = 0; i < size; ++i) {
- lp_polynomial_t* mgcd_i = lp_polynomial_vector_at(mgcd, i);
- PyObject* p = Polynomial_create(mgcd_i);
- PyList_SetItem(list, i, p);
- }
- lp_polynomial_vector_delete(mgcd);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return list;
-}
-
-static PyObject*
-Polynomial_resultant(PyObject* self, PyObject* args) {
-
- // self is always a polynomial
- Polynomial* p1 = (Polynomial*) self;
- const lp_polynomial_context_t* p1_ctx = lp_polynomial_get_context(p1->p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* other = PyTuple_GetItem(args, 0);
-
- int dec_other = 0;
-
- // Make sure other is a polynomial
- if (!PyPolynomial_CHECK(other)) {
- if (PyVariable_CHECK(other)) {
- other = PyPolynomial_FromVariable(other, p1_ctx);
- dec_other = 1;
- } else if (PyLong_or_Int_Check(other)) {
- other = PyPolynomial_FromLong_or_Int(other, p1_ctx);
- dec_other = 1;
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
-
- // Other polynomial
- Polynomial* p2 = (Polynomial*) other;
- const lp_polynomial_context_t* p2_ctx = lp_polynomial_get_context(p2->p);
- if (!lp_polynomial_context_equal(p1_ctx, p2_ctx)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Check the arguments (must be same top variable)
- if (lp_polynomial_is_constant(p1->p) || lp_polynomial_is_constant(p2->p)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- if (lp_polynomial_top_variable(p1->p) != lp_polynomial_top_variable(p2->p)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Allocate the resultant
- lp_polynomial_t* resultant = lp_polynomial_new(p1_ctx);
-
- // Compute the psc
- lp_polynomial_resultant(resultant, p1->p, p2->p);
-
- if (dec_other) {
- Py_DECREF(other);
- }
-
- // Return the result
- return Polynomial_create(resultant);
-}
-
-static PyObject*
-Polynomial_extended_gcd(PyObject* self, PyObject* args) {
- return 0;
-}
-
-static PyObject*
-Polynomial_factor(PyObject* self) {
- return 0;
-}
-
-// Creates a python list from the factors, taking over the polynomials
-PyObject* factors_to_PyList(lp_polynomial_t** factors, size_t* multiplicities, size_t size) {
- // Construct the result
- PyObject* factors_list = PyList_New(size);
-
- // Copy the constant
- // Copy over the factors
- size_t i;
- for (i = 0; i < size; ++ i) {
- PyObject* p_i = Polynomial_create(factors[i]);
- Py_INCREF(p_i);
- PyObject* d = PyLong_FromSize_t(multiplicities[i]);
- PyObject* pair = PyTuple_New(2);
- PyTuple_SetItem(pair, 0, p_i);
- PyTuple_SetItem(pair, 1, d);
- PyList_SetItem(factors_list, i, pair);
- }
-
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-Polynomial_factor_square_free(PyObject* self) {
- // Get arguments
- Polynomial* p = (Polynomial*) self;
- // Factor
- lp_polynomial_t** factors = 0;
- size_t* multiplicities = 0;
- size_t factors_size = 0;
- lp_polynomial_factor_square_free(p->p, &factors, &multiplicities, &factors_size);
- // Create the list
- PyObject* factors_list = factors_to_PyList(factors, multiplicities, factors_size);
- // Get rid of the factors (not the polynomials)
- free(factors);
- free(multiplicities);
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-Polynomial_roots_count(PyObject* self, PyObject* args) {
- return 0;
-}
-
-static PyObject*
-Polynomial_roots_isolate(PyObject* self, PyObject* args) {
-
- size_t i;
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
-
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
-
- // Check that the top variable is the only unassigned
- if (!lp_polynomial_is_univariate_m(p, assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "roots_count(): Polynomial must be univariate modulo the assignment.");
- return NULL;
- }
-
- // Get the degree of the polynomial and allocate the values
- lp_value_t* roots = malloc(sizeof(lp_value_t)*lp_polynomial_degree(p));
- size_t roots_size = 0;
-
- // Get the roots
- lp_polynomial_roots_isolate(p, assignment, roots, &roots_size);
-
- // Generate a list of roots
- PyObject* list = PyList_New(roots_size);
-
- for (i = 0; i < roots_size; ++ i) {
- PyObject* c = PyValue_create(roots + i);
- PyList_SetItem(list, i, c);
- }
-
- // Get rid of the temporaries
- for (i = 0; i < roots_size; ++ i) {
- lp_value_destruct(roots + i);
- }
- free(roots);
-
- // Return the list
- return list;
-}
-
-static PyObject*
-Polynomial_derivative(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_polynomial_t* p_derivative = lp_polynomial_new(lp_polynomial_get_context(p));
- lp_polynomial_derivative(p_derivative, p);
- return Polynomial_create(p_derivative);
-}
-
-static PyObject*
-Polynomial_sturm_sequence(PyObject* self) {
- return 0;
-}
-
-static PyObject*
-Polynomial_degree(PyObject* self) {
- Polynomial* p = (Polynomial*) self;
- return PyLong_FromLong(lp_polynomial_degree(p->p));
-}
-
-static PyObject*
-Polynomial_coefficients(PyObject* self) {
- size_t i;
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- size_t size = lp_polynomial_degree(p) + 1;
-
- // Get the coefficients
- const lp_polynomial_context_t* ctx = lp_polynomial_get_context(p);
-
- // Copy the polynomials into a list
- PyObject* list = PyList_New(size);
- for (i = 0; i < size; ++i) {
- lp_polynomial_t* c_p = lp_polynomial_new(ctx);
- lp_polynomial_get_coefficient(c_p, p, i);
- PyObject* c = Polynomial_create(c_p);
- PyList_SetItem(list, i, c);
- }
-
- return list;
-}
-
-static PyObject*
-Polynomial_vars(PyObject* self) {
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
-
- lp_variable_list_t p_vars;
- lp_variable_list_construct(&p_vars);
-
- // Get the variables
- lp_polynomial_get_variables(p, &p_vars);
-
- // Copy the polynomials into a list
- PyObject* list = PyList_New(p_vars.list_size);
- size_t i;
- for (i = 0; i < p_vars.list_size; ++i) {
- PyObject* c = PyVariable_create(p_vars.list[i]);
- PyList_SetItem(list, i, c);
- }
-
- lp_variable_list_destruct(&p_vars);
-
- return list;
-}
-
-static PyObject*
-Polynomial_var(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- return PyVariable_create(lp_polynomial_top_variable(p));
-}
-
-
-static PyObject*
-Polynomial_reductum(PyObject* self, PyObject* args) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- const lp_polynomial_context_t* ctx = lp_polynomial_get_context(p);
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) > 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_assignment_t* assignment = 0;
-
- if (PyTuple_Size(args) == 1) {
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- } else {
- assignment = ((Assignment*) assignment_obj)->assignment;
- }
- }
-
- lp_polynomial_t* result = lp_polynomial_new(ctx);
- if (assignment) {
- lp_polynomial_reductum_m(result, p, assignment);
- } else {
- lp_polynomial_reductum(result, p);
- }
-
- return Polynomial_create(result);
-}
-
-static PyObject*
-Polynomial_sgn(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
-
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
-
- int sgn = lp_polynomial_sgn(p, assignment);
-
- return PyLong_FromLong(sgn);
-}
-
-
-static PyObject*
-Polynomial_evaluate(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
-
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
-
- lp_value_t* value = lp_polynomial_evaluate(p, assignment);
- PyObject* value_obj = PyValue_create(value);
- lp_value_delete(value);
-
- return value_obj;
-}
-
-static PyObject*
-Polynomial_feasible_intervals(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): Needs two arguments, an assignment and a sign condition.");
- return NULL;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
- if (!PyAssignment_CHECK(assignment_obj)) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): First argument must be an assignment.");
- return NULL;
- }
-
- PyObject* sgn_condition_obj = PyTuple_GetItem(args, 1);
- if (!PyLong_Check(sgn_condition_obj)) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): Second argument must be a sign-condition.");
- return NULL;
- }
-
- // Get the arguments
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
- lp_sign_condition_t sgn_condition = PyLong_AsLong(sgn_condition_obj);
-
- // Check if all but the top variable are unassigned
- if (!lp_polynomial_is_univariate_m(p, assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_intervals(): Polynomial must be univariate modulo the assignment.");
- return NULL;
- }
-
- // Get the feasible intervals
- lp_feasibility_set_t* feasible = lp_polynomial_constraint_get_feasible_set(p, sgn_condition, 0, assignment);
-
- // The list where we return the arguments
- PyObject* list = PyList_New(feasible->size);
- // Copy over to the list
- size_t i;
- for (i = 0; i < feasible->size; ++i) {
- PyObject* p = PyInterval_create(feasible->intervals + i);
- PyList_SetItem(list, i, p);
- }
- // Remove temp
- lp_feasibility_set_delete(feasible);
-
- // Return the list
- return list;
-}
-
-static PyObject*
-Polynomial_feasible_set(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* sgn_condition_obj = PyTuple_GetItem(args, 1);
- if (!PyLong_Check(sgn_condition_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Get the arguments
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
- lp_sign_condition_t sgn_condition = PyLong_AsLong(sgn_condition_obj);
-
- // Check if all but the top variable are unassigned
- if (!lp_polynomial_is_univariate_m(p, assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "feasible_set(): Polynomial must be univariate modulo the assignment.");
- return NULL;
- }
-
- // Get the feasible intervals
- lp_feasibility_set_t* feasible = lp_polynomial_constraint_get_feasible_set(p, sgn_condition, 0, assignment);
-
- // Return the list
- return PyFeasibilitySet_create(feasible);
-}
-
-static PyObject*
-Polynomial_sgn_check(PyObject* self, PyObject* args) {
-
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* assignment_obj = PyTuple_GetItem(args, 0);
- if (!PyAssignment_CHECK(assignment_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- PyObject* sgn_condition_obj = PyTuple_GetItem(args, 1);
- if (!PyLong_Check(sgn_condition_obj)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- // Get the arguments
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- lp_assignment_t* assignment = ((Assignment*) assignment_obj)->assignment;
- lp_sign_condition_t sgn_condition = PyLong_AsLong(sgn_condition_obj);
-
- // Check if all but the top variable are unassigned
- if (!lp_polynomial_is_assigned(p, assignment)) {
- PyErr_SetString(PyExc_RuntimeError, "sgn_check(): All polynomial variables should be assigned by the given assignment.");
- return NULL;
- }
-
- // Check the sign
- int sgn = lp_polynomial_sgn(p, assignment);
- if (lp_sign_condition_consistent(sgn_condition, sgn)) {
- Py_RETURN_TRUE;
- } else {
- Py_RETURN_FALSE;
- }
-}
-
-static PyObject*
-Polynomial_pp(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p);
- lp_polynomial_t* pp = lp_polynomial_new(p_ctx);
- lp_polynomial_pp(pp, p);
- PyObject* pp_py = Polynomial_create(pp);
- return pp_py;
-}
-
-static PyObject*
-Polynomial_cont(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p);
- lp_polynomial_t* cont = lp_polynomial_new(p_ctx);
- lp_polynomial_cont(cont, p);
- PyObject* cont_py = Polynomial_create(cont);
- return cont_py;
-}
-
-static PyObject*
-Polynomial_pp_cont(PyObject* self) {
- lp_polynomial_t* p = ((Polynomial*) self)->p;
- const lp_polynomial_context_t* p_ctx = lp_polynomial_get_context(p);
- lp_polynomial_t* pp = lp_polynomial_new(p_ctx);
- lp_polynomial_t* cont = lp_polynomial_new(p_ctx);
- lp_polynomial_pp_cont(pp, cont, p);
- PyObject* pp_py = Polynomial_create(pp);
- PyObject* cont_py = Polynomial_create(cont);
- PyObject* tuple = PyTuple_New(2);
- PyTuple_SetItem(tuple, 0, pp_py);
- PyTuple_SetItem(tuple, 1, cont_py);
- return tuple;
-}
diff --git a/python/polypyUPolynomial.c b/python/polypyUPolynomial.c
index 8ca57cb2..bb3831e9 100644
--- a/python/polypyUPolynomial.c
+++ b/python/polypyUPolynomial.c
@@ -17,12 +17,910 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
-#if PY_MAJOR_VERSION >= 3
-#include "polypyUPolynomial3.c"
-#else
-#include "polypyUPolynomial2.c"
-#endif
+#include "polypyUPolynomial.h"
+#include "polypyInteger.h"
+#include "polypyAlgebraicNumber.h"
+#include "utils.h"
+
+#include "rational_interval.h"
+
+#include
+
+static void
+UPolynomial_dealloc(UPolynomialObject* self);
+
+static PyObject*
+UPolynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static int
+UPolynomial_init(UPolynomialObject* self, PyObject* args);
+
+static PyObject*
+UPolynomial_richcompare(PyObject* self, PyObject* other, int op);
+
+static PyObject*
+UPolynomial_degree(PyObject* self);
+
+static PyObject*
+UPolynomial_coefficients(PyObject* self);
+
+static PyObject*
+UPolynomial_ring(PyObject* self);
+
+static PyObject*
+UPolynomial_gcd(PyObject* self, PyObject* args);
+
+static PyObject*
+UPolynomial_derivative(PyObject* self);
+
+static PyObject*
+UPolynomial_extended_gcd(PyObject* self, PyObject* args);
+
+static PyObject*
+UPolynomial_factor(PyObject* self);
+
+static PyObject*
+UPolynomial_factor_square_free(PyObject* self);
+
+static PyObject*
+UPolynomial_roots_count(PyObject* self, PyObject* args);
+
+static PyObject*
+UPolynomial_roots_isolate(PyObject* self);
+
+static PyObject*
+UPolynomial_sturm_sequence(PyObject* self);
+
+static PyObject*
+UPolynomial_roots_find_Zp(PyObject* self);
+
+static PyObject*
+UPolynomial_evaluate(PyObject* self, PyObject* args);
+
+static PyObject*
+UPolynomial_to_ring(PyObject* self, PyObject* args);
+
+static PyObject*
+UPolynomial_str(PyObject* self);
+
+static int
+UPolynomialObject_nonzero(PyObject* self);
+
+static PyObject*
+UPolynomialObject_add(PyObject* self, PyObject* other);
+
+static PyObject*
+UPolynomialObject_sub(PyObject* self, PyObject* other);
+
+static PyObject*
+UPolynomialObject_mul(PyObject* self, PyObject* other);
+
+static PyObject*
+UPolynomialObject_div(PyObject* self, PyObject* args);
+
+static PyObject*
+UPolynomialObject_rem(PyObject* self, PyObject* args);
+
+static PyObject*
+UPolynomialObject_divmod(PyObject* self, PyObject* args);
+
+static PyObject*
+UPolynomialObject_pow(PyObject* self, PyObject* other);
+
+static PyObject*
+UPolynomialObject_neg(PyObject* self);
+
+PyMethodDef UPolynomial_methods[] = {
+ {"degree", (PyCFunction)UPolynomial_degree, METH_NOARGS, "Returns the degree of the polynomial"},
+ {"coefficients", (PyCFunction)UPolynomial_coefficients, METH_NOARGS, "Returns a dictionary from degrees to coefficients"},
+ {"ring", (PyCFunction)UPolynomial_ring, METH_NOARGS, "Returns the ring of the polynomial"},
+ {"to_ring", (PyCFunction)UPolynomial_to_ring, METH_VARARGS, "Returns the polynomial in the given ring"},
+ {"gcd", (PyCFunction)UPolynomial_gcd, METH_VARARGS, "Returns the gcd of current and given polynomial in the given ring"},
+ {"extended_gcd", (PyCFunction)UPolynomial_extended_gcd, METH_VARARGS, "Returns the extended gcd, i.e. (gcd, u, v), of current and given polynomial in the given ring"},
+ {"factor", (PyCFunction)UPolynomial_factor, METH_NOARGS, "Returns the factorization of the polynomial"},
+ {"factor_square_free", (PyCFunction)UPolynomial_factor_square_free, METH_NOARGS, "Returns the square-free factorization of the polynomial"},
+ {"roots_count", (PyCFunction)UPolynomial_roots_count, METH_VARARGS, "Returns the number of real roots in the given interval"},
+ {"roots_isolate", (PyCFunction)UPolynomial_roots_isolate, METH_NOARGS, "Returns the list of real roots"},
+ {"sturm_sequence", (PyCFunction)UPolynomial_sturm_sequence, METH_NOARGS, "Returns the Sturm sequence"},
+ {"roots_find_Zp", (PyCFunction)UPolynomial_roots_find_Zp, METH_NOARGS, "Returns the roots of the polynomial in Zp"},
+ {"derivative", (PyCFunction)UPolynomial_derivative, METH_NOARGS, "Returns the derivative of the polynomial"},
+ {"evaluate", (PyCFunction)UPolynomial_evaluate, METH_VARARGS, "Returns the value of the polynomial at the given point"},
+ {NULL} /* Sentinel */
+};
+
+PyNumberMethods UPolynomial_NumberMethods = {
+ UPolynomialObject_add, // binaryfunc nb_add;
+ UPolynomialObject_sub, // binaryfunc nb_subtract;
+ UPolynomialObject_mul, // binaryfunc nb_multiply;
+ UPolynomialObject_rem, // binaryfunc nb_remainder;
+ UPolynomialObject_divmod, // binaryfunc nb_divmod;
+ (ternaryfunc)UPolynomialObject_pow, // ternaryfunc nb_power;
+ UPolynomialObject_neg, // unaryfunc nb_negative;
+ NULL, // unaryfunc nb_positive;
+ NULL, // unaryfunc nb_absolute;
+ UPolynomialObject_nonzero, // inquiry nb_bool;
+ NULL, // unaryfunc nb_invert;
+ NULL, // binaryfunc nb_lshift;
+ NULL, // binaryfunc nb_rshift;
+ NULL, // binaryfunc nb_and;
+ NULL, // binaryfunc nb_xor;
+ NULL, // binaryfunc nb_or;
+ NULL, // unaryfunc nb_int;
+ NULL, // void *nb_reserved;
+ NULL, // unaryfunc nb_float;
+ NULL, // binaryfunc nb_inplace_add;
+ NULL, // binaryfunc nb_inplace_subtract;
+ NULL, // binaryfunc nb_inplace_multiply;
+ NULL, // binaryfunc nb_inplace_remainder;
+ NULL, // ternaryfunc nb_inplace_power;
+ NULL, // binaryfunc nb_inplace_lshift;
+ NULL, // binaryfunc nb_inplace_rshift;
+ NULL, // binaryfunc nb_inplace_and;
+ NULL, // binaryfunc nb_inplace_xor;
+ NULL, // binaryfunc nb_inplace_or;
+ NULL, // binaryfunc nb_floor_divide;
+ UPolynomialObject_div, // binaryfunc nb_true_divide;
+ NULL, // binaryfunc nb_inplace_floor_divide;
+ NULL, // binaryfunc nb_inplace_true_divide;
+ NULL, // unaryfunc nb_index;
+ NULL, // binaryfunc nb_matrix_multiply;
+ NULL, // binaryfunc nb_inplace_matrix_multiply;
+};
+
+PyTypeObject UPolynomialType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.UPolynomial", // const char *tp_name;
+ sizeof(UPolynomialObject), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)UPolynomial_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async;
+ UPolynomial_str, // reprfunc tp_repr;
+ &UPolynomial_NumberMethods, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ NULL, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ UPolynomial_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "Univariate polynomial objects", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ UPolynomial_richcompare, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ UPolynomial_methods, // struct PyMethodDef *tp_methods;
+ NULL, // struct PyMemberDef *tp_members;
+ NULL, // struct PyGetSetDef *tp_getset;
+ NULL, // struct _typeobject *tp_base;
+ NULL, // PyObject *tp_dict;
+ NULL, // descrgetfunc tp_descr_get;
+ NULL, // descrsetfunc tp_descr_set;
+ 0, // Py_ssize_t tp_dictoffset;
+ (initproc)UPolynomial_init, // initproc tp_init;
+ NULL, // allocfunc tp_alloc;
+ UPolynomial_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+static void
+UPolynomial_dealloc(UPolynomialObject* self)
+{
+ if (self->p) lp_upolynomial_delete(self->p);
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+PyObject*
+PyUPolynomial_create(lp_upolynomial_t* p) {
+ UPolynomialObject *self;
+ self = (UPolynomialObject*)UPolynomialType.tp_alloc(&UPolynomialType, 0);
+ if (self != NULL) {
+ self->p = p;
+ }
+ return (PyObject *)self;
+}
+
+static PyObject*
+UPolynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return PyUPolynomial_create(NULL);
+}
+
+static int
+UPolynomial_init(UPolynomialObject* self, PyObject* args)
+{
+ if (PyTuple_Check(args)) {
+ if (PyTuple_Size(args) == 0) {
+ // Just a zero polynomial
+ int coeff[] = { 0 };
+ self->p = lp_upolynomial_construct_from_int(lp_Z, 0, coeff);
+ } else if (PyTuple_Size(args) <= 2) {
+ lp_int_ring_t* K = lp_Z;
+
+ // Get the list of coefficients
+ PyObject* coefficients = PyTuple_GetItem(args, 0);
+
+ // The first item might be the ring
+ if (PyCoefficientRing_CHECK(coefficients)) {
+ K = ((CoefficientRing*) coefficients)->K;
+ coefficients = PyTuple_GetItem(args, 1);
+ } else {
+ if (PyTuple_Size(args) == 2) {
+ return -1;
+ }
+ }
+
+ if (PyList_Check(coefficients)) {
+ Py_ssize_t size = PyList_Size(coefficients);
+ if (size > 0) {
+ long c_ints[size];
+ for (Py_ssize_t i = 0; i < size; ++ i) {
+ PyObject* c_i = PyList_GetItem(coefficients, i);
+ if (!PyLong_Check(c_i)) {
+ return -1;
+ } else {
+ c_ints[i] = PyLong_AsLong(c_i);
+ }
+ }
+ self->p = lp_upolynomial_construct_from_long(K, size-1, c_ints);
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
+
+static PyObject*
+UPolynomial_richcompare(PyObject* self, PyObject* other, int op) {
+ PyObject *result = NULL;
+
+ if (!PyUPolynomial_CHECK(other) && !PyLong_Check(other)) {
+ //IAM: Surely we can be braver here?
+ // if op == Py_EQ we could return Py_False
+ // if op == Py_NE we could return Py_True
+ // I am sure this holds for other versions of:
+ // _cmp AND _richcompare in this codebase.
+ result = Py_NotImplemented;
+ } else {
+ lp_upolynomial_t* self_p = ((UPolynomialObject*) self)->p;
+ lp_upolynomial_t* other_p = NULL;
+ if (PyUPolynomial_CHECK(other)) {
+ other_p = ((UPolynomialObject*) other)->p;
+ } else {
+ long c = PyLong_AsLong(other);
+ const lp_int_ring_t* K = lp_upolynomial_ring(self_p);
+ other_p = lp_upolynomial_construct_from_long(K, 0, &c);
+ }
+
+ int cmp = lp_upolynomial_cmp(self_p, other_p);
+
+ switch (op) {
+ case Py_LT:
+ result = cmp < 0 ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ result = cmp <= 0 ? Py_True : Py_False;
+ break;
+ case Py_EQ:
+ result = cmp == 0 ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = cmp != 0 ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ result = cmp > 0 ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ result = cmp >= 0 ? Py_True : Py_False;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (PyLong_Check(other)) {
+ lp_upolynomial_delete(other_p);
+ }
+ }
+
+ Py_INCREF(result);
+ return result;
+}
+
+static PyObject*
+UPolynomial_degree(PyObject* self) {
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ if (p) {
+ return PyLong_FromUnsignedLong(lp_upolynomial_degree(p->p));
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject*
+UPolynomial_coefficients(PyObject* self) {
+ lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
+ size_t size = lp_upolynomial_degree(p) + 1;
+
+ lp_integer_t coefficients[size];
+ for (size_t i = 0; i < size; ++ i) {
+ lp_integer_construct_from_int(lp_Z, coefficients + i, 0);
+ }
+
+ lp_upolynomial_unpack(p, coefficients);
+
+ PyObject* list = PyList_New(size);
+
+ for (size_t i = 0; i < size; ++ i) {
+ PyObject* c = integer_to_PyLong(coefficients + i);
+ PyList_SetItem(list, i, c);
+ lp_integer_destruct(coefficients + i);
+ }
+
+ return list;
+}
+
+static PyObject*
+UPolynomial_ring(PyObject* self) {
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ if (p) {
+ lp_int_ring_t* K = (lp_int_ring_t*) lp_upolynomial_ring(p->p);
+ lp_int_ring_attach(K);
+ return PyCoefficientRing_create(K);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject*
+UPolynomial_to_ring(PyObject* self, PyObject* args) {
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ if (p) {
+ // Get the ring argument
+ if (PyTuple_Size(args) == 1) {
+ // Get the ring
+ PyObject* arg = PyTuple_GetItem(args, 0);
+ if (PyCoefficientRing_CHECK(arg)) {
+ CoefficientRing* K = (CoefficientRing*)arg;
+ lp_upolynomial_t* p_K = lp_upolynomial_construct_copy_K(K->K, p->p);
+ return PyUPolynomial_create(p_K);
+ } else {
+ Py_RETURN_NONE;
+ }
+ } else {
+ Py_RETURN_NONE;
+ }
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject* UPolynomial_str(PyObject* self) {
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ if (p) {
+ char* p_str = lp_upolynomial_to_string(p->p);
+ PyObject* str = PyUnicode_FromString(p_str);
+ free(p_str);
+ return str;
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+// Add other integer
+static PyObject*
+UPolynomialObject_add_number(PyObject* self, PyObject* other) {
+ UPolynomialObject* p1 = (UPolynomialObject*) self;
+ lp_integer_t c;
+ const lp_int_ring_t* K = lp_upolynomial_ring(p1->p);
+ PyLong_or_Int_to_integer(other, K, &c);
+ lp_upolynomial_t* c_p = lp_upolynomial_construct(K, 0, &c);
+ lp_upolynomial_t* sum = lp_upolynomial_add(p1->p, c_p);
+ lp_upolynomial_delete(c_p);
+ lp_integer_destruct(&c);
+ return PyUPolynomial_create(sum);
+}
+
+static PyObject*
+UPolynomialObject_add(PyObject* self, PyObject* other) {
+ // Integer addition
+ if (PyLong_or_Int_Check(other)) {
+ return UPolynomialObject_add_number(self, other);
+ }
+ if (PyLong_or_Int_Check(self)) {
+ return UPolynomialObject_add_number(other, self);
+ }
+ // Check arguments
+ if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ // Get arguments
+ UPolynomialObject* p1 = (UPolynomialObject*) self;
+ UPolynomialObject* p2 = (UPolynomialObject*) other;
+ // Add the polynomials
+ lp_upolynomial_t* sum = lp_upolynomial_add(p1->p, p2->p);
+ // Return the result
+ return PyUPolynomial_create(sum);
+}
+
+static PyObject*
+UPolynomialObject_sub_int(PyObject* self, PyObject* other, int negate) {
+ UPolynomialObject* p1 = (UPolynomialObject*) self;
+ lp_integer_t c;
+ const lp_int_ring_t* K = lp_upolynomial_ring(p1->p);
+ PyLong_or_Int_to_integer(other, K, &c);
+ lp_upolynomial_t* c_p = lp_upolynomial_construct(K, 0, &c);
+ lp_upolynomial_t* sub =
+ negate ? lp_upolynomial_sub(c_p, p1->p) : lp_upolynomial_sub(p1->p, c_p);
+ lp_upolynomial_delete(c_p);
+ lp_integer_destruct(&c);
+ return PyUPolynomial_create(sub);
+}
+
+static PyObject*
+UPolynomialObject_sub(PyObject* self, PyObject* other) {
+ // Integer addition
+ if (PyLong_or_Int_Check(other)) {
+ return UPolynomialObject_sub_int(self, other, 0);
+ }
+ if (PyLong_or_Int_Check(self)) {
+ return UPolynomialObject_sub_int(other, self, 1);
+ }
+ // Check arguments
+ if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ // Get arguments
+ UPolynomialObject* p1 = (UPolynomialObject*) self;
+ UPolynomialObject* p2 = (UPolynomialObject*) other;
+ // Add the polynomials
+ lp_upolynomial_t* sum = lp_upolynomial_sub(p1->p, p2->p);
+ // Return the result
+ return PyUPolynomial_create(sum);
+}
+
+// Multiply other integer
+static PyObject*
+UPolynomialObject_mul_int(PyObject* self, PyObject* other) {
+ UPolynomialObject* p1 = (UPolynomialObject*) self;
+ lp_integer_t c;
+ PyLong_or_Int_to_integer(other, lp_upolynomial_ring(p1->p), &c);
+ lp_upolynomial_t* sum = lp_upolynomial_mul_c(p1->p, &c);
+ lp_integer_destruct(&c);
+ return PyUPolynomial_create(sum);
+}
+
+static PyObject*
+UPolynomialObject_mul(PyObject* self, PyObject* other) {
+ // Integer multiplication
+ if (PyLong_or_Int_Check(other)) {
+ return UPolynomialObject_mul_int(self, other);
+ }
+ if (PyLong_or_Int_Check(self)) {
+ return UPolynomialObject_mul_int(other, self);
+ }
+ // Check arguments
+ if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ // Get arguments
+ UPolynomialObject* p1 = (UPolynomialObject*) self;
+ UPolynomialObject* p2 = (UPolynomialObject*) other;
+ // Add the polynomials
+ lp_upolynomial_t* sum = lp_upolynomial_mul(p1->p, p2->p);
+ // Return the result
+ return PyUPolynomial_create(sum);
+}
+
+static PyObject*
+UPolynomialObject_div(PyObject* self, PyObject* args) {
+ // Check arguments
+ if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(args)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ // Get arguments
+ UPolynomialObject* p1 = (UPolynomialObject*) self;
+ UPolynomialObject* p2 = (UPolynomialObject*) args;
+ // Divide the polynomials
+ lp_upolynomial_t* div = lp_upolynomial_div_exact(p1->p, p2->p);
+ // Return the result
+ return PyUPolynomial_create(div);
+}
+
+static PyObject*
+UPolynomialObject_rem(PyObject* self, PyObject* args) {
+ // Check arguments
+ if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(args)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ // Get arguments
+ UPolynomialObject* p1 = (UPolynomialObject*) self;
+ UPolynomialObject* p2 = (UPolynomialObject*) args;
+ // Divide the polynomials
+ lp_upolynomial_t* rem = lp_upolynomial_rem_exact(p1->p, p2->p);
+ // Return the result
+ return PyUPolynomial_create(rem);
+}
+
+static PyObject*
+UPolynomialObject_divmod(PyObject* self, PyObject* args) {
+ // Check arguments
+ if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(args)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ // Get arguments
+ UPolynomialObject* p1 = (UPolynomialObject*) self;
+ UPolynomialObject* p2 = (UPolynomialObject*) args;
+ // To store div, rem
+ lp_upolynomial_t* div = NULL;
+ lp_upolynomial_t* rem = NULL;
+ // Divide the polynomials
+ lp_upolynomial_div_rem_exact(p1->p, p2->p, &div, &rem);
+ // Return the result
+ PyObject* pair = PyTuple_New(2);
+ PyObject* divObj = PyUPolynomial_create(div);
+ PyObject* remObj = PyUPolynomial_create(rem);
+ Py_INCREF(divObj);
+ Py_INCREF(remObj);
+ PyTuple_SetItem(pair, 0, divObj);
+ PyTuple_SetItem(pair, 1, remObj);
+ return pair;
+}
+
+// object.__neg__(self)
+static PyObject*
+UPolynomialObject_neg(PyObject* self) {
+ // Check arguments
+ if (!PyUPolynomial_CHECK(self)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ // Get arguments
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ // Add the polynomials
+ lp_integer_t c;
+ lp_integer_construct_from_int(lp_upolynomial_ring(p->p), &c, -1);
+ lp_upolynomial_t* neg = lp_upolynomial_mul_c(p->p, &c);
+ lp_integer_destruct(&c);
+ // Return the result
+ return PyUPolynomial_create(neg);
+}
+
+static PyObject*
+UPolynomialObject_pow(PyObject* self, PyObject* other) {
+ // Check arguments
+ if (!PyUPolynomial_CHECK(self) || !PyLong_Check(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ // Get arguments
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ long pow = PyLong_AsLong(other);
+ // Power the polynomial
+ lp_upolynomial_t* p_pow = lp_upolynomial_pow(p->p, pow);
+ // Return the result
+ return PyUPolynomial_create(p_pow);
+}
+
+static int
+UPolynomialObject_nonzero(PyObject* self) {
+ // Get arguments
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ // Return the result
+ return !lp_upolynomial_is_zero(p->p);
+}
+
+static PyObject*
+UPolynomial_gcd(PyObject* self, PyObject* args) {
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
+ PyObject* arg = PyTuple_GetItem(args, 0);
+ if (PyUPolynomial_CHECK(arg)) {
+ lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
+ lp_upolynomial_t* q = ((UPolynomialObject*) arg)->p;
+ lp_upolynomial_t* gcd = lp_upolynomial_gcd(p, q);
+ return PyUPolynomial_create(gcd);
+ } else {
+ Py_RETURN_NONE;
+ }
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject*
+UPolynomial_extended_gcd(PyObject* self, PyObject* args) {
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
+ PyObject* arg = PyTuple_GetItem(args, 0);
+ if (PyUPolynomial_CHECK(arg)) {
+ lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
+ lp_upolynomial_t* q = ((UPolynomialObject*) arg)->p;
+ lp_upolynomial_t* u = NULL;
+ lp_upolynomial_t* v = NULL;
+ lp_upolynomial_t* gcd = lp_upolynomial_extended_gcd(p, q, &u, &v);
+
+ PyObject* t = PyTuple_New(3);
+ PyObject* t0 = PyUPolynomial_create(gcd);
+ PyObject* t1 = PyUPolynomial_create(u);
+ PyObject* t2 = PyUPolynomial_create(v);
+ Py_INCREF(t0);
+ Py_INCREF(t1);
+ Py_INCREF(t2);
+ PyTuple_SetItem(t, 0, t0);
+ PyTuple_SetItem(t, 1, t1);
+ PyTuple_SetItem(t, 2, t2);
+ return t;
+ } else {
+ Py_RETURN_NONE;
+ }
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject* factors_to_PyList(lp_upolynomial_factors_t* factors) {
+ // Construct the result
+ size_t size = lp_upolynomial_factors_size(factors);
+ PyObject* factors_list = PyList_New(size + 1);
+
+ // Copy the constant
+ PyObject* constant = integer_to_PyLong(lp_upolynomial_factors_get_constant(factors));
+ PyList_SetItem(factors_list, 0, constant); // Steals the reference
+
+ // Copy over the factors
+ for (size_t i = 0; i < size; ++ i) {
+ size_t degree;
+ PyObject* p_i = PyUPolynomial_create(lp_upolynomial_factors_get_factor(factors, i, °ree));
+ Py_INCREF(p_i);
+ PyObject* d = PyLong_FromSize_t(degree);
+ PyObject* pair = PyTuple_New(2);
+ PyTuple_SetItem(pair, 0, p_i);
+ PyTuple_SetItem(pair, 1, d);
+ PyList_SetItem(factors_list, i + 1, pair);
+ }
+
+ // Return the list
+ return factors_list;
+}
+
+static PyObject*
+UPolynomial_factor(PyObject* self) {
+ // Get arguments
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ // Factor
+ lp_upolynomial_factors_t* factors = lp_upolynomial_factor(p->p);
+ // Create the list
+ PyObject* factors_list = factors_to_PyList(factors);
+ // Get rid of the factors (not the polynomials)
+ lp_upolynomial_factors_destruct(factors, 0);
+ // Return the list
+ return factors_list;
+}
+
+static PyObject*
+UPolynomial_factor_square_free(PyObject* self) {
+ // Get arguments
+ UPolynomialObject* p = (UPolynomialObject*) self;
+ // Factor
+ lp_upolynomial_factors_t* factors = lp_upolynomial_factor_square_free(p->p);
+ // Create the list
+ PyObject* factors_list = factors_to_PyList(factors);
+ // Get rid of the factors (not the polynomials)
+ lp_upolynomial_factors_destruct(factors, 0);
+ // Return the list
+ return factors_list;
+}
+
+static PyObject*
+UPolynomial_roots_count(PyObject* self, PyObject* args) {
+ // Get arguments
+ UPolynomialObject* p = (UPolynomialObject*) self;
+
+ int roots = 0;
+
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 2) {
+ PyObject* a = PyTuple_GetItem(args, 0);
+ PyObject* b = PyTuple_GetItem(args, 1);
+
+ // Ends of the interval
+ lp_dyadic_rational_t a_rat, b_rat;
+
+ if (PyLong_or_Int_Check(a)) {
+ lp_integer_t a_int;
+ PyLong_or_Int_to_integer(a, lp_Z, &a_int);
+ lp_dyadic_rational_construct_from_integer(&a_rat, &a_int);
+ lp_integer_destruct(&a_int);
+ } else if (PyFloat_Check(a)) {
+ PyFloat_to_dyadic_rational(a, &a_rat);
+ } else {
+ Py_RETURN_NONE;
+ }
+
+ if (PyLong_or_Int_Check(b)) {
+ lp_integer_t b_int;
+ PyLong_or_Int_to_integer(b, lp_Z, &b_int);
+ lp_dyadic_rational_construct_from_integer(&b_rat, &b_int);
+ lp_integer_destruct(&b_int);
+ } else if (PyFloat_Check(b)) {
+ PyFloat_to_dyadic_rational(b, &b_rat);
+ } else {
+ lp_dyadic_rational_destruct(&a_rat);
+ Py_RETURN_NONE;
+ }
+
+ // The interval
+ lp_rational_interval_t ab;
+ lp_rational_interval_construct_from_dyadic(&ab, &a_rat, 1, &b_rat, 1);
+
+ // Count
+ roots = lp_upolynomial_roots_count(p->p, &ab);
+
+ // Remove the temporaries
+ lp_rational_interval_destruct(&ab);
+ lp_dyadic_rational_destruct(&a_rat);
+ lp_dyadic_rational_destruct(&b_rat);
+
+ } else if (PyTuple_Size(args) == 0) {
+ // count in (-inf, inf)
+ roots = lp_upolynomial_roots_count(p->p, NULL);
+ } else {
+ Py_RETURN_NONE;
+ }
+
+ return PyLong_FromLong(roots);
+}
+
+static PyObject*
+UPolynomial_roots_isolate(PyObject* self) {
+
+ // Get the polynomial
+ lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
+
+ // The isolating intervals
+ size_t roots_size = lp_upolynomial_degree(p)+1;
+ lp_algebraic_number_t* roots = malloc(sizeof(lp_algebraic_number_t)*roots_size);
+
+ // Isolate the intervals (up to 2^precision)
+ lp_upolynomial_roots_isolate(p, roots, &roots_size);
+
+ // Generate a list of floats
+ PyObject* list = PyList_New(roots_size);
+
+ for (size_t i = 0; i < roots_size; ++ i) {
+ PyObject* c = PyAlgebraicNumber_create(&roots[i]);
+ PyList_SetItem(list, i, c);
+ }
+
+ // Get rid of the temporaries
+ for (size_t i = 0; i < roots_size; ++ i) {
+ lp_algebraic_number_destruct(roots + i);
+ }
+ free(roots);
+
+ // This is the list
+ return list;
+}
+
+static PyObject*
+UPolynomial_derivative(PyObject* self) {
+ lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
+ lp_upolynomial_t* p_derivative = lp_upolynomial_derivative(p);
+ return PyUPolynomial_create(p_derivative);
+}
+
+static PyObject* upolynomials_to_PyList(lp_upolynomial_t** list, size_t size) {
+ // Construct the result
+ PyObject* pylist = PyList_New(size);
+
+ // Copy over the polynomials
+ for (size_t i = 0; i < size; ++ i) {
+ PyObject* pylist_i = PyUPolynomial_create(list[i]);
+ Py_INCREF(pylist_i);
+ PyList_SetItem(pylist, i, pylist_i);
+ }
+
+ // Return the list
+ return pylist;
+}
+
+
+static PyObject*
+UPolynomial_sturm_sequence(PyObject* self) {
+ lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
+ lp_upolynomial_t** S;
+ size_t S_size;
+ lp_upolynomial_sturm_sequence(p, &S, &S_size);
+ PyObject* result = upolynomials_to_PyList(S, S_size);
+ free(S);
+ return result;
+}
+
+static PyObject* integer_list_to_PyList(const lp_integer_t *list, size_t size) {
+ // Construct the result
+ PyObject* pylist = PyList_New(size);
+
+ // Copy over the integers
+ for (size_t i = 0; i < size; ++ i) {
+ PyObject* pylist_i = integer_to_PyLong(&list[i]);
+ Py_INCREF(pylist_i);
+ PyList_SetItem(pylist, i, pylist_i);
+ }
+
+ // Return the list
+ return pylist;
+}
+
+static PyObject*
+UPolynomial_roots_find_Zp(PyObject* self) {
+ lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
+ lp_integer_t* roots;
+ size_t roots_size;
+ lp_upolynomial_roots_find_Zp(p, &roots, &roots_size);
+ PyObject* result = integer_list_to_PyList(roots, roots_size);
+ for (size_t i = 0; i < roots_size; ++i) {
+ lp_integer_destruct(&roots[i]);
+ }
+ free(roots);
+ return result;
+}
+
+static PyObject*
+UPolynomial_evaluate(PyObject* self, PyObject* args) {
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
+ PyObject* x = PyTuple_GetItem(args, 0);
+ // Ends of the interval
+ lp_dyadic_rational_t x_rat;
+ if (PyLong_or_Int_Check(x)) {
+ lp_integer_t x_int;
+ PyLong_or_Int_to_integer(x, lp_Z, &x_int);
+ lp_dyadic_rational_construct_from_integer(&x_rat, &x_int);
+ lp_integer_destruct(&x_int);
+ } else if (PyFloat_Check(x)) {
+ PyFloat_to_dyadic_rational(x, &x_rat);
+ } else {
+ Py_RETURN_NONE;
+ }
+
+ lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
+ lp_dyadic_rational_t value;
+ lp_dyadic_rational_construct(&value);
+ lp_upolynomial_evaluate_at_dyadic_rational(p, &x_rat, &value);
+ PyObject* result = dyadic_rational_to_PyFloat(&value);
+ lp_dyadic_rational_destruct(&x_rat);
+ lp_dyadic_rational_destruct(&value);
+ return result;
+ } else {
+ Py_RETURN_NONE;
+ }
+
+}
diff --git a/python/polypyUPolynomial.h b/python/polypyUPolynomial.h
index 371750fd..ec15800b 100644
--- a/python/polypyUPolynomial.h
+++ b/python/polypyUPolynomial.h
@@ -19,8 +19,7 @@
#pragma once
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include "utils.h"
#include "upolynomial.h"
diff --git a/python/polypyUPolynomial2.c b/python/polypyUPolynomial2.c
deleted file mode 100644
index 14a6d6a1..00000000
--- a/python/polypyUPolynomial2.c
+++ /dev/null
@@ -1,909 +0,0 @@
-/**
- * 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 "polypyUPolynomial.h"
-#include "polypyInteger.h"
-#include "polypyAlgebraicNumber.h"
-
-#include "utils.h"
-
-#include "rational_interval.h"
-
-#include
-
-static void
-UPolynomial_dealloc(UPolynomialObject* self);
-
-static PyObject*
-UPolynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-UPolynomial_init(UPolynomialObject* self, PyObject* args);
-
-static int
-UPolynomial_cmp(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_richcompare(PyObject* self, PyObject* args, int op);
-
-static PyObject*
-UPolynomial_degree(PyObject* self);
-
-static PyObject*
-UPolynomial_coefficients(PyObject* self);
-
-static PyObject*
-UPolynomial_ring(PyObject* self);
-
-static PyObject*
-UPolynomial_gcd(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_derivative(PyObject* self);
-
-static PyObject*
-UPolynomial_extended_gcd(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_factor(PyObject* self);
-
-static PyObject*
-UPolynomial_factor_square_free(PyObject* self);
-
-static PyObject*
-UPolynomial_roots_count(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_roots_isolate(PyObject* self);
-
-static PyObject*
-UPolynomial_sturm_sequence(PyObject* self);
-
-static PyObject*
-UPolynomial_evaluate(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_to_ring(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_str(PyObject* self);
-
-static int
-UPolynomialObject_nonzero(PyObject* self);
-
-static PyObject*
-UPolynomialObject_add(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_div(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_rem(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_divmod(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_pow(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_neg(PyObject* self);
-
-PyMethodDef UPolynomial_methods[] = {
- {"degree", (PyCFunction)UPolynomial_degree, METH_NOARGS, "Returns the degree of the polynomial"},
- {"coefficients", (PyCFunction)UPolynomial_coefficients, METH_NOARGS, "Returns a dictionary from degrees to coefficients"},
- {"ring", (PyCFunction)UPolynomial_ring, METH_NOARGS, "Returns the ring of the polynomial"},
- {"to_ring", (PyCFunction)UPolynomial_to_ring, METH_VARARGS, "Returns the polynomial in the given ring"},
- {"gcd", (PyCFunction)UPolynomial_gcd, METH_VARARGS, "Returns the gcd of current and given polynomial in the given ring"},
- {"extended_gcd", (PyCFunction)UPolynomial_extended_gcd, METH_VARARGS, "Returns the extended gcd, i.e. (gcd, u, v), of current and given polynomial in the given ring"},
- {"factor", (PyCFunction)UPolynomial_factor, METH_NOARGS, "Returns the factorization of the polynomial"},
- {"factor_square_free", (PyCFunction)UPolynomial_factor_square_free, METH_NOARGS, "Returns the square-free factorization of the polynomial"},
- {"roots_count", (PyCFunction)UPolynomial_roots_count, METH_VARARGS, "Returns the number of real roots in the given interval"},
- {"roots_isolate", (PyCFunction)UPolynomial_roots_isolate, METH_NOARGS, "Returns the list of real roots"},
- {"sturm_sequence", (PyCFunction)UPolynomial_sturm_sequence, METH_NOARGS, "Returns the Sturm sequence"},
- {"derivative", (PyCFunction)UPolynomial_derivative, METH_NOARGS, "Returns the derivative of the polynomial"},
- {"evaluate", (PyCFunction)UPolynomial_evaluate, METH_VARARGS, "Returns the value of the polynomial at the given point"},
- {NULL} /* Sentinel */
-};
-
-PyNumberMethods UPolynomial_NumberMethods = {
- UPolynomialObject_add, // binaryfunc nb_add;
- UPolynomialObject_sub, // binaryfunc nb_subtract;
- UPolynomialObject_mul, // binaryfunc nb_multiply;
- UPolynomialObject_div, // binaryfunc nb_divide;
- UPolynomialObject_rem, // binaryfunc nb_remainder;
- UPolynomialObject_divmod, // binaryfunc nb_divmod;
- (ternaryfunc)UPolynomialObject_pow, // ternaryfunc nb_power;
- UPolynomialObject_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- UPolynomialObject_nonzero, // inquiry nb_nonzero; /* Used by PyObject_IsTrue */
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- 0, // coercion nb_coerce; /* Used by the coerce() function */
- 0, // unaryfunc nb_int;
- 0, // unaryfunc nb_long;
- 0, // unaryfunc nb_float;
- 0, // unaryfunc nb_oct;
- 0, // unaryfunc nb_hex;
-
- /* Added in release 2.0 */
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_divide;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
-
- /* Added in release 2.2 */
- 0, // binaryfunc nb_floor_divide;
- 0, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
-
- /* Added in release 2.5 */
- 0 // unaryfunc nb_index;
-};
-
-PyTypeObject UPolynomialType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.UPolynomial", /*tp_name*/
- sizeof(UPolynomialObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)UPolynomial_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- UPolynomial_cmp, /*tp_compare*/
- UPolynomial_str, /*tp_repr*/
- &UPolynomial_NumberMethods, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- UPolynomial_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "Univariate polynomial objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- UPolynomial_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- UPolynomial_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)UPolynomial_init,/* tp_init */
- 0, /* tp_alloc */
- UPolynomial_new, /* tp_new */
-};
-
-static void
-UPolynomial_dealloc(UPolynomialObject* self)
-{
- if (self->p) lp_upolynomial_delete(self->p);
- self->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyUPolynomial_create(lp_upolynomial_t* p) {
- UPolynomialObject *self;
- self = (UPolynomialObject*)UPolynomialType.tp_alloc(&UPolynomialType, 0);
- if (self != NULL) {
- self->p = p;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-UPolynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyUPolynomial_create(0);
-}
-
-static int
-UPolynomial_init(UPolynomialObject* self, PyObject* args)
-{
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) == 0) {
- // Just a zero polynomial
- int coeff[] = { 0 };
- self->p = lp_upolynomial_construct_from_int(lp_Z, 0, coeff);
- } else if (PyTuple_Size(args) <= 2) {
- const lp_int_ring_t* K = lp_Z;
-
- // Get the list of coefficients
- PyObject* coefficients = PyTuple_GetItem(args, 0);
-
- // The first item might be the ring
- if (PyCoefficientRing_CHECK(coefficients)) {
- K = ((CoefficientRing*) coefficients)->K;
- coefficients = PyTuple_GetItem(args, 1);
- } else {
- if (PyTuple_Size(args) == 2) {
- return -1;
- }
- }
-
- if (PyList_Check(coefficients)) {
- Py_ssize_t size = PyList_Size(coefficients);
- if (size > 0) {
- long c_ints[size];
- Py_ssize_t i;
- for (i = 0; i < size; ++ i) {
- PyObject* c_i = PyList_GetItem(coefficients, i);
- if (!PyInt_Check(c_i)) {
- return -1;
- } else {
- c_ints[i] = PyInt_AsLong(c_i);
- }
- }
- self->p = lp_upolynomial_construct_from_long(K, size-1, c_ints);
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-
- return 0;
-}
-
-static PyObject*
-UPolynomial_richcompare(PyObject* self, PyObject* other, int op) {
- PyObject *result = 0;
-
- if (!PyUPolynomial_CHECK(other) && !PyInt_Check(other)) {
- result = Py_NotImplemented;
- } else {
- lp_upolynomial_t* self_p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t* other_p = 0;
- if (PyUPolynomial_CHECK(other)) {
- other_p = ((UPolynomialObject*) other)->p;
- } else {
- long c = PyInt_AsLong(other);
- const lp_int_ring_t* K = lp_upolynomial_ring(self_p);
- other_p = lp_upolynomial_construct_from_long(K, 0, &c);
- }
-
- int cmp = lp_upolynomial_cmp(self_p, other_p);
-
- switch (op) {
- case Py_LT:
- result = cmp < 0 ? Py_True : Py_False;
- break;
- case Py_LE:
- result = cmp <= 0 ? Py_True : Py_False;
- break;
- case Py_EQ:
- result = cmp == 0 ? Py_True : Py_False;
- break;
- case Py_NE:
- result = cmp != 0 ? Py_True : Py_False;
- break;
- case Py_GT:
- result = cmp > 0 ? Py_True : Py_False;
- break;
- case Py_GE:
- result = cmp >= 0 ? Py_True : Py_False;
- break;
- }
-
- if (PyInt_Check(other)) {
- lp_upolynomial_delete(other_p);
- }
- }
-
- Py_INCREF(result);
- return result;
-}
-
-static int
-UPolynomial_cmp(PyObject* self, PyObject* other) {
-
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
- // should return -1 and set an exception condition when an error occurred
- return -1;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) other;
- // Compare
- int cmp = lp_upolynomial_cmp(p1->p, p2->p);
- return cmp > 0 ? 1 : cmp < 0 ? -1 : 0;
-}
-
-static PyObject*
-UPolynomial_degree(PyObject* self) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- return PyInt_FromLong(lp_upolynomial_degree(p->p));
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject*
-UPolynomial_coefficients(PyObject* self) {
- int i;
-
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- size_t size = lp_upolynomial_degree(p) + 1;
-
- lp_integer_t coefficients[size];
- for (i = 0; i < size; ++ i) {
- lp_integer_construct_from_int(lp_Z, coefficients + i, 0);
- }
-
- lp_upolynomial_unpack(p, coefficients);
-
- PyObject* list = PyList_New(size);
-
- for (i = 0; i < size; ++ i) {
- PyObject* c = integer_to_PyInt(coefficients + i);
- PyList_SetItem(list, i, c);
- lp_integer_destruct(coefficients + i);
- }
-
- return list;
-}
-
-static PyObject*
-UPolynomial_ring(PyObject* self) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- lp_int_ring_t* K = (lp_int_ring_t*) lp_upolynomial_ring(p->p);
- lp_int_ring_attach(K);
- return PyCoefficientRing_create(K);
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject*
-UPolynomial_to_ring(PyObject* self, PyObject* args) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- // Get the ring argument
- if (PyTuple_Size(args) == 1) {
- // Get the ring
- PyObject* arg = PyTuple_GetItem(args, 0);
- if (PyCoefficientRing_CHECK(arg)) {
- CoefficientRing* K = (CoefficientRing*)arg;
- lp_upolynomial_t* p_K = lp_upolynomial_construct_copy_K(K->K, p->p);
- return PyUPolynomial_create(p_K);
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject* UPolynomial_str(PyObject* self) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- char* p_str = lp_upolynomial_to_string(p->p);
- PyObject* str = PyString_FromString(p_str);
- free(p_str);
- return str;
- } else {
- Py_RETURN_NONE;
- }
-}
-
-// Add other integer
-static PyObject*
-UPolynomialObject_add_number(PyObject* self, PyObject* other) {
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- lp_integer_t c;
- const lp_int_ring_t* K = lp_upolynomial_ring(p1->p);
- PyLong_or_Int_to_integer(other, K, &c);
- lp_upolynomial_t* c_p = lp_upolynomial_construct(K, 0, &c);
- lp_upolynomial_t* sum = lp_upolynomial_add(p1->p, c_p);
- lp_upolynomial_delete(c_p);
- lp_integer_destruct(&c);
- return PyUPolynomial_create(sum);
-}
-
-static PyObject*
-UPolynomialObject_add(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return UPolynomialObject_add_number(self, other);
- }
- if (PyLong_or_Int_Check(self)) {
- return UPolynomialObject_add_number(other, self);
- }
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) other;
- // Add the polynomials
- lp_upolynomial_t* sum = lp_upolynomial_add(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(sum);
-}
-
-static PyObject*
-UPolynomialObject_sub_int(PyObject* self, PyObject* other, int negate) {
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- lp_integer_t c;
- const lp_int_ring_t* K = lp_upolynomial_ring(p1->p);
- PyLong_or_Int_to_integer(other, K, &c);
- lp_upolynomial_t* c_p = lp_upolynomial_construct(K, 0, &c);
- lp_upolynomial_t* sub =
- negate ? lp_upolynomial_sub(c_p, p1->p) : lp_upolynomial_sub(p1->p, c_p);
- lp_upolynomial_delete(c_p);
- lp_integer_destruct(&c);
- return PyUPolynomial_create(sub);
-}
-
-static PyObject*
-UPolynomialObject_sub(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return UPolynomialObject_sub_int(self, other, 0);
- }
- if (PyLong_or_Int_Check(self)) {
- return UPolynomialObject_sub_int(other, self, 1);
- }
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) other;
- // Add the polynomials
- lp_upolynomial_t* sum = lp_upolynomial_sub(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(sum);
-}
-
-// Multiply other integer
-static PyObject*
-UPolynomialObject_mul_int(PyObject* self, PyObject* other) {
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- lp_integer_t c;
- PyLong_or_Int_to_integer(other, lp_upolynomial_ring(p1->p), &c);
- lp_upolynomial_t* sum = lp_upolynomial_mul_c(p1->p, &c);
- lp_integer_destruct(&c);
- return PyUPolynomial_create(sum);
-}
-
-static PyObject*
-UPolynomialObject_mul(PyObject* self, PyObject* other) {
- // Integer multiplication
- if (PyLong_or_Int_Check(other)) {
- return UPolynomialObject_mul_int(self, other);
- }
- if (PyLong_or_Int_Check(self)) {
- return UPolynomialObject_mul_int(other, self);
- }
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) other;
- // Add the polynomials
- lp_upolynomial_t* sum = lp_upolynomial_mul(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(sum);
-}
-
-static PyObject*
-UPolynomialObject_div(PyObject* self, PyObject* args) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(args)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) args;
- // Divide the polynomials
- lp_upolynomial_t* div = lp_upolynomial_div_exact(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(div);
-}
-
-static PyObject*
-UPolynomialObject_rem(PyObject* self, PyObject* args) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(args)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) args;
- // Divide the polynomials
- lp_upolynomial_t* rem = lp_upolynomial_rem_exact(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(rem);
-}
-
-static PyObject*
-UPolynomialObject_divmod(PyObject* self, PyObject* args) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(args)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) args;
- // To store div, rem
- lp_upolynomial_t* div = 0;
- lp_upolynomial_t* rem = 0;
- // Divide the polynomials
- lp_upolynomial_div_rem_exact(p1->p, p2->p, &div, &rem);
- // Return the result
- PyObject* pair = PyTuple_New(2);
- PyObject* divObj = PyUPolynomial_create(div);
- PyObject* remObj = PyUPolynomial_create(rem);
- Py_INCREF(divObj);
- Py_INCREF(remObj);
- PyTuple_SetItem(pair, 0, divObj);
- PyTuple_SetItem(pair, 1, remObj);
- return pair;
-}
-
-// object.__neg__(self)
-static PyObject*
-UPolynomialObject_neg(PyObject* self) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- // Add the polynomials
- lp_integer_t c;
- lp_integer_construct_from_int(lp_upolynomial_ring(p->p), &c, -1);
- lp_upolynomial_t* neg = lp_upolynomial_mul_c(p->p, &c);
- lp_integer_destruct(&c);
- // Return the result
- return PyUPolynomial_create(neg);
-}
-
-static PyObject*
-UPolynomialObject_pow(PyObject* self, PyObject* other) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyInt_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- long pow = PyInt_AsLong(other);
- // Power the polynomial
- lp_upolynomial_t* p_pow = lp_upolynomial_pow(p->p, pow);
- // Return the result
- return PyUPolynomial_create(p_pow);
-}
-
-static int
-UPolynomialObject_nonzero(PyObject* self) {
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- // Return the result
- return !lp_upolynomial_is_zero(p->p);
-}
-
-static PyObject*
-UPolynomial_gcd(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* arg = PyTuple_GetItem(args, 0);
- if (PyUPolynomial_CHECK(arg)) {
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t* q = ((UPolynomialObject*) arg)->p;
- lp_upolynomial_t* gcd = lp_upolynomial_gcd(p, q);
- return PyUPolynomial_create(gcd);
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject*
-UPolynomial_extended_gcd(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* arg = PyTuple_GetItem(args, 0);
- if (PyUPolynomial_CHECK(arg)) {
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t* q = ((UPolynomialObject*) arg)->p;
- lp_upolynomial_t* u = 0;
- lp_upolynomial_t* v = 0;
- lp_upolynomial_t* gcd = lp_upolynomial_extended_gcd(p, q, &u, &v);
-
- PyObject* t = PyTuple_New(3);
- PyObject* t0 = PyUPolynomial_create(gcd);
- PyObject* t1 = PyUPolynomial_create(u);
- PyObject* t2 = PyUPolynomial_create(v);
- Py_INCREF(t0);
- Py_INCREF(t1);
- Py_INCREF(t2);
- PyTuple_SetItem(t, 0, t0);
- PyTuple_SetItem(t, 1, t1);
- PyTuple_SetItem(t, 2, t2);
- return t;
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject* factors_to_PyList(lp_upolynomial_factors_t* factors) {
- // Construct the result
- size_t size = lp_upolynomial_factors_size(factors);
- PyObject* factors_list = PyList_New(size + 1);
-
- // Copy the constant
- PyObject* constant = integer_to_PyInt(lp_upolynomial_factors_get_constant(factors));
- PyList_SetItem(factors_list, 0, constant); // Steals the reference
-
- // Copy over the factors
- int i;
- for (i = 0; i < size; ++ i) {
- size_t degree;
- PyObject* p_i = PyUPolynomial_create(lp_upolynomial_factors_get_factor(factors, i, °ree));
- Py_INCREF(p_i);
- PyObject* d = PyInt_FromSize_t(degree);
- PyObject* pair = PyTuple_New(2);
- PyTuple_SetItem(pair, 0, p_i);
- PyTuple_SetItem(pair, 1, d);
- PyList_SetItem(factors_list, i + 1, pair);
- }
-
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-UPolynomial_factor(PyObject* self) {
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- // Factor
- lp_upolynomial_factors_t* factors = lp_upolynomial_factor(p->p);
- // Create the list
- PyObject* factors_list = factors_to_PyList(factors);
- // Get rid of the factors (not the polynomials)
- lp_upolynomial_factors_destruct(factors, 0);
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-UPolynomial_factor_square_free(PyObject* self) {
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- // Factor
- lp_upolynomial_factors_t* factors = lp_upolynomial_factor_square_free(p->p);
- // Create the list
- PyObject* factors_list = factors_to_PyList(factors);
- // Get rid of the factors (not the polynomials)
- lp_upolynomial_factors_destruct(factors, 0);
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-UPolynomial_roots_count(PyObject* self, PyObject* args) {
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
-
- int roots = 0;
-
- if (PyTuple_Check(args) && PyTuple_Size(args) == 2) {
- PyObject* a = PyTuple_GetItem(args, 0);
- PyObject* b = PyTuple_GetItem(args, 1);
-
- // Ends of the interval
- lp_dyadic_rational_t a_rat, b_rat;
-
- if (PyLong_or_Int_Check(a)) {
- lp_integer_t a_int;
- PyLong_or_Int_to_integer(a, lp_Z, &a_int);
- lp_dyadic_rational_construct_from_integer(&a_rat, &a_int);
- lp_integer_destruct(&a_int);
- } else if (PyFloat_Check(a)) {
- PyFloat_to_dyadic_rational(a, &a_rat);
- } else {
- Py_RETURN_NONE;
- }
-
- if (PyLong_or_Int_Check(b)) {
- lp_integer_t b_int;
- PyLong_or_Int_to_integer(b, lp_Z, &b_int);
- lp_dyadic_rational_construct_from_integer(&b_rat, &b_int);
- lp_integer_destruct(&b_int);
- } else if (PyFloat_Check(b)) {
- PyFloat_to_dyadic_rational(b, &b_rat);
- } else {
- lp_dyadic_rational_destruct(&a_rat);
- Py_RETURN_NONE;
- }
-
- // The interval
- lp_rational_interval_t ab;
- lp_rational_interval_construct_from_dyadic(&ab, &a_rat, 1, &b_rat, 1);
-
- // Count
- roots = lp_upolynomial_roots_count(p->p, &ab);
-
- // Remove the temporaries
- lp_rational_interval_destruct(&ab);
- lp_dyadic_rational_destruct(&a_rat);
- lp_dyadic_rational_destruct(&b_rat);
-
- } else if (PyTuple_Size(args) == 0) {
- // count in (-inf, inf)
- roots = lp_upolynomial_roots_count(p->p, 0);
- } else {
- Py_RETURN_NONE;
- }
-
- return PyInt_FromLong(roots);
-}
-
-static PyObject*
-UPolynomial_roots_isolate(PyObject* self) {
-
- // Get the polynomial
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
-
- // The isolating intervals
- size_t roots_size = lp_upolynomial_degree(p)+1;
- lp_algebraic_number_t* roots = malloc(sizeof(lp_algebraic_number_t)*roots_size);
-
- // Isolate the intervals (up to 2^precision)
- lp_upolynomial_roots_isolate(p, roots, &roots_size);
-
- // Generate a list of floats
- PyObject* list = PyList_New(roots_size);
-
- int i;
- for (i = 0; i < roots_size; ++ i) {
- PyObject* c = PyAlgebraicNumber_create(&roots[i]);
- PyList_SetItem(list, i, c);
- }
-
- // Get rid of the temporaries
- for (i = 0; i < roots_size; ++ i) {
- lp_algebraic_number_destruct(roots + i);
- }
- free(roots);
-
- // This is the list
- return list;
-}
-
-static PyObject*
-UPolynomial_derivative(PyObject* self) {
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t* p_derivative = lp_upolynomial_derivative(p);
- return PyUPolynomial_create(p_derivative);
-}
-
-static PyObject* upolynomials_to_PyList(lp_upolynomial_t** list, size_t size) {
- // Construct the result
- PyObject* pylist = PyList_New(size);
-
- // Copy over the polynomials
- size_t i;
- for (i = 0; i < size; ++ i) {
- PyObject* pylist_i = PyUPolynomial_create(list[i]);
- Py_INCREF(pylist_i);
- PyList_SetItem(pylist, i, pylist_i);
- }
-
- // Return the list
- return pylist;
-}
-
-
-static PyObject*
-UPolynomial_sturm_sequence(PyObject* self) {
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t** S;
- size_t S_size;
- lp_upolynomial_sturm_sequence(p, &S, &S_size);
- PyObject* result = upolynomials_to_PyList(S, S_size);
- free(S);
- return result;
-}
-
-static PyObject*
-UPolynomial_evaluate(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* x = PyTuple_GetItem(args, 0);
- // Ends of the interval
- lp_dyadic_rational_t x_rat;
- if (PyLong_or_Int_Check(x)) {
- lp_integer_t x_int;
- PyLong_or_Int_to_integer(x, lp_Z, &x_int);
- lp_dyadic_rational_construct_from_integer(&x_rat, &x_int);
- lp_integer_destruct(&x_int);
- } else if (PyFloat_Check(x)) {
- PyFloat_to_dyadic_rational(x, &x_rat);
- } else {
- Py_RETURN_NONE;
- }
-
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_dyadic_rational_t value;
- lp_dyadic_rational_construct(&value);
- lp_upolynomial_evaluate_at_dyadic_rational(p, &x_rat, &value);
- PyObject* result = dyadic_rational_to_PyFloat(&value);
- lp_dyadic_rational_destruct(&x_rat);
- lp_dyadic_rational_destruct(&value);
- return result;
- } else {
- Py_RETURN_NONE;
- }
-
-}
diff --git a/python/polypyUPolynomial3.c b/python/polypyUPolynomial3.c
deleted file mode 100644
index e3b65056..00000000
--- a/python/polypyUPolynomial3.c
+++ /dev/null
@@ -1,929 +0,0 @@
-/**
- * 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 "polypyUPolynomial.h"
-#include "polypyInteger.h"
-#include "polypyAlgebraicNumber.h"
-
-#include "utils.h"
-
-#include "rational_interval.h"
-
-#include
-
-static void
-UPolynomial_dealloc(UPolynomialObject* self);
-
-static PyObject*
-UPolynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-UPolynomial_init(UPolynomialObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_richcompare(PyObject* self, PyObject* args, int op);
-
-static PyObject*
-UPolynomial_degree(PyObject* self);
-
-static PyObject*
-UPolynomial_coefficients(PyObject* self);
-
-static PyObject*
-UPolynomial_ring(PyObject* self);
-
-static PyObject*
-UPolynomial_gcd(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_derivative(PyObject* self);
-
-static PyObject*
-UPolynomial_extended_gcd(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_factor(PyObject* self);
-
-static PyObject*
-UPolynomial_factor_square_free(PyObject* self);
-
-static PyObject*
-UPolynomial_roots_count(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_roots_isolate(PyObject* self);
-
-static PyObject*
-UPolynomial_sturm_sequence(PyObject* self);
-
-static PyObject*
-UPolynomial_roots_find_Zp(PyObject* self);
-
-static PyObject*
-UPolynomial_evaluate(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_to_ring(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomial_str(PyObject* self);
-
-static int
-UPolynomialObject_nonzero(PyObject* self);
-
-static PyObject*
-UPolynomialObject_add(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_div(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_rem(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_divmod(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_pow(PyObject* self, PyObject* args);
-
-static PyObject*
-UPolynomialObject_neg(PyObject* self);
-
-PyMethodDef UPolynomial_methods[] = {
- {"degree", (PyCFunction)UPolynomial_degree, METH_NOARGS, "Returns the degree of the polynomial"},
- {"coefficients", (PyCFunction)UPolynomial_coefficients, METH_NOARGS, "Returns a dictionary from degrees to coefficients"},
- {"ring", (PyCFunction)UPolynomial_ring, METH_NOARGS, "Returns the ring of the polynomial"},
- {"to_ring", (PyCFunction)UPolynomial_to_ring, METH_VARARGS, "Returns the polynomial in the given ring"},
- {"gcd", (PyCFunction)UPolynomial_gcd, METH_VARARGS, "Returns the gcd of current and given polynomial in the given ring"},
- {"extended_gcd", (PyCFunction)UPolynomial_extended_gcd, METH_VARARGS, "Returns the extended gcd, i.e. (gcd, u, v), of current and given polynomial in the given ring"},
- {"factor", (PyCFunction)UPolynomial_factor, METH_NOARGS, "Returns the factorization of the polynomial"},
- {"factor_square_free", (PyCFunction)UPolynomial_factor_square_free, METH_NOARGS, "Returns the square-free factorization of the polynomial"},
- {"roots_count", (PyCFunction)UPolynomial_roots_count, METH_VARARGS, "Returns the number of real roots in the given interval"},
- {"roots_isolate", (PyCFunction)UPolynomial_roots_isolate, METH_NOARGS, "Returns the list of real roots"},
- {"sturm_sequence", (PyCFunction)UPolynomial_sturm_sequence, METH_NOARGS, "Returns the Sturm sequence"},
- {"roots_find_Zp", (PyCFunction)UPolynomial_roots_find_Zp, METH_NOARGS, "Returns the roots of the polynomial in Zp"},
- {"derivative", (PyCFunction)UPolynomial_derivative, METH_NOARGS, "Returns the derivative of the polynomial"},
- {"evaluate", (PyCFunction)UPolynomial_evaluate, METH_VARARGS, "Returns the value of the polynomial at the given point"},
- {NULL} /* Sentinel */
-};
-
-PyNumberMethods UPolynomial_NumberMethods = {
- UPolynomialObject_add, // binaryfunc nb_add;
- UPolynomialObject_sub, // binaryfunc nb_subtract;
- UPolynomialObject_mul, // binaryfunc nb_multiply;
- UPolynomialObject_rem, // binaryfunc nb_remainder;
- UPolynomialObject_divmod, // binaryfunc nb_divmod;
- (ternaryfunc)UPolynomialObject_pow, // ternaryfunc nb_power;
- UPolynomialObject_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- UPolynomialObject_nonzero, // inquiry nb_bool;
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- 0, // unaryfunc nb_int;
- 0, // void *nb_reserved;
- 0, // unaryfunc nb_float;
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
- 0, // binaryfunc nb_floor_divide;
- UPolynomialObject_div, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
- 0, // unaryfunc nb_index;
- 0, // binaryfunc nb_matrix_multiply;
- 0, // binaryfunc nb_inplace_matrix_multiply;
-};
-
-PyTypeObject UPolynomialType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.UPolynomial", // const char *tp_name;
- sizeof(UPolynomialObject), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)UPolynomial_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async;
- UPolynomial_str, // reprfunc tp_repr;
- &UPolynomial_NumberMethods, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- 0, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- UPolynomial_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "Univariate polynomial objects", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- UPolynomial_richcompare, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- UPolynomial_methods, // struct PyMethodDef *tp_methods;
- 0, // struct PyMemberDef *tp_members;
- 0, // struct PyGetSetDef *tp_getset;
- 0, // struct _typeobject *tp_base;
- 0, // PyObject *tp_dict;
- 0, // descrgetfunc tp_descr_get;
- 0, // descrsetfunc tp_descr_set;
- 0, // Py_ssize_t tp_dictoffset;
- (initproc)UPolynomial_init, // initproc tp_init;
- 0, // allocfunc tp_alloc;
- UPolynomial_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-static void
-UPolynomial_dealloc(UPolynomialObject* self)
-{
- if (self->p) lp_upolynomial_delete(self->p);
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyUPolynomial_create(lp_upolynomial_t* p) {
- UPolynomialObject *self;
- self = (UPolynomialObject*)UPolynomialType.tp_alloc(&UPolynomialType, 0);
- if (self != NULL) {
- self->p = p;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-UPolynomial_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyUPolynomial_create(0);
-}
-
-static int
-UPolynomial_init(UPolynomialObject* self, PyObject* args)
-{
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) == 0) {
- // Just a zero polynomial
- int coeff[] = { 0 };
- self->p = lp_upolynomial_construct_from_int(lp_Z, 0, coeff);
- } else if (PyTuple_Size(args) <= 2) {
- lp_int_ring_t* K = lp_Z;
-
- // Get the list of coefficients
- PyObject* coefficients = PyTuple_GetItem(args, 0);
-
- // The first item might be the ring
- if (PyCoefficientRing_CHECK(coefficients)) {
- K = ((CoefficientRing*) coefficients)->K;
- coefficients = PyTuple_GetItem(args, 1);
- } else {
- if (PyTuple_Size(args) == 2) {
- return -1;
- }
- }
-
- if (PyList_Check(coefficients)) {
- Py_ssize_t size = PyList_Size(coefficients);
- if (size > 0) {
- long c_ints[size];
- Py_ssize_t i;
- for (i = 0; i < size; ++ i) {
- PyObject* c_i = PyList_GetItem(coefficients, i);
- if (!PyLong_Check(c_i)) {
- return -1;
- } else {
- c_ints[i] = PyLong_AsLong(c_i);
- }
- }
- self->p = lp_upolynomial_construct_from_long(K, size-1, c_ints);
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-
- return 0;
-}
-
-static PyObject*
-UPolynomial_richcompare(PyObject* self, PyObject* other, int op) {
- PyObject *result = 0;
-
- if (!PyUPolynomial_CHECK(other) && !PyLong_Check(other)) {
- //IAM: Surely we can be braver here?
- // if op == Py_EQ we could return Py_False
- // if op == Py_NE we could return Py_True
- // I am sure this holds for other versions of:
- // _cmp AND _richcompare in this codebase.
- result = Py_NotImplemented;
- } else {
- lp_upolynomial_t* self_p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t* other_p = 0;
- if (PyUPolynomial_CHECK(other)) {
- other_p = ((UPolynomialObject*) other)->p;
- } else {
- long c = PyLong_AsLong(other);
- const lp_int_ring_t* K = lp_upolynomial_ring(self_p);
- other_p = lp_upolynomial_construct_from_long(K, 0, &c);
- }
-
- int cmp = lp_upolynomial_cmp(self_p, other_p);
-
- switch (op) {
- case Py_LT:
- result = cmp < 0 ? Py_True : Py_False;
- break;
- case Py_LE:
- result = cmp <= 0 ? Py_True : Py_False;
- break;
- case Py_EQ:
- result = cmp == 0 ? Py_True : Py_False;
- break;
- case Py_NE:
- result = cmp != 0 ? Py_True : Py_False;
- break;
- case Py_GT:
- result = cmp > 0 ? Py_True : Py_False;
- break;
- case Py_GE:
- result = cmp >= 0 ? Py_True : Py_False;
- break;
- }
-
- if (PyLong_Check(other)) {
- lp_upolynomial_delete(other_p);
- }
- }
-
- Py_INCREF(result);
- return result;
-}
-
-static PyObject*
-UPolynomial_degree(PyObject* self) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- return PyLong_FromLong(lp_upolynomial_degree(p->p));
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject*
-UPolynomial_coefficients(PyObject* self) {
- size_t i;
-
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- size_t size = lp_upolynomial_degree(p) + 1;
-
- lp_integer_t coefficients[size];
- for (i = 0; i < size; ++ i) {
- lp_integer_construct_from_int(lp_Z, coefficients + i, 0);
- }
-
- lp_upolynomial_unpack(p, coefficients);
-
- PyObject* list = PyList_New(size);
-
- for (i = 0; i < size; ++ i) {
- PyObject* c = integer_to_PyLong(coefficients + i);
- PyList_SetItem(list, i, c);
- lp_integer_destruct(coefficients + i);
- }
-
- return list;
-}
-
-static PyObject*
-UPolynomial_ring(PyObject* self) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- lp_int_ring_t* K = (lp_int_ring_t*) lp_upolynomial_ring(p->p);
- lp_int_ring_attach(K);
- return PyCoefficientRing_create(K);
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject*
-UPolynomial_to_ring(PyObject* self, PyObject* args) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- // Get the ring argument
- if (PyTuple_Size(args) == 1) {
- // Get the ring
- PyObject* arg = PyTuple_GetItem(args, 0);
- if (PyCoefficientRing_CHECK(arg)) {
- CoefficientRing* K = (CoefficientRing*)arg;
- lp_upolynomial_t* p_K = lp_upolynomial_construct_copy_K(K->K, p->p);
- return PyUPolynomial_create(p_K);
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject* UPolynomial_str(PyObject* self) {
- UPolynomialObject* p = (UPolynomialObject*) self;
- if (p) {
- char* p_str = lp_upolynomial_to_string(p->p);
- PyObject* str = PyUnicode_FromString(p_str);
- free(p_str);
- return str;
- } else {
- Py_RETURN_NONE;
- }
-}
-
-// Add other integer
-static PyObject*
-UPolynomialObject_add_number(PyObject* self, PyObject* other) {
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- lp_integer_t c;
- const lp_int_ring_t* K = lp_upolynomial_ring(p1->p);
- PyLong_or_Int_to_integer(other, K, &c);
- lp_upolynomial_t* c_p = lp_upolynomial_construct(K, 0, &c);
- lp_upolynomial_t* sum = lp_upolynomial_add(p1->p, c_p);
- lp_upolynomial_delete(c_p);
- lp_integer_destruct(&c);
- return PyUPolynomial_create(sum);
-}
-
-static PyObject*
-UPolynomialObject_add(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return UPolynomialObject_add_number(self, other);
- }
- if (PyLong_or_Int_Check(self)) {
- return UPolynomialObject_add_number(other, self);
- }
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) other;
- // Add the polynomials
- lp_upolynomial_t* sum = lp_upolynomial_add(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(sum);
-}
-
-static PyObject*
-UPolynomialObject_sub_int(PyObject* self, PyObject* other, int negate) {
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- lp_integer_t c;
- const lp_int_ring_t* K = lp_upolynomial_ring(p1->p);
- PyLong_or_Int_to_integer(other, K, &c);
- lp_upolynomial_t* c_p = lp_upolynomial_construct(K, 0, &c);
- lp_upolynomial_t* sub =
- negate ? lp_upolynomial_sub(c_p, p1->p) : lp_upolynomial_sub(p1->p, c_p);
- lp_upolynomial_delete(c_p);
- lp_integer_destruct(&c);
- return PyUPolynomial_create(sub);
-}
-
-static PyObject*
-UPolynomialObject_sub(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return UPolynomialObject_sub_int(self, other, 0);
- }
- if (PyLong_or_Int_Check(self)) {
- return UPolynomialObject_sub_int(other, self, 1);
- }
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) other;
- // Add the polynomials
- lp_upolynomial_t* sum = lp_upolynomial_sub(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(sum);
-}
-
-// Multiply other integer
-static PyObject*
-UPolynomialObject_mul_int(PyObject* self, PyObject* other) {
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- lp_integer_t c;
- PyLong_or_Int_to_integer(other, lp_upolynomial_ring(p1->p), &c);
- lp_upolynomial_t* sum = lp_upolynomial_mul_c(p1->p, &c);
- lp_integer_destruct(&c);
- return PyUPolynomial_create(sum);
-}
-
-static PyObject*
-UPolynomialObject_mul(PyObject* self, PyObject* other) {
- // Integer multiplication
- if (PyLong_or_Int_Check(other)) {
- return UPolynomialObject_mul_int(self, other);
- }
- if (PyLong_or_Int_Check(self)) {
- return UPolynomialObject_mul_int(other, self);
- }
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) other;
- // Add the polynomials
- lp_upolynomial_t* sum = lp_upolynomial_mul(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(sum);
-}
-
-static PyObject*
-UPolynomialObject_div(PyObject* self, PyObject* args) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(args)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) args;
- // Divide the polynomials
- lp_upolynomial_t* div = lp_upolynomial_div_exact(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(div);
-}
-
-static PyObject*
-UPolynomialObject_rem(PyObject* self, PyObject* args) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(args)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) args;
- // Divide the polynomials
- lp_upolynomial_t* rem = lp_upolynomial_rem_exact(p1->p, p2->p);
- // Return the result
- return PyUPolynomial_create(rem);
-}
-
-static PyObject*
-UPolynomialObject_divmod(PyObject* self, PyObject* args) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyUPolynomial_CHECK(args)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p1 = (UPolynomialObject*) self;
- UPolynomialObject* p2 = (UPolynomialObject*) args;
- // To store div, rem
- lp_upolynomial_t* div = 0;
- lp_upolynomial_t* rem = 0;
- // Divide the polynomials
- lp_upolynomial_div_rem_exact(p1->p, p2->p, &div, &rem);
- // Return the result
- PyObject* pair = PyTuple_New(2);
- PyObject* divObj = PyUPolynomial_create(div);
- PyObject* remObj = PyUPolynomial_create(rem);
- Py_INCREF(divObj);
- Py_INCREF(remObj);
- PyTuple_SetItem(pair, 0, divObj);
- PyTuple_SetItem(pair, 1, remObj);
- return pair;
-}
-
-// object.__neg__(self)
-static PyObject*
-UPolynomialObject_neg(PyObject* self) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- // Add the polynomials
- lp_integer_t c;
- lp_integer_construct_from_int(lp_upolynomial_ring(p->p), &c, -1);
- lp_upolynomial_t* neg = lp_upolynomial_mul_c(p->p, &c);
- lp_integer_destruct(&c);
- // Return the result
- return PyUPolynomial_create(neg);
-}
-
-static PyObject*
-UPolynomialObject_pow(PyObject* self, PyObject* other) {
- // Check arguments
- if (!PyUPolynomial_CHECK(self) || !PyLong_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- long pow = PyLong_AsLong(other);
- // Power the polynomial
- lp_upolynomial_t* p_pow = lp_upolynomial_pow(p->p, pow);
- // Return the result
- return PyUPolynomial_create(p_pow);
-}
-
-static int
-UPolynomialObject_nonzero(PyObject* self) {
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- // Return the result
- return !lp_upolynomial_is_zero(p->p);
-}
-
-static PyObject*
-UPolynomial_gcd(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* arg = PyTuple_GetItem(args, 0);
- if (PyUPolynomial_CHECK(arg)) {
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t* q = ((UPolynomialObject*) arg)->p;
- lp_upolynomial_t* gcd = lp_upolynomial_gcd(p, q);
- return PyUPolynomial_create(gcd);
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject*
-UPolynomial_extended_gcd(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* arg = PyTuple_GetItem(args, 0);
- if (PyUPolynomial_CHECK(arg)) {
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t* q = ((UPolynomialObject*) arg)->p;
- lp_upolynomial_t* u = 0;
- lp_upolynomial_t* v = 0;
- lp_upolynomial_t* gcd = lp_upolynomial_extended_gcd(p, q, &u, &v);
-
- PyObject* t = PyTuple_New(3);
- PyObject* t0 = PyUPolynomial_create(gcd);
- PyObject* t1 = PyUPolynomial_create(u);
- PyObject* t2 = PyUPolynomial_create(v);
- Py_INCREF(t0);
- Py_INCREF(t1);
- Py_INCREF(t2);
- PyTuple_SetItem(t, 0, t0);
- PyTuple_SetItem(t, 1, t1);
- PyTuple_SetItem(t, 2, t2);
- return t;
- } else {
- Py_RETURN_NONE;
- }
- } else {
- Py_RETURN_NONE;
- }
-}
-
-static PyObject* factors_to_PyList(lp_upolynomial_factors_t* factors) {
- // Construct the result
- size_t size = lp_upolynomial_factors_size(factors);
- PyObject* factors_list = PyList_New(size + 1);
-
- // Copy the constant
- PyObject* constant = integer_to_PyLong(lp_upolynomial_factors_get_constant(factors));
- PyList_SetItem(factors_list, 0, constant); // Steals the reference
-
- // Copy over the factors
- size_t i;
- for (i = 0; i < size; ++ i) {
- size_t degree;
- PyObject* p_i = PyUPolynomial_create(lp_upolynomial_factors_get_factor(factors, i, °ree));
- Py_INCREF(p_i);
- PyObject* d = PyLong_FromSize_t(degree);
- PyObject* pair = PyTuple_New(2);
- PyTuple_SetItem(pair, 0, p_i);
- PyTuple_SetItem(pair, 1, d);
- PyList_SetItem(factors_list, i + 1, pair);
- }
-
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-UPolynomial_factor(PyObject* self) {
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- // Factor
- lp_upolynomial_factors_t* factors = lp_upolynomial_factor(p->p);
- // Create the list
- PyObject* factors_list = factors_to_PyList(factors);
- // Get rid of the factors (not the polynomials)
- lp_upolynomial_factors_destruct(factors, 0);
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-UPolynomial_factor_square_free(PyObject* self) {
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
- // Factor
- lp_upolynomial_factors_t* factors = lp_upolynomial_factor_square_free(p->p);
- // Create the list
- PyObject* factors_list = factors_to_PyList(factors);
- // Get rid of the factors (not the polynomials)
- lp_upolynomial_factors_destruct(factors, 0);
- // Return the list
- return factors_list;
-}
-
-static PyObject*
-UPolynomial_roots_count(PyObject* self, PyObject* args) {
- // Get arguments
- UPolynomialObject* p = (UPolynomialObject*) self;
-
- int roots = 0;
-
- if (PyTuple_Check(args) && PyTuple_Size(args) == 2) {
- PyObject* a = PyTuple_GetItem(args, 0);
- PyObject* b = PyTuple_GetItem(args, 1);
-
- // Ends of the interval
- lp_dyadic_rational_t a_rat, b_rat;
-
- if (PyLong_or_Int_Check(a)) {
- lp_integer_t a_int;
- PyLong_or_Int_to_integer(a, lp_Z, &a_int);
- lp_dyadic_rational_construct_from_integer(&a_rat, &a_int);
- lp_integer_destruct(&a_int);
- } else if (PyFloat_Check(a)) {
- PyFloat_to_dyadic_rational(a, &a_rat);
- } else {
- Py_RETURN_NONE;
- }
-
- if (PyLong_or_Int_Check(b)) {
- lp_integer_t b_int;
- PyLong_or_Int_to_integer(b, lp_Z, &b_int);
- lp_dyadic_rational_construct_from_integer(&b_rat, &b_int);
- lp_integer_destruct(&b_int);
- } else if (PyFloat_Check(b)) {
- PyFloat_to_dyadic_rational(b, &b_rat);
- } else {
- lp_dyadic_rational_destruct(&a_rat);
- Py_RETURN_NONE;
- }
-
- // The interval
- lp_rational_interval_t ab;
- lp_rational_interval_construct_from_dyadic(&ab, &a_rat, 1, &b_rat, 1);
-
- // Count
- roots = lp_upolynomial_roots_count(p->p, &ab);
-
- // Remove the temporaries
- lp_rational_interval_destruct(&ab);
- lp_dyadic_rational_destruct(&a_rat);
- lp_dyadic_rational_destruct(&b_rat);
-
- } else if (PyTuple_Size(args) == 0) {
- // count in (-inf, inf)
- roots = lp_upolynomial_roots_count(p->p, 0);
- } else {
- Py_RETURN_NONE;
- }
-
- return PyLong_FromLong(roots);
-}
-
-static PyObject*
-UPolynomial_roots_isolate(PyObject* self) {
-
- // Get the polynomial
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
-
- // The isolating intervals
- size_t roots_size = lp_upolynomial_degree(p)+1;
- lp_algebraic_number_t* roots = malloc(sizeof(lp_algebraic_number_t)*roots_size);
-
- // Isolate the intervals (up to 2^precision)
- lp_upolynomial_roots_isolate(p, roots, &roots_size);
-
- // Generate a list of floats
- PyObject* list = PyList_New(roots_size);
-
- size_t i;
- for (i = 0; i < roots_size; ++ i) {
- PyObject* c = PyAlgebraicNumber_create(&roots[i]);
- PyList_SetItem(list, i, c);
- }
-
- // Get rid of the temporaries
- for (i = 0; i < roots_size; ++ i) {
- lp_algebraic_number_destruct(roots + i);
- }
- free(roots);
-
- // This is the list
- return list;
-}
-
-static PyObject*
-UPolynomial_derivative(PyObject* self) {
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t* p_derivative = lp_upolynomial_derivative(p);
- return PyUPolynomial_create(p_derivative);
-}
-
-static PyObject* upolynomials_to_PyList(lp_upolynomial_t** list, size_t size) {
- // Construct the result
- PyObject* pylist = PyList_New(size);
-
- // Copy over the polynomials
- size_t i;
- for (i = 0; i < size; ++ i) {
- PyObject* pylist_i = PyUPolynomial_create(list[i]);
- Py_INCREF(pylist_i);
- PyList_SetItem(pylist, i, pylist_i);
- }
-
- // Return the list
- return pylist;
-}
-
-
-static PyObject*
-UPolynomial_sturm_sequence(PyObject* self) {
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_upolynomial_t** S;
- size_t S_size;
- lp_upolynomial_sturm_sequence(p, &S, &S_size);
- PyObject* result = upolynomials_to_PyList(S, S_size);
- free(S);
- return result;
-}
-
-static PyObject* integer_list_to_PyList(lp_integer_t *list, size_t size) {
- // Construct the result
- PyObject* pylist = PyList_New(size);
-
- // Copy over the integers
- size_t i;
- for (i = 0; i < size; ++ i) {
- PyObject* pylist_i = integer_to_PyLong(&list[i]);
- Py_INCREF(pylist_i);
- PyList_SetItem(pylist, i, pylist_i);
- }
-
- // Return the list
- return pylist;
-}
-
-static PyObject*
-UPolynomial_roots_find_Zp(PyObject* self) {
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_integer_t* roots;
- size_t roots_size;
- lp_upolynomial_roots_find_Zp(p, &roots, &roots_size);
- PyObject* result = integer_list_to_PyList(roots, roots_size);
- for (size_t i = 0; i < roots_size; ++i) {
- lp_integer_destruct(&roots[i]);
- }
- free(roots);
- return result;
-}
-
-static PyObject*
-UPolynomial_evaluate(PyObject* self, PyObject* args) {
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* x = PyTuple_GetItem(args, 0);
- // Ends of the interval
- lp_dyadic_rational_t x_rat;
- if (PyLong_or_Int_Check(x)) {
- lp_integer_t x_int;
- PyLong_or_Int_to_integer(x, lp_Z, &x_int);
- lp_dyadic_rational_construct_from_integer(&x_rat, &x_int);
- lp_integer_destruct(&x_int);
- } else if (PyFloat_Check(x)) {
- PyFloat_to_dyadic_rational(x, &x_rat);
- } else {
- Py_RETURN_NONE;
- }
-
- lp_upolynomial_t* p = ((UPolynomialObject*) self)->p;
- lp_dyadic_rational_t value;
- lp_dyadic_rational_construct(&value);
- lp_upolynomial_evaluate_at_dyadic_rational(p, &x_rat, &value);
- PyObject* result = dyadic_rational_to_PyFloat(&value);
- lp_dyadic_rational_destruct(&x_rat);
- lp_dyadic_rational_destruct(&value);
- return result;
- } else {
- Py_RETURN_NONE;
- }
-
-}
diff --git a/python/polypyValue.c b/python/polypyValue.c
index e67d7892..d13bba20 100644
--- a/python/polypyValue.c
+++ b/python/polypyValue.c
@@ -17,12 +17,475 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
-#if PY_MAJOR_VERSION >= 3
-#include "polypyValue3.c"
-#else
-#include "polypyValue2.c"
-#endif
+#include "polypyValue.h"
+#include "utils.h"
+#include "polypyAlgebraicNumber.h"
+#include
+#include
+
+static void
+Value_dealloc(Value* self);
+
+static PyObject*
+Value_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static int
+Value_init(Value* self, PyObject* args);
+
+static PyObject*
+Value_to_double(PyObject* self);
+
+static PyObject*
+Value_richcompare(PyObject* self, PyObject* other, int op);
+
+static PyObject*
+Value_str(PyObject* self);
+
+static Py_hash_t
+Value_hash(PyObject* self);
+
+static PyObject*
+Value_get_value_between(PyObject* self, PyObject* args);
+
+static PyObject*
+Value_add(PyObject* self, PyObject* other);
+
+static PyObject*
+Value_neg(PyObject* self);
+
+static PyObject*
+Value_sub(PyObject* self, PyObject* other);
+
+static PyObject*
+Value_mul(PyObject* self, PyObject* other);
+
+static PyObject*
+Value_div(PyObject* self, PyObject* other);
+
+static PyObject*
+Value_pow(PyObject* self, PyObject* other);
+
+static PyObject*
+Value_long(PyObject* self);
+
+static PyObject*
+Value_float(PyObject* self);
+
+PyMethodDef Value_methods[] = {
+ {"to_double", (PyCFunction)Value_to_double, METH_NOARGS, "Returns the approximation of the value"},
+ {"get_value_between", (PyCFunction)Value_get_value_between, METH_VARARGS, "Returns a value between this and given value"},
+ {NULL} /* Sentinel */
+};
+
+PyNumberMethods Value_NumberMethods = {
+ Value_add, // binaryfunc nb_add;
+ Value_sub, // binaryfunc nb_subtract;
+ Value_mul, // binaryfunc nb_multiply;
+ NULL, // binaryfunc nb_remainder;
+ NULL, // binaryfunc nb_divmod;
+ (ternaryfunc)Value_pow, // ternaryfunc nb_power;
+ Value_neg, // unaryfunc nb_negative;
+ NULL, // unaryfunc nb_positive;
+ NULL, // unaryfunc nb_absolute;
+ NULL, // inquiry nb_bool;
+ NULL, // unaryfunc nb_invert;
+ NULL, // binaryfunc nb_lshift;
+ NULL, // binaryfunc nb_rshift;
+ NULL, // binaryfunc nb_and;
+ NULL, // binaryfunc nb_xor;
+ NULL, // binaryfunc nb_or;
+ Value_long, // unaryfunc nb_int;
+ NULL, // void *nb_reserved;
+ Value_float, // unaryfunc nb_float;
+ NULL, // binaryfunc nb_inplace_add;
+ NULL, // binaryfunc nb_inplace_subtract;
+ NULL, // binaryfunc nb_inplace_multiply;
+ NULL, // binaryfunc nb_inplace_remainder;
+ NULL, // ternaryfunc nb_inplace_power;
+ NULL, // binaryfunc nb_inplace_lshift;
+ NULL, // binaryfunc nb_inplace_rshift;
+ NULL, // binaryfunc nb_inplace_and;
+ NULL, // binaryfunc nb_inplace_xor;
+ NULL, // binaryfunc nb_inplace_or;
+ NULL, // binaryfunc nb_floor_divide;
+ Value_div, // binaryfunc nb_true_divide;
+ NULL, // binaryfunc nb_inplace_floor_divide;
+ NULL, // binaryfunc nb_inplace_true_divide;
+ NULL, // unaryfunc nb_index;
+ NULL, // binaryfunc nb_matrix_multiply;
+ NULL, // binaryfunc nb_inplace_matrix_multiply;
+};
+
+PyTypeObject ValueType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.Value", // const char *tp_name;
+ sizeof(Value), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)Value_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async;
+ Value_str, // reprfunc tp_repr;
+ &Value_NumberMethods, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ &Value_hash, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ Value_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "Values of different kinds", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ Value_richcompare, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ Value_methods, // struct PyMethodDef *tp_methods;
+ NULL, // struct PyMemberDef *tp_members;
+ NULL, // struct PyGetSetDef *tp_getset;
+ NULL, // struct _typeobject *tp_base;
+ NULL, // PyObject *tp_dict;
+ NULL, // descrgetfunc tp_descr_get;
+ NULL, // descrsetfunc tp_descr_set;
+ 0, // Py_ssize_t tp_dictoffset;
+ (initproc)Value_init, // initproc tp_init;
+ NULL, // allocfunc tp_alloc;
+ Value_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+static void
+Value_dealloc(Value* self)
+{
+ lp_value_destruct(&self->v);
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+PyObject*
+PyValue_create(const lp_value_t* v) {
+ Value *self = (Value*)ValueType.tp_alloc(&ValueType, 0);
+ if (self != NULL) {
+ if (v) {
+ lp_value_construct_copy(&self->v, v);
+ } else {
+ lp_value_construct_zero(&self->v);
+ }
+ }
+ return (PyObject *)self;
+}
+
+static PyObject*
+Value_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return PyValue_create(NULL);
+}
+
+/** Construct a value from given number. */
+static int
+Value_init(Value* self, PyObject* args)
+{
+ if (PyTuple_Check(args)) {
+ if (PyTuple_Size(args) == 0) {
+ lp_value_construct_zero(&self->v);
+ } else if (PyTuple_Size(args) == 1) {
+ PyObject* v = PyTuple_GetItem(args, 0);
+ if (PyLong_Check(v)) {
+ long v_int = PyLong_AsLong(v);
+ lp_value_construct_int(&self->v, v_int);
+ } else if (PyAlgebraicNumber_CHECK(v)) {
+ AlgebraicNumber* v_alg = (AlgebraicNumber*) v;
+ lp_value_construct(&self->v, LP_VALUE_ALGEBRAIC, &v_alg->a);
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+
+ // All fine, initialized
+ return 0;
+}
+
+static PyObject*
+Value_to_double(PyObject* self) {
+
+ Value* a = (Value*) self;
+
+ double value = 0;
+
+ switch (a->v.type) {
+ case LP_VALUE_NONE:
+ assert(0);
+ break;
+ case LP_VALUE_INTEGER:
+ value = lp_integer_to_int(&a->v.value.z);
+ break;
+ case LP_VALUE_DYADIC_RATIONAL:
+ value = lp_dyadic_rational_to_double(&a->v.value.dy_q);
+ break;
+ case LP_VALUE_RATIONAL:
+ value = lp_rational_to_double(&a->v.value.q);
+ break;
+ case LP_VALUE_ALGEBRAIC:
+ value = lp_algebraic_number_to_double(&a->v.value.a);
+ break;
+ case LP_VALUE_PLUS_INFINITY:
+ value = INFINITY;
+ break;
+ case LP_VALUE_MINUS_INFINITY:
+ value = -INFINITY;
+ break;
+ }
+
+ return PyFloat_FromDouble(value);
+}
+
+static PyObject*
+Value_richcompare(PyObject* self, PyObject* other, int op) {
+ PyObject *result = NULL;
+
+ if (!PyValue_CHECK(other)) {
+ result = Py_NotImplemented;
+ } else {
+ lp_value_t* self_v = &((Value*) self)->v;
+ lp_value_t* other_v = &((Value*) other)->v;
+ int cmp = lp_value_cmp(self_v, other_v);
+
+ switch (op) {
+ case Py_LT:
+ result = cmp < 0 ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ result = cmp <= 0 ? Py_True : Py_False;
+ break;
+ case Py_EQ:
+ result = cmp == 0 ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = cmp != 0 ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ result = cmp > 0 ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ result = cmp >= 0 ? Py_True : Py_False;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ Py_INCREF(result);
+ return result;
+}
+
+static PyObject* Value_str(PyObject* self) {
+ Value* v = (Value*) self;
+ char* cstr = lp_value_to_string(&v->v);
+ PyObject* pystr = PyUnicode_FromString(cstr);
+ free(cstr);
+ return pystr;
+}
+
+static Py_hash_t
+Value_hash(PyObject* self) {
+ Value* v = (Value*) self;
+ Py_hash_t hash = lp_value_hash(&v->v);
+ if (hash == -1) {
+ // value -1 should not be returned as a normal return value
+ hash = 0;
+ }
+ return hash;
+}
+
+static PyObject*
+Value_get_value_between(PyObject* self, PyObject* args) {
+ // self is always a polynomial
+ Value* v1 = (Value*) self;
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ PyErr_SetString(PyExc_RuntimeError, "get_value_between(): need one argument.");
+ return NULL;
+ }
+ PyObject* other = PyTuple_GetItem(args, 0);
+
+ // other should be a value
+ if (!PyValue_CHECK(other)) {
+ PyErr_SetString(PyExc_RuntimeError, "get_value_between(): argument not a value.");
+ return NULL;
+ }
+ Value* v2 = (Value*) other;
+
+ // compare the values (they should be different)
+ if (v1->v.type == LP_VALUE_NONE || v2->v.type == LP_VALUE_NONE) {
+ PyErr_SetString(PyExc_RuntimeError, "get_value_between(): values should not be null.");
+ return NULL;
+ }
+ if (lp_value_cmp(&v1->v, &v2->v) == 0) {
+ PyErr_SetString(PyExc_RuntimeError, "get_value_between(): values should be different.");
+ return NULL;
+ }
+
+ lp_value_t m;
+ lp_value_construct_none(&m);
+ lp_value_get_value_between(&v1->v, 1, &v2->v, 1, &m);
+ PyObject* result = PyValue_create(&m);
+ lp_value_destruct(&m);
+
+ return result;
+}
+
+static PyObject*
+Value_add(PyObject* self, PyObject* other) {
+ if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ Value* v1 = (Value*) self;
+ Value* v2 = (Value*) other;
+
+ lp_value_t add;
+ lp_value_construct_none(&add);
+ lp_value_add(&add, &v1->v, &v2->v);
+ PyObject* result = PyValue_create(&add);
+ lp_value_destruct(&add);
+
+ return result;
+}
+
+static PyObject*
+Value_neg(PyObject* self) {
+ if (!PyValue_CHECK(self)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ Value* v = (Value*) self;
+
+ lp_value_t neg;
+ lp_value_construct_none(&neg);
+ lp_value_neg(&neg, &v->v);
+ PyObject* result = PyValue_create(&neg);
+ lp_value_destruct(&neg);
+
+ return result;
+}
+
+static PyObject*
+Value_sub(PyObject* self, PyObject* other) {
+ if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ Value* v1 = (Value*) self;
+ Value* v2 = (Value*) other;
+
+ lp_value_t sub;
+ lp_value_construct_none(&sub);
+ lp_value_sub(&sub, &v1->v, &v2->v);
+ PyObject* result = PyValue_create(&sub);
+ lp_value_destruct(&sub);
+
+ return result;
+}
+
+static PyObject*
+Value_mul(PyObject* self, PyObject* other) {
+ if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ Value* v1 = (Value*) self;
+ Value* v2 = (Value*) other;
+
+ lp_value_t mul;
+ lp_value_construct_none(&mul);
+ lp_value_mul(&mul, &v1->v, &v2->v);
+ PyObject* result = PyValue_create(&mul);
+ lp_value_destruct(&mul);
+
+ return result;
+}
+
+static PyObject*
+Value_div(PyObject* self, PyObject* other) {
+ if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ Value* v1 = (Value*) self;
+ Value* v2 = (Value*) other;
+
+ lp_value_t div;
+ lp_value_construct_none(&div);
+ lp_value_div(&div, &v1->v, &v2->v);
+ PyObject* result = PyValue_create(&div);
+ lp_value_destruct(&div);
+
+ return result;
+}
+
+
+static PyObject*
+Value_pow(PyObject* self, PyObject* other) {
+ if (!PyValue_CHECK(self) || !PyLong_Check(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ Value* v = (Value*) self;
+ long n = PyLong_AsLong(other);
+
+ lp_value_t mul;
+ lp_value_construct_none(&mul);
+ lp_value_pow(&mul, &v->v, n);
+ PyObject* result = PyValue_create(&mul);
+ lp_value_destruct(&mul);
+
+ return result;
+}
+
+// Returns the o converted to a long integer object on success, or NULL on
+// failure. This is the equivalent of the Python 3 expression int(o).
+// Return value: New reference.
+static PyObject*
+Value_long(PyObject* self) {
+ Value* value_obj = (Value*) self;
+ lp_integer_t int_cast;
+ lp_integer_construct(&int_cast);
+ lp_value_floor(&value_obj->v, &int_cast);
+ PyObject* py_int_cast = integer_to_PyLong(&int_cast);
+ lp_integer_destruct(&int_cast);
+ return py_int_cast;
+}
+
+// Returns the o converted to a float object on success, or NULL on failure.
+// This is the equivalent of the Python expression float(o).
+// Return value: New reference.
+static PyObject*
+Value_float(PyObject* self) {
+ Value* value_obj = (Value*) self;
+ double value = lp_value_to_double(&value_obj->v);
+ return PyFloat_FromDouble(value);
+}
diff --git a/python/polypyValue.h b/python/polypyValue.h
index fca471f8..d3ddd6f4 100644
--- a/python/polypyValue.h
+++ b/python/polypyValue.h
@@ -19,8 +19,7 @@
#pragma once
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include "value.h"
diff --git a/python/polypyValue2.c b/python/polypyValue2.c
deleted file mode 100644
index 7f82a456..00000000
--- a/python/polypyValue2.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/**
- * 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 "polypyValue.h"
-#include "utils.h"
-#include "polypyAlgebraicNumber.h"
-
-#include
-#include
-
-static void
-Value_dealloc(Value* self);
-
-static PyObject*
-Value_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-Value_init(Value* self, PyObject* args);
-
-static PyObject*
-Value_to_double(PyObject* self);
-
-static int
-Value_cmp(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_richcompare(PyObject* self, PyObject* other, int op);
-
-static PyObject*
-Value_str(PyObject* self);
-
-static long
-Value_hash(PyObject* self);
-
-static PyObject*
-Value_get_value_between(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_add(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_neg(PyObject* self);
-
-static PyObject*
-Value_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_div(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_pow(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_int(PyObject* self);
-
-static PyObject*
-Value_long(PyObject* self);
-
-static PyObject*
-Value_float(PyObject* self);
-
-PyMethodDef Value_methods[] = {
- {"to_double", (PyCFunction)Value_to_double, METH_NOARGS, "Returns the approximation of the value"},
- {"get_value_between", (PyCFunction)Value_get_value_between, METH_VARARGS, "Returns a value between this and given value"},
- {NULL} /* Sentinel */
-};
-
-PyNumberMethods Value_NumberMethods = {
- Value_add, // binaryfunc nb_add;
- Value_sub, // binaryfunc nb_subtract;
- Value_mul, // binaryfunc nb_multiply;
- Value_div, // binaryfunc nb_divide;
- 0, // binaryfunc nb_remainder;
- 0, // binaryfunc nb_divmod;
- (ternaryfunc)Value_pow, // ternaryfunc nb_power;
- Value_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- 0, // inquiry nb_nonzero; /* Used by PyObject_IsTrue */
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- 0, // coercion nb_coerce; /* Used by the coerce() function */
- Value_int, // unaryfunc nb_int;
- Value_long, // unaryfunc nb_long;
- Value_float, // unaryfunc nb_float;
- 0, // unaryfunc nb_oct;
- 0, // unaryfunc nb_hex;
-
- /* Added in release 2.0 */
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_divide;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
-
- /* Added in release 2.2 */
- 0, // binaryfunc nb_floor_divide;
- 0, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
-
- /* Added in release 2.5 */
- 0 // unaryfunc nb_index;
-};
-
-PyTypeObject ValueType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.Value", /*tp_name*/
- sizeof(Value), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)Value_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- Value_cmp, /*tp_compare*/
- Value_str, /*tp_repr*/
- &Value_NumberMethods, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- &Value_hash, /*tp_hash */
- 0, /*tp_call*/
- Value_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "Values of different kinds", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- Value_richcompare,/* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- Value_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)Value_init,/* tp_init */
- 0, /* tp_alloc */
- Value_new, /* tp_new */
-};
-
-static void
-Value_dealloc(Value* self)
-{
- lp_value_destruct(&self->v);
- self->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyValue_create(const lp_value_t* v) {
- Value *self;
- self = (Value*)ValueType.tp_alloc(&ValueType, 0);
- if (self != NULL) {
- if (v) {
- lp_value_construct_copy(&self->v, v);
- } else {
- lp_value_construct_zero(&self->v);
- }
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-Value_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyValue_create(0);
-}
-
-/** Construct a value from given number (integer, long or algebraic. */
-static int
-Value_init(Value* self, PyObject* args)
-{
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) == 0) {
- lp_value_construct_zero(&self->v);
- } else if (PyTuple_Size(args) == 1) {
- PyObject* v = PyTuple_GetItem(args, 0);
- if (PyInt_Check(v)) {
- long v_int = PyInt_AsLong(v);
- lp_value_construct_int(&self->v, v_int);
- } else if (PyAlgebraicNumber_CHECK(v)) {
- AlgebraicNumber* v_alg = (AlgebraicNumber*) v;
- lp_value_construct(&self->v, LP_VALUE_ALGEBRAIC, &v_alg->a);
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-
- // All fine, initialized
- return 0;
-}
-
-static PyObject*
-Value_to_double(PyObject* self) {
-
- Value* a = (Value*) self;
-
- double value = 0;
-
- switch (a->v.type) {
- case LP_VALUE_NONE:
- assert(0);
- break;
- case LP_VALUE_INTEGER:
- value = lp_integer_to_int(&a->v.value.z);
- break;
- case LP_VALUE_DYADIC_RATIONAL:
- value = lp_dyadic_rational_to_double(&a->v.value.dy_q);
- break;
- case LP_VALUE_RATIONAL:
- value = lp_rational_to_double(&a->v.value.q);
- break;
- case LP_VALUE_ALGEBRAIC:
- value = lp_algebraic_number_to_double(&a->v.value.a);
- break;
- case LP_VALUE_PLUS_INFINITY:
- value = INFINITY;
- break;
- case LP_VALUE_MINUS_INFINITY:
- value = -INFINITY;
- break;
- }
-
- return PyFloat_FromDouble(value);
-}
-
-static int
-Value_cmp(PyObject* self, PyObject* other) {
- // Check arguments
- if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
- // should return -1 and set an exception condition when an error occurred
- return -1;
- }
- // Get arguments
- Value* v1 = (Value*) self;
- Value* v2 = (Value*) other;
- // Compare
- return lp_value_cmp(&v1->v, &v2->v);
-}
-
-static PyObject*
-Value_richcompare(PyObject* self, PyObject* other, int op) {
- PyObject *result = 0;
-
- if (!PyValue_CHECK(other)) {
- result = Py_NotImplemented;
- } else {
- lp_value_t* self_v = &((Value*) self)->v;
- lp_value_t* other_v = &((Value*) other)->v;
- int cmp = lp_value_cmp(self_v, other_v);
-
- switch (op) {
- case Py_LT:
- result = cmp < 0 ? Py_True : Py_False;
- break;
- case Py_LE:
- result = cmp <= 0 ? Py_True : Py_False;
- break;
- case Py_EQ:
- result = cmp == 0 ? Py_True : Py_False;
- break;
- case Py_NE:
- result = cmp != 0 ? Py_True : Py_False;
- break;
- case Py_GT:
- result = cmp > 0 ? Py_True : Py_False;
- break;
- case Py_GE:
- result = cmp >= 0 ? Py_True : Py_False;
- break;
- default:
- assert(0);
- }
- }
-
- Py_INCREF(result);
- return result;
-}
-
-static PyObject* Value_str(PyObject* self) {
- Value* v = (Value*) self;
- char* cstr = lp_value_to_string(&v->v);
- PyObject* pystr = PyString_FromString(cstr);
- free(cstr);
- return pystr;
-}
-
-static long
-Value_hash(PyObject* self) {
- Value* v = (Value*) self;
- long hash = lp_value_hash(&v->v);
- if (hash == -1) {
- // value -1 should not be returned as a normal return value
- hash = 0;
- }
- return hash;
-}
-
-static PyObject*
-Value_get_value_between(PyObject* self, PyObject* args) {
- // self is always a polynomial
- Value* v1 = (Value*) self;
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- PyErr_SetString(PyExc_RuntimeError, "get_value_between(): need one argument.");
- return NULL;
- }
- PyObject* other = PyTuple_GetItem(args, 0);
-
- // other should be a value
- if (!PyValue_CHECK(other)) {
- PyErr_SetString(PyExc_RuntimeError, "get_value_between(): argument not a value.");
- return NULL;
- }
- Value* v2 = (Value*) other;
-
- // compare the values (they should be different)
- if (v1->v.type == LP_VALUE_NONE || v2->v.type == LP_VALUE_NONE) {
- PyErr_SetString(PyExc_RuntimeError, "get_value_between(): values should not be null.");
- return NULL;
- }
- if (lp_value_cmp(&v1->v, &v2->v) == 0) {
- PyErr_SetString(PyExc_RuntimeError, "get_value_between(): values should be different.");
- return NULL;
- }
-
- lp_value_t m;
- lp_value_construct_none(&m);
- lp_value_get_value_between(&v1->v, 1, &v2->v, 1, &m);
- PyObject* result = PyValue_create(&m);
- lp_value_destruct(&m);
-
- return result;
-}
-
-static PyObject*
-Value_add(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v1 = (Value*) self;
- Value* v2 = (Value*) other;
-
- lp_value_t add;
- lp_value_construct_none(&add);
- lp_value_add(&add, &v1->v, &v2->v);
- PyObject* result = PyValue_create(&add);
- lp_value_destruct(&add);
-
- return result;
-}
-
-static PyObject*
-Value_neg(PyObject* self) {
- if (!PyValue_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v = (Value*) self;
-
- lp_value_t neg;
- lp_value_construct_none(&neg);
- lp_value_neg(&neg, &v->v);
- PyObject* result = PyValue_create(&neg);
- lp_value_destruct(&neg);
-
- return result;
-}
-
-static PyObject*
-Value_sub(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v1 = (Value*) self;
- Value* v2 = (Value*) other;
-
- lp_value_t sub;
- lp_value_construct_none(&sub);
- lp_value_sub(&sub, &v1->v, &v2->v);
- PyObject* result = PyValue_create(&sub);
- lp_value_destruct(&sub);
-
- return result;
-}
-
-static PyObject*
-Value_mul(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v1 = (Value*) self;
- Value* v2 = (Value*) other;
-
- lp_value_t mul;
- lp_value_construct_none(&mul);
- lp_value_mul(&mul, &v1->v, &v2->v);
- PyObject* result = PyValue_create(&mul);
- lp_value_destruct(&mul);
-
- return result;
-}
-
-static PyObject*
-Value_div(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v1 = (Value*) self;
- Value* v2 = (Value*) other;
-
- lp_value_t div;
- lp_value_construct_none(&div);
- lp_value_div(&div, &v1->v, &v2->v);
- PyObject* result = PyValue_create(&div);
- lp_value_destruct(&div);
-
- return result;
-}
-
-
-static PyObject*
-Value_pow(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyInt_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v = (Value*) self;
- long n = PyInt_AsLong(other);
-
- lp_value_t mul;
- lp_value_construct_none(&mul);
- lp_value_pow(&mul, &v->v, n);
- PyObject* result = PyValue_create(&mul);
- lp_value_destruct(&mul);
-
- return result;
-}
-
-// Returns the o converted to an integer object on success, or NULL on failure.
-// If the argument is outside the integer range a long object will be returned
-// instead. This is the equivalent of the Python expression int(o).
-// Return value: New reference.
-static PyObject*
-Value_int(PyObject* self) {
- Value* value_obj = (Value*) self;
- lp_integer_t int_cast;
- lp_integer_construct(&int_cast);
- lp_value_floor(&value_obj->v, &int_cast);
- PyObject* py_int_cast = integer_to_PyInt(&int_cast);
- lp_integer_destruct(&int_cast);
- return py_int_cast;
-}
-
-// Returns the o converted to a long integer object on success, or NULL on
-// failure. This is the equivalent of the Python expression long(o).
-// Return value: New reference.
-static PyObject*
-Value_long(PyObject* self) {
- Value* value_obj = (Value*) self;
- lp_integer_t int_cast;
- lp_integer_construct(&int_cast);
- lp_value_floor(&value_obj->v, &int_cast);
- PyObject* py_int_cast = integer_to_PyLong(&int_cast);
- lp_integer_destruct(&int_cast);
- return py_int_cast;
-}
-
-// Returns the o converted to a float object on success, or NULL on failure.
-// This is the equivalent of the Python expression float(o).
-// Return value: New reference.
-static PyObject*
-Value_float(PyObject* self) {
- Value* value_obj = (Value*) self;
- double value = lp_value_to_double(&value_obj->v);
- return PyFloat_FromDouble(value);
-}
diff --git a/python/polypyValue3.c b/python/polypyValue3.c
deleted file mode 100644
index 6fccbe71..00000000
--- a/python/polypyValue3.c
+++ /dev/null
@@ -1,490 +0,0 @@
-/**
- * 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 "polypyValue.h"
-#include "utils.h"
-#include "polypyAlgebraicNumber.h"
-
-#include
-#include
-
-static void
-Value_dealloc(Value* self);
-
-static PyObject*
-Value_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-Value_init(Value* self, PyObject* args);
-
-static PyObject*
-Value_to_double(PyObject* self);
-
-static PyObject*
-Value_richcompare(PyObject* self, PyObject* other, int op);
-
-static PyObject*
-Value_str(PyObject* self);
-
-static Py_hash_t
-Value_hash(PyObject* self);
-
-static PyObject*
-Value_get_value_between(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_add(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_neg(PyObject* self);
-
-static PyObject*
-Value_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_div(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_pow(PyObject* self, PyObject* args);
-
-static PyObject*
-Value_long(PyObject* self);
-
-static PyObject*
-Value_float(PyObject* self);
-
-PyMethodDef Value_methods[] = {
- {"to_double", (PyCFunction)Value_to_double, METH_NOARGS, "Returns the approximation of the value"},
- {"get_value_between", (PyCFunction)Value_get_value_between, METH_VARARGS, "Returns a value between this and given value"},
- {NULL} /* Sentinel */
-};
-
-PyNumberMethods Value_NumberMethods = {
- Value_add, // binaryfunc nb_add;
- Value_sub, // binaryfunc nb_subtract;
- Value_mul, // binaryfunc nb_multiply;
- 0, // binaryfunc nb_remainder;
- 0, // binaryfunc nb_divmod;
- (ternaryfunc)Value_pow, // ternaryfunc nb_power;
- Value_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- 0, // inquiry nb_bool;
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- Value_long, // unaryfunc nb_int;
- 0, // void *nb_reserved;
- Value_float, // unaryfunc nb_float;
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
- 0, // binaryfunc nb_floor_divide;
- Value_div, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
- 0, // unaryfunc nb_index;
- 0, // binaryfunc nb_matrix_multiply;
- 0, // binaryfunc nb_inplace_matrix_multiply;
-};
-
-PyTypeObject ValueType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.Value", // const char *tp_name;
- sizeof(Value), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)Value_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async;
- Value_str, // reprfunc tp_repr;
- &Value_NumberMethods, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- &Value_hash, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- Value_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "Values of different kinds", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- Value_richcompare, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- Value_methods, // struct PyMethodDef *tp_methods;
- 0, // struct PyMemberDef *tp_members;
- 0, // struct PyGetSetDef *tp_getset;
- 0, // struct _typeobject *tp_base;
- 0, // PyObject *tp_dict;
- 0, // descrgetfunc tp_descr_get;
- 0, // descrsetfunc tp_descr_set;
- 0, // Py_ssize_t tp_dictoffset;
- (initproc)Value_init, // initproc tp_init;
- 0, // allocfunc tp_alloc;
- Value_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-static void
-Value_dealloc(Value* self)
-{
- lp_value_destruct(&self->v);
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-PyObject*
-PyValue_create(const lp_value_t* v) {
- Value *self;
- self = (Value*)ValueType.tp_alloc(&ValueType, 0);
- if (self != NULL) {
- if (v) {
- lp_value_construct_copy(&self->v, v);
- } else {
- lp_value_construct_zero(&self->v);
- }
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-Value_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyValue_create(0);
-}
-
-/** Construct a value from given number. */
-static int
-Value_init(Value* self, PyObject* args)
-{
- if (PyTuple_Check(args)) {
- if (PyTuple_Size(args) == 0) {
- lp_value_construct_zero(&self->v);
- } else if (PyTuple_Size(args) == 1) {
- PyObject* v = PyTuple_GetItem(args, 0);
- if (PyLong_Check(v)) {
- long v_int = PyLong_AsLong(v);
- lp_value_construct_int(&self->v, v_int);
- } else if (PyAlgebraicNumber_CHECK(v)) {
- AlgebraicNumber* v_alg = (AlgebraicNumber*) v;
- lp_value_construct(&self->v, LP_VALUE_ALGEBRAIC, &v_alg->a);
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-
- // All fine, initialized
- return 0;
-}
-
-static PyObject*
-Value_to_double(PyObject* self) {
-
- Value* a = (Value*) self;
-
- double value = 0;
-
- switch (a->v.type) {
- case LP_VALUE_NONE:
- assert(0);
- break;
- case LP_VALUE_INTEGER:
- value = lp_integer_to_int(&a->v.value.z);
- break;
- case LP_VALUE_DYADIC_RATIONAL:
- value = lp_dyadic_rational_to_double(&a->v.value.dy_q);
- break;
- case LP_VALUE_RATIONAL:
- value = lp_rational_to_double(&a->v.value.q);
- break;
- case LP_VALUE_ALGEBRAIC:
- value = lp_algebraic_number_to_double(&a->v.value.a);
- break;
- case LP_VALUE_PLUS_INFINITY:
- value = INFINITY;
- break;
- case LP_VALUE_MINUS_INFINITY:
- value = -INFINITY;
- break;
- }
-
- return PyFloat_FromDouble(value);
-}
-
-static PyObject*
-Value_richcompare(PyObject* self, PyObject* other, int op) {
- PyObject *result = 0;
-
- if (!PyValue_CHECK(other)) {
- result = Py_NotImplemented;
- } else {
- lp_value_t* self_v = &((Value*) self)->v;
- lp_value_t* other_v = &((Value*) other)->v;
- int cmp = lp_value_cmp(self_v, other_v);
-
- switch (op) {
- case Py_LT:
- result = cmp < 0 ? Py_True : Py_False;
- break;
- case Py_LE:
- result = cmp <= 0 ? Py_True : Py_False;
- break;
- case Py_EQ:
- result = cmp == 0 ? Py_True : Py_False;
- break;
- case Py_NE:
- result = cmp != 0 ? Py_True : Py_False;
- break;
- case Py_GT:
- result = cmp > 0 ? Py_True : Py_False;
- break;
- case Py_GE:
- result = cmp >= 0 ? Py_True : Py_False;
- break;
- default:
- assert(0);
- }
- }
-
- Py_INCREF(result);
- return result;
-}
-
-static PyObject* Value_str(PyObject* self) {
- Value* v = (Value*) self;
- char* cstr = lp_value_to_string(&v->v);
- PyObject* pystr = PyUnicode_FromString(cstr);
- free(cstr);
- return pystr;
-}
-
-static Py_hash_t
-Value_hash(PyObject* self) {
- Value* v = (Value*) self;
- Py_hash_t hash = lp_value_hash(&v->v);
- if (hash == -1) {
- // value -1 should not be returned as a normal return value
- hash = 0;
- }
- return hash;
-}
-
-static PyObject*
-Value_get_value_between(PyObject* self, PyObject* args) {
- // self is always a polynomial
- Value* v1 = (Value*) self;
- if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
- PyErr_SetString(PyExc_RuntimeError, "get_value_between(): need one argument.");
- return NULL;
- }
- PyObject* other = PyTuple_GetItem(args, 0);
-
- // other should be a value
- if (!PyValue_CHECK(other)) {
- PyErr_SetString(PyExc_RuntimeError, "get_value_between(): argument not a value.");
- return NULL;
- }
- Value* v2 = (Value*) other;
-
- // compare the values (they should be different)
- if (v1->v.type == LP_VALUE_NONE || v2->v.type == LP_VALUE_NONE) {
- PyErr_SetString(PyExc_RuntimeError, "get_value_between(): values should not be null.");
- return NULL;
- }
- if (lp_value_cmp(&v1->v, &v2->v) == 0) {
- PyErr_SetString(PyExc_RuntimeError, "get_value_between(): values should be different.");
- return NULL;
- }
-
- lp_value_t m;
- lp_value_construct_none(&m);
- lp_value_get_value_between(&v1->v, 1, &v2->v, 1, &m);
- PyObject* result = PyValue_create(&m);
- lp_value_destruct(&m);
-
- return result;
-}
-
-static PyObject*
-Value_add(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v1 = (Value*) self;
- Value* v2 = (Value*) other;
-
- lp_value_t add;
- lp_value_construct_none(&add);
- lp_value_add(&add, &v1->v, &v2->v);
- PyObject* result = PyValue_create(&add);
- lp_value_destruct(&add);
-
- return result;
-}
-
-static PyObject*
-Value_neg(PyObject* self) {
- if (!PyValue_CHECK(self)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v = (Value*) self;
-
- lp_value_t neg;
- lp_value_construct_none(&neg);
- lp_value_neg(&neg, &v->v);
- PyObject* result = PyValue_create(&neg);
- lp_value_destruct(&neg);
-
- return result;
-}
-
-static PyObject*
-Value_sub(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v1 = (Value*) self;
- Value* v2 = (Value*) other;
-
- lp_value_t sub;
- lp_value_construct_none(&sub);
- lp_value_sub(&sub, &v1->v, &v2->v);
- PyObject* result = PyValue_create(&sub);
- lp_value_destruct(&sub);
-
- return result;
-}
-
-static PyObject*
-Value_mul(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v1 = (Value*) self;
- Value* v2 = (Value*) other;
-
- lp_value_t mul;
- lp_value_construct_none(&mul);
- lp_value_mul(&mul, &v1->v, &v2->v);
- PyObject* result = PyValue_create(&mul);
- lp_value_destruct(&mul);
-
- return result;
-}
-
-static PyObject*
-Value_div(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v1 = (Value*) self;
- Value* v2 = (Value*) other;
-
- lp_value_t div;
- lp_value_construct_none(&div);
- lp_value_div(&div, &v1->v, &v2->v);
- PyObject* result = PyValue_create(&div);
- lp_value_destruct(&div);
-
- return result;
-}
-
-
-static PyObject*
-Value_pow(PyObject* self, PyObject* other) {
- if (!PyValue_CHECK(self) || !PyLong_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Value* v = (Value*) self;
- long n = PyLong_AsLong(other);
-
- lp_value_t mul;
- lp_value_construct_none(&mul);
- lp_value_pow(&mul, &v->v, n);
- PyObject* result = PyValue_create(&mul);
- lp_value_destruct(&mul);
-
- return result;
-}
-
-// Returns the o converted to a long integer object on success, or NULL on
-// failure. This is the equivalent of the Python 3 expression int(o).
-// Return value: New reference.
-static PyObject*
-Value_long(PyObject* self) {
- Value* value_obj = (Value*) self;
- lp_integer_t int_cast;
- lp_integer_construct(&int_cast);
- lp_value_floor(&value_obj->v, &int_cast);
- PyObject* py_int_cast = integer_to_PyLong(&int_cast);
- lp_integer_destruct(&int_cast);
- return py_int_cast;
-}
-
-// Returns the o converted to a float object on success, or NULL on failure.
-// This is the equivalent of the Python expression float(o).
-// Return value: New reference.
-static PyObject*
-Value_float(PyObject* self) {
- Value* value_obj = (Value*) self;
- double value = lp_value_to_double(&value_obj->v);
- return PyFloat_FromDouble(value);
-}
diff --git a/python/polypyVariable.c b/python/polypyVariable.c
index 026e904f..e5c93bc0 100644
--- a/python/polypyVariable.c
+++ b/python/polypyVariable.c
@@ -17,12 +17,507 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include
-
-#if PY_MAJOR_VERSION >= 3
-#include "polypyVariable3.c"
-#else
-#include "polypyVariable2.c"
-#endif
+#include "python.h"
+
+#include "polypyVariable.h"
+#include "polypyInteger.h"
+#include "polypyPolynomial.h"
+#include "utils.h"
+
+#include
+
+/** Default variable database */
+static lp_variable_db_t* default_var_db = NULL;
+
+void Variable_init_default_db(void) {
+ if (default_var_db) {
+ lp_variable_db_detach(default_var_db);
+ }
+ default_var_db = lp_variable_db_new();
+}
+
+lp_variable_db_t* Variable_get_default_db(void) {
+ if (!default_var_db) {
+ Variable_init_default_db();
+ }
+ return default_var_db;
+}
+
+static PyObject*
+Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static int
+Variable_init(Variable* self, PyObject* args);
+
+static void
+Variable_dealloc(Variable* self);
+
+static PyObject*
+Variable_str(PyObject* self);
+
+static PyObject*
+Variable_repr(PyObject* self);
+
+static Py_hash_t
+Variable_hash(PyObject* self);
+
+static PyObject *
+Variable_richcompare(PyObject *self, PyObject *other, int op);
+
+PyMethodDef Variable_methods[] = {
+ {NULL} /* Sentinel */
+};
+
+static PyObject*
+Variable_add(PyObject* self, PyObject* other);
+
+static PyObject*
+Variable_neg(PyObject* self);
+
+static PyObject*
+Variable_sub(PyObject* self, PyObject* other);
+
+static PyObject*
+Variable_mul(PyObject* self, PyObject* other);
+
+static PyObject*
+Variable_pow(PyObject* self, PyObject* other);
+
+PyNumberMethods Variable_NumberMethods = {
+ Variable_add, // binaryfunc nb_add;
+ Variable_sub, // binaryfunc nb_subtract;
+ Variable_mul, // binaryfunc nb_multiply;
+ NULL, // binaryfunc nb_remainder;
+ NULL, // binaryfunc nb_divmod;
+ (ternaryfunc)Variable_pow, // ternaryfunc nb_power;
+ Variable_neg, // unaryfunc nb_negative;
+ NULL, // unaryfunc nb_positive;
+ NULL, // unaryfunc nb_absolute;
+ NULL, // inquiry nb_bool;
+ NULL, // unaryfunc nb_invert;
+ NULL, // binaryfunc nb_lshift;
+ NULL, // binaryfunc nb_rshift;
+ NULL, // binaryfunc nb_and;
+ NULL, // binaryfunc nb_xor;
+ NULL, // binaryfunc nb_or;
+ NULL, // unaryfunc nb_int;
+ NULL, // void *nb_reserved;
+ NULL, // unaryfunc nb_float;
+ NULL, // binaryfunc nb_inplace_add;
+ NULL, // binaryfunc nb_inplace_subtract;
+ NULL, // binaryfunc nb_inplace_multiply;
+ NULL, // binaryfunc nb_inplace_remainder;
+ NULL, // ternaryfunc nb_inplace_power;
+ NULL, // binaryfunc nb_inplace_lshift;
+ NULL, // binaryfunc nb_inplace_rshift;
+ NULL, // binaryfunc nb_inplace_and;
+ NULL, // binaryfunc nb_inplace_xor;
+ NULL, // binaryfunc nb_inplace_or;
+ NULL, // binaryfunc nb_floor_divide;
+ NULL, // binaryfunc nb_true_divide;
+ NULL, // binaryfunc nb_inplace_floor_divide;
+ NULL, // binaryfunc nb_inplace_true_divide;
+ NULL, // unaryfunc nb_index;
+ NULL, // binaryfunc nb_matrix_multiply;
+ NULL, // binaryfunc nb_inplace_matrix_multiply;
+};
+
+PyTypeObject VariableType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.Variable", // const char *tp_name;
+ sizeof(Variable), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)Variable_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async;
+ Variable_repr, // reprfunc tp_repr;
+ &Variable_NumberMethods, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ Variable_hash, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ Variable_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "Variable objects", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ Variable_richcompare, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ Variable_methods, // struct PyMethodDef *tp_methods;
+ NULL, // istruct PyMemberDef *tp_members;
+ NULL, // istruct PyGetSetDef *tp_getset;
+ NULL, // istruct _typeobject *tp_base;
+ NULL, // iPyObject *tp_dict;
+ NULL, // idescrgetfunc tp_descr_get;
+ NULL, // idescrsetfunc tp_descr_set;
+ 0, // iPy_ssize_t tp_dictoffset;
+ (initproc)Variable_init, // initproc tp_init;
+ NULL, // allocfunc tp_alloc;
+ Variable_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+PyObject*
+PyVariable_create(lp_variable_t x) {
+ Variable *self = (Variable*)VariableType.tp_alloc(&VariableType, 0);
+ if (self != NULL) {
+ self->x = x;
+ }
+ return (PyObject *)self;
+}
+
+static PyObject*
+Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return PyVariable_create(0);
+}
+
+static int
+Variable_init(Variable* self, PyObject* args)
+{
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
+ PyObject* obj = PyTuple_GetItem(args, 0);
+ if (PyUnicode_Check(obj) || PyBytes_Check(obj)) {
+ const char* c_str = pythonObject2CharStar(obj);
+ lp_variable_t x = lp_variable_db_new_variable(Variable_get_default_db(), c_str);
+ self->x = x;
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static void
+Variable_dealloc(Variable* self)
+{
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+static PyObject* Variable_str(PyObject* self) {
+ Variable* x = (Variable*) self;
+ const char* x_str = lp_variable_db_get_name(Variable_get_default_db(), x->x);
+ PyObject* str = PyUnicode_FromString(x_str);
+ return str;
+}
+
+static PyObject* Variable_repr(PyObject* self) {
+ Variable* x = (Variable*) self;
+ const char* x_str = lp_variable_db_get_name(Variable_get_default_db(), x->x);
+ char* x_repr = malloc(strlen(x_str) + strlen(VariableType.tp_name) + 5);
+ sprintf(x_repr, "%s('%s')", VariableType.tp_name, x_str);
+ PyObject* str = PyUnicode_FromString(x_repr);
+ free(x_repr);
+ return str;
+}
+
+static Py_hash_t Variable_hash(PyObject* self) {
+ Variable* x = (Variable*) self;
+ return x->x;
+}
+
+static
+lp_polynomial_t* PyLong_Or_Int_to_polynomial(PyObject* number) {
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+ lp_integer_t c;
+ PyLong_or_Int_to_integer(number, NULL, &c);
+ lp_polynomial_t* p_c = lp_polynomial_alloc();
+ lp_polynomial_construct_simple(p_c, ctx, &c, 0, 0);
+ lp_integer_destruct(&c);
+ return p_c;
+}
+
+static
+lp_polynomial_t* Variable_to_polynomial(PyObject* var) {
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+ Variable* x = (Variable*) var;
+ lp_integer_t one;
+ lp_integer_construct_from_int(lp_Z, &one, 1);
+ lp_polynomial_t* p_x = lp_polynomial_alloc();
+ lp_polynomial_construct_simple(p_x, ctx, &one, x->x, 1);
+ lp_integer_destruct(&one);
+ return p_x;
+}
+
+static PyObject*
+Variable_add_number(PyObject* self, PyObject* other) {
+
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+
+ // The x polynomial
+ lp_polynomial_t* p_x = Variable_to_polynomial(self);
+ // The c polynomial
+ lp_polynomial_t* p_c = PyLong_Or_Int_to_polynomial(other);
+
+ // x + c polynomial
+ lp_polynomial_t* p_sum = lp_polynomial_new(ctx);
+ lp_polynomial_add(p_sum, p_x, p_c);
+
+ // Remove temporaries
+ lp_polynomial_destruct(p_x);
+ lp_polynomial_destruct(p_c);
+ free(p_x);
+ free(p_c);
+
+ return Polynomial_create(p_sum);
+}
+
+static PyObject*
+Variable_add_Variable(PyObject* self, PyObject* other) {
+
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+
+ // The x polynomial
+ lp_polynomial_t* p_x = Variable_to_polynomial(self);
+ // The c polynomial
+ lp_polynomial_t* p_y = Variable_to_polynomial(other);
+
+ // x + c polynomial
+ lp_polynomial_t* p_sum = lp_polynomial_new(ctx);
+ lp_polynomial_add(p_sum, p_x, p_y);
+
+ // Remove temporaries
+ lp_polynomial_destruct(p_x);
+ lp_polynomial_destruct(p_y);
+ free(p_x);
+ free(p_y);
+
+ return Polynomial_create(p_sum);
+}
+
+static PyObject*
+Variable_add(PyObject* self, PyObject* other) {
+ // Integer addition
+ if (PyLong_or_Int_Check(other)) {
+ return Variable_add_number(self, other);
+ } else if (PyLong_or_Int_Check(self)) {
+ return Variable_add_number(other, self);
+ } else if (PyVariable_CHECK(other)) {
+ return Variable_add_Variable(self, other);
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+}
+
+static PyObject*
+Variable_neg(PyObject* self) {
+
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+
+ // The x polynomial
+ lp_polynomial_t* p_x = Variable_to_polynomial(self);
+
+ // -x polynomial
+ lp_polynomial_t* p_neg = lp_polynomial_new(ctx);
+ lp_polynomial_neg(p_neg, p_x);
+
+ // Remove temporaries
+ lp_polynomial_destruct(p_x);
+ free(p_x);
+
+ return Polynomial_create(p_neg);
+}
+
+static PyObject*
+Variable_sub_number(PyObject* self, PyObject* other) {
+
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+
+ // The x polynomial
+ lp_polynomial_t* p_x = Variable_to_polynomial(self);
+ // The c polynomial
+ lp_polynomial_t* p_c = PyLong_Or_Int_to_polynomial(other);
+
+ // x + c polynomial
+ lp_polynomial_t* p_sub = lp_polynomial_new(ctx);
+ lp_polynomial_sub(p_sub, p_x, p_c);
+
+ // Remove temporaries
+ lp_polynomial_destruct(p_x);
+ lp_polynomial_destruct(p_c);
+ free(p_x);
+ free(p_c);
+
+ return Polynomial_create(p_sub);
+}
+
+static PyObject*
+Variable_sub_Variable(PyObject* self, PyObject* other) {
+
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+
+ // The x polynomial
+ lp_polynomial_t* p_x = Variable_to_polynomial(self);
+ // The c polynomial
+ lp_polynomial_t* p_y = Variable_to_polynomial(other);
+
+ // x - y polynomial
+ lp_polynomial_t* p_sub = lp_polynomial_new(ctx);
+ lp_polynomial_sub(p_sub, p_x, p_y);
+
+ // Remove temporaries
+ lp_polynomial_destruct(p_x);
+ lp_polynomial_destruct(p_y);
+ free(p_x);
+ free(p_y);
+
+ return Polynomial_create(p_sub);
+}
+
+static PyObject*
+Variable_sub(PyObject* self, PyObject* other) {
+ // Integer addition
+ if (PyLong_or_Int_Check(other)) {
+ return Variable_sub_number(self, other);
+ } else if (PyLong_or_Int_Check(self)) {
+ Polynomial* result = (Polynomial*) Variable_sub_number(other, self);
+ lp_polynomial_neg(result->p, result->p);
+ return (PyObject*) result;
+ } else if (PyVariable_CHECK(other)) {
+ return Variable_sub_Variable(self, other);
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+}
+
+static PyObject*
+Variable_mul_number(PyObject* self, PyObject* other) {
+
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+
+ // The x polynomial
+ lp_polynomial_t* p_x = Variable_to_polynomial(self);
+ // The c polynomial
+ lp_polynomial_t* p_c = PyLong_Or_Int_to_polynomial(other);
+
+ // x + c polynomial
+ lp_polynomial_t* p_mul = lp_polynomial_new(ctx);
+ lp_polynomial_mul(p_mul, p_x, p_c);
+
+ // Remove temporaries
+ lp_polynomial_destruct(p_x);
+ lp_polynomial_destruct(p_c);
+ free(p_x);
+ free(p_c);
+
+ return Polynomial_create(p_mul);
+}
+
+static PyObject*
+Variable_mul_Variable(PyObject* self, PyObject* other) {
+
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+
+ // The x polynomial
+ lp_polynomial_t* p_x = Variable_to_polynomial(self);
+ // The c polynomial
+ lp_polynomial_t* p_y = Variable_to_polynomial(other);
+
+ // x + c polynomial
+ lp_polynomial_t* p_mul = lp_polynomial_new(ctx);
+ lp_polynomial_mul(p_mul, p_x, p_y);
+
+ // Remove temporaries
+ lp_polynomial_destruct(p_x);
+ lp_polynomial_destruct(p_y);
+ free(p_x);
+ free(p_y);
+
+ return Polynomial_create(p_mul);
+}
+
+static PyObject*
+Variable_mul(PyObject* self, PyObject* other) {
+ // Integer addition
+ if (PyLong_or_Int_Check(other)) {
+ return Variable_mul_number(self, other);
+ } else if (PyLong_or_Int_Check(self)) {
+ return Variable_mul_number(other, self);
+ } else if (PyVariable_CHECK(other)) {
+ return Variable_mul_Variable(other, self);
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+}
+
+static PyObject*
+Variable_pow(PyObject* self, PyObject* other) {
+ // Check arguments
+ if (!PyVariable_CHECK(self) || !PyLong_Check(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ } else {
+ long n = PyLong_AsLong(other);
+ if (n < 0) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ } else {
+ const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
+ Variable* var = (Variable*) self;
+ lp_integer_t one;
+ lp_integer_construct_from_int(lp_Z, &one, 1);
+ lp_polynomial_t* pow_x = lp_polynomial_alloc();
+ lp_polynomial_construct_simple(pow_x, ctx, &one, var->x, n);
+ lp_integer_destruct(&one);
+ return Polynomial_create(pow_x);
+ }
+ }
+}
+
+static PyObject *
+Variable_richcompare(PyObject *self, PyObject *other, int op){
+ PyObject *result = Py_NotImplemented;
+
+ if (!PyVariable_CHECK(other)) {
+ if(op == Py_EQ){ return Py_False; }
+ if(op == Py_NE){ return Py_True; }
+ } else {
+ Variable* x = (Variable*) self;
+ Variable* y = (Variable*) other;
+
+ switch (op) {
+ case Py_LT:
+ result = (x->x < y->x ? Py_True : Py_False);
+ break;
+ case Py_LE:
+ result = (x->x <= y->x ? Py_True : Py_False);
+ break;
+ case Py_EQ:
+ result = (x->x == y->x ? Py_True : Py_False);
+ break;
+ case Py_NE:
+ result = (x->x != y->x ? Py_True : Py_False);
+ break;
+ case Py_GT:
+ result = (x->x > y->x ? Py_True : Py_False);
+ break;
+ case Py_GE:
+ result = (x->x >= y->x ? Py_True : Py_False);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ return result;
+}
diff --git a/python/polypyVariable.h b/python/polypyVariable.h
index 1b63cdb6..fbb311a7 100644
--- a/python/polypyVariable.h
+++ b/python/polypyVariable.h
@@ -19,8 +19,7 @@
#pragma once
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include
#include
diff --git a/python/polypyVariable2.c b/python/polypyVariable2.c
deleted file mode 100644
index a1e044db..00000000
--- a/python/polypyVariable2.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/**
- * 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 "polypyVariable.h"
-#include "polypyInteger.h"
-#include "polypyPolynomial.h"
-
-#include
-
-/** Default variable database */
-static lp_variable_db_t* default_var_db = 0;
-
-void Variable_init_default_db(void) {
- if (default_var_db) {
- lp_variable_db_detach(default_var_db);
- }
- default_var_db = lp_variable_db_new();
-}
-
-lp_variable_db_t* Variable_get_default_db(void) {
- if (!default_var_db) {
- Variable_init_default_db();
- }
- return default_var_db;
-}
-
-static PyObject*
-Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-Variable_init(Variable* self, PyObject* args);
-
-static void
-Variable_dealloc(Variable* self);
-
-static PyObject*
-Variable_str(PyObject* self);
-
-static int
-Variable_cmp(PyObject* self, PyObject* other);
-
-static PyObject*
-Variable_repr(PyObject* self);
-
-static long
-Variable_hash(PyObject* self);
-
-PyMethodDef Variable_methods[] = {
- {NULL} /* Sentinel */
-};
-
-static PyObject*
-Variable_add(PyObject* self, PyObject* args);
-
-static PyObject*
-Variable_neg(PyObject* self);
-
-static PyObject*
-Variable_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-Variable_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-Variable_pow(PyObject* self, PyObject* args);
-
-PyNumberMethods Variable_NumberMethods = {
- Variable_add, // binaryfunc nb_add;
- Variable_sub, // binaryfunc nb_subtract;
- Variable_mul, // binaryfunc nb_multiply;
- 0, // binaryfunc nb_divide;
- 0, // binaryfunc nb_remainder;
- 0, // binaryfunc nb_divmod;
- (ternaryfunc)Variable_pow, // ternaryfunc nb_power;
- Variable_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- 0, // inquiry nb_nonzero; /* Used by PyObject_IsTrue */
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- 0, // coercion nb_coerce; /* Used by the coerce() function */
- 0, // unaryfunc nb_int;
- 0, // unaryfunc nb_long;
- 0, // unaryfunc nb_float;
- 0, // unaryfunc nb_oct;
- 0, // unaryfunc nb_hex;
-
- /* Added in release 2.0 */
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_divide;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
-
- /* Added in release 2.2 */
- 0, // binaryfunc nb_floor_divide;
- 0, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
-
- /* Added in release 2.5 */
- 0 // unaryfunc nb_index;
-};
-
-PyTypeObject VariableType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.Variable", /*tp_name*/
- sizeof(Variable), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)Variable_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- Variable_cmp, /*tp_compare*/
- Variable_repr, /*tp_repr*/
- &Variable_NumberMethods, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- Variable_hash, /*tp_hash */
- 0, /*tp_call*/
- Variable_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "Variable objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- Variable_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)Variable_init, /* tp_init */
- 0, /* tp_alloc */
- Variable_new, /* tp_new */
-};
-
-PyObject*
-PyVariable_create(lp_variable_t x) {
- Variable *self;
- self = (Variable*)VariableType.tp_alloc(&VariableType, 0);
- if (self != NULL) {
- self->x = x;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyVariable_create(0);
-}
-
-static int
-Variable_init(Variable* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* obj = PyTuple_GetItem(args, 0);
- if (PyString_Check(obj)) {
- const char* c_str = PyString_AsString(obj);
- lp_variable_t x = lp_variable_db_new_variable(Variable_get_default_db(), c_str);
- self->x = x;
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- return 0;
-}
-
-static void
-Variable_dealloc(Variable* self)
-{
- self->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject* Variable_str(PyObject* self) {
- Variable* x = (Variable*) self;
- const char* x_str = lp_variable_db_get_name(Variable_get_default_db(), x->x);
- PyObject* str = PyString_FromString(x_str);
- return str;
-}
-
-static int Variable_cmp(PyObject* self, PyObject* other) {
- Variable* x = (Variable*) self;
- if (PyVariable_CHECK(other)) {
- Variable* y = (Variable*) other;
- if (x->x > y->x) {
- return 1;
- } else if (x->x == y->x) {
- return 0;
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-}
-
-
-static PyObject* Variable_repr(PyObject* self) {
- Variable* x = (Variable*) self;
- const char* x_str = lp_variable_db_get_name(Variable_get_default_db(), x->x);
- char* x_repr = malloc(strlen(x_str) + strlen(VariableType.tp_name) + 5);
- sprintf(x_repr, "%s('%s')", VariableType.tp_name, x_str);
- PyObject* str = PyString_FromString(x_repr);
- free(x_repr);
- return str;
-}
-
-static long Variable_hash(PyObject* self) {
- Variable* x = (Variable*) self;
- return x->x;
-}
-
-static
-lp_polynomial_t* PyLong_Or_Int_to_polynomial(PyObject* number) {
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
- lp_integer_t c;
- PyLong_or_Int_to_integer(number, 0, &c);
- lp_polynomial_t* p_c = lp_polynomial_alloc();
- lp_polynomial_construct_simple(p_c, ctx, &c, 0, 0);
- lp_integer_destruct(&c);
- return p_c;
-}
-
-static
-lp_polynomial_t* Variable_to_polynomial(PyObject* var) {
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
- Variable* x = (Variable*) var;
- lp_integer_t one;
- lp_integer_construct_from_int(lp_Z, &one, 1);
- lp_polynomial_t* p_x = lp_polynomial_alloc();
- lp_polynomial_construct_simple(p_x, ctx, &one, x->x, 1);
- lp_integer_destruct(&one);
- return p_x;
-}
-
-static PyObject*
-Variable_add_number(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_c = PyLong_Or_Int_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_sum = lp_polynomial_new(ctx);
- lp_polynomial_add(p_sum, p_x, p_c);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_c);
- free(p_x);
- free(p_c);
-
- return Polynomial_create(p_sum);
-}
-
-static PyObject*
-Variable_add_Variable(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_y = Variable_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_sum = lp_polynomial_new(ctx);
- lp_polynomial_add(p_sum, p_x, p_y);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_y);
- free(p_x);
- free(p_y);
-
- return Polynomial_create(p_sum);
-}
-
-static PyObject*
-Variable_add(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return Variable_add_number(self, other);
- } else if (PyLong_or_Int_Check(self)) {
- return Variable_add_number(other, self);
- } else if (PyVariable_CHECK(other)) {
- return Variable_add_Variable(self, other);
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static PyObject*
-Variable_neg(PyObject* self) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
-
- // -x polynomial
- lp_polynomial_t* p_neg = lp_polynomial_new(ctx);
- lp_polynomial_neg(p_neg, p_x);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- free(p_x);
-
- return Polynomial_create(p_neg);
-}
-
-static PyObject*
-Variable_sub_number(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_c = PyLong_Or_Int_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_sub = lp_polynomial_new(ctx);
- lp_polynomial_sub(p_sub, p_x, p_c);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_c);
- free(p_x);
- free(p_c);
-
- return Polynomial_create(p_sub);
-}
-
-static PyObject*
-Variable_sub_Variable(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_y = Variable_to_polynomial(other);
-
- // x - y polynomial
- lp_polynomial_t* p_sub = lp_polynomial_new(ctx);
- lp_polynomial_sub(p_sub, p_x, p_y);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_y);
- free(p_x);
- free(p_y);
-
- return Polynomial_create(p_sub);
-}
-
-static PyObject*
-Variable_sub(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return Variable_sub_number(self, other);
- } else if (PyLong_or_Int_Check(self)) {
- Polynomial* result = (Polynomial*) Variable_sub_number(other, self);
- lp_polynomial_neg(result->p, result->p);
- return (PyObject*) result;
- } else if (PyVariable_CHECK(other)) {
- return Variable_sub_Variable(self, other);
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static PyObject*
-Variable_mul_number(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_c = PyLong_Or_Int_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_mul = lp_polynomial_new(ctx);
- lp_polynomial_mul(p_mul, p_x, p_c);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_c);
- free(p_x);
- free(p_c);
-
- return Polynomial_create(p_mul);
-}
-
-static PyObject*
-Variable_mul_Variable(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_y = Variable_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_mul = lp_polynomial_new(ctx);
- lp_polynomial_mul(p_mul, p_x, p_y);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_y);
- free(p_x);
- free(p_y);
-
- return Polynomial_create(p_mul);
-}
-
-static PyObject*
-Variable_mul(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return Variable_mul_number(self, other);
- } else if (PyLong_or_Int_Check(self)) {
- return Variable_mul_number(other, self);
- } else if (PyVariable_CHECK(other)) {
- return Variable_mul_Variable(other, self);
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static PyObject*
-Variable_pow(PyObject* self, PyObject* other) {
- // Check arguments
- if (!PyVariable_CHECK(self) || !PyInt_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- } else {
- long n = PyInt_AsLong(other);
- if (n < 0) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- } else {
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
- Variable* var = (Variable*) self;
- lp_integer_t one;
- lp_integer_construct_from_int(lp_Z, &one, 1);
- lp_polynomial_t* pow_x = lp_polynomial_alloc();
- lp_polynomial_construct_simple(pow_x, ctx, &one, var->x, n);
- lp_integer_destruct(&one);
- return Polynomial_create(pow_x);
- }
- }
-}
diff --git a/python/polypyVariable3.c b/python/polypyVariable3.c
deleted file mode 100644
index 4d49e967..00000000
--- a/python/polypyVariable3.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/**
- * 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 "polypyVariable.h"
-#include "polypyInteger.h"
-#include "polypyPolynomial.h"
-#include "utils.h"
-
-#include
-
-/** Default variable database */
-static lp_variable_db_t* default_var_db = 0;
-
-void Variable_init_default_db(void) {
- if (default_var_db) {
- lp_variable_db_detach(default_var_db);
- }
- default_var_db = lp_variable_db_new();
-}
-
-lp_variable_db_t* Variable_get_default_db(void) {
- if (!default_var_db) {
- Variable_init_default_db();
- }
- return default_var_db;
-}
-
-static PyObject*
-Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-Variable_init(Variable* self, PyObject* args);
-
-static void
-Variable_dealloc(Variable* self);
-
-static PyObject*
-Variable_str(PyObject* self);
-
-static PyObject*
-Variable_repr(PyObject* self);
-
-static Py_hash_t
-Variable_hash(PyObject* self);
-
-static PyObject *
-Variable_richcompare(PyObject *self, PyObject *other, int op);
-
-PyMethodDef Variable_methods[] = {
- {NULL} /* Sentinel */
-};
-
-static PyObject*
-Variable_add(PyObject* self, PyObject* args);
-
-static PyObject*
-Variable_neg(PyObject* self);
-
-static PyObject*
-Variable_sub(PyObject* self, PyObject* args);
-
-static PyObject*
-Variable_mul(PyObject* self, PyObject* args);
-
-static PyObject*
-Variable_pow(PyObject* self, PyObject* args);
-
-PyNumberMethods Variable_NumberMethods = {
- Variable_add, // binaryfunc nb_add;
- Variable_sub, // binaryfunc nb_subtract;
- Variable_mul, // binaryfunc nb_multiply;
- 0, // binaryfunc nb_remainder;
- 0, // binaryfunc nb_divmod;
- (ternaryfunc)Variable_pow, // ternaryfunc nb_power;
- Variable_neg, // unaryfunc nb_negative;
- 0, // unaryfunc nb_positive;
- 0, // unaryfunc nb_absolute;
- 0, // inquiry nb_bool;
- 0, // unaryfunc nb_invert;
- 0, // binaryfunc nb_lshift;
- 0, // binaryfunc nb_rshift;
- 0, // binaryfunc nb_and;
- 0, // binaryfunc nb_xor;
- 0, // binaryfunc nb_or;
- 0, // unaryfunc nb_int;
- 0, // void *nb_reserved;
- 0, // unaryfunc nb_float;
- 0, // binaryfunc nb_inplace_add;
- 0, // binaryfunc nb_inplace_subtract;
- 0, // binaryfunc nb_inplace_multiply;
- 0, // binaryfunc nb_inplace_remainder;
- 0, // ternaryfunc nb_inplace_power;
- 0, // binaryfunc nb_inplace_lshift;
- 0, // binaryfunc nb_inplace_rshift;
- 0, // binaryfunc nb_inplace_and;
- 0, // binaryfunc nb_inplace_xor;
- 0, // binaryfunc nb_inplace_or;
- 0, // binaryfunc nb_floor_divide;
- 0, // binaryfunc nb_true_divide;
- 0, // binaryfunc nb_inplace_floor_divide;
- 0, // binaryfunc nb_inplace_true_divide;
- 0, // unaryfunc nb_index;
- 0, // binaryfunc nb_matrix_multiply;
- 0, // binaryfunc nb_inplace_matrix_multiply;
-};
-
-PyTypeObject VariableType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.Variable", // const char *tp_name;
- sizeof(Variable), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)Variable_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async;
- Variable_repr, // reprfunc tp_repr;
- &Variable_NumberMethods, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- Variable_hash, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- Variable_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "Variable objects", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- Variable_richcompare, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- Variable_methods, // struct PyMethodDef *tp_methods;
- 0, // istruct PyMemberDef *tp_members;
- 0, // istruct PyGetSetDef *tp_getset;
- 0, // istruct _typeobject *tp_base;
- 0, // iPyObject *tp_dict;
- 0, // idescrgetfunc tp_descr_get;
- 0, // idescrsetfunc tp_descr_set;
- 0, // iPy_ssize_t tp_dictoffset;
- (initproc)Variable_init, // initproc tp_init;
- 0, // allocfunc tp_alloc;
- Variable_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-PyObject*
-PyVariable_create(lp_variable_t x) {
- Variable *self;
- self = (Variable*)VariableType.tp_alloc(&VariableType, 0);
- if (self != NULL) {
- self->x = x;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-Variable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return PyVariable_create(0);
-}
-
-static int
-Variable_init(Variable* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* obj = PyTuple_GetItem(args, 0);
- if (PyUnicode_Check(obj) || PyBytes_Check(obj)) {
- const char* c_str = pythonObject2CharStar(obj);
- lp_variable_t x = lp_variable_db_new_variable(Variable_get_default_db(), c_str);
- self->x = x;
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- return 0;
-}
-
-static void
-Variable_dealloc(Variable* self)
-{
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject* Variable_str(PyObject* self) {
- Variable* x = (Variable*) self;
- const char* x_str = lp_variable_db_get_name(Variable_get_default_db(), x->x);
- PyObject* str = PyUnicode_FromString(x_str);
- return str;
-}
-
-static PyObject* Variable_repr(PyObject* self) {
- Variable* x = (Variable*) self;
- const char* x_str = lp_variable_db_get_name(Variable_get_default_db(), x->x);
- char* x_repr = malloc(strlen(x_str) + strlen(VariableType.tp_name) + 5);
- sprintf(x_repr, "%s('%s')", VariableType.tp_name, x_str);
- PyObject* str = PyUnicode_FromString(x_repr);
- free(x_repr);
- return str;
-}
-
-static Py_hash_t Variable_hash(PyObject* self) {
- Variable* x = (Variable*) self;
- return x->x;
-}
-
-static
-lp_polynomial_t* PyLong_Or_Int_to_polynomial(PyObject* number) {
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
- lp_integer_t c;
- PyLong_or_Int_to_integer(number, 0, &c);
- lp_polynomial_t* p_c = lp_polynomial_alloc();
- lp_polynomial_construct_simple(p_c, ctx, &c, 0, 0);
- lp_integer_destruct(&c);
- return p_c;
-}
-
-static
-lp_polynomial_t* Variable_to_polynomial(PyObject* var) {
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
- Variable* x = (Variable*) var;
- lp_integer_t one;
- lp_integer_construct_from_int(lp_Z, &one, 1);
- lp_polynomial_t* p_x = lp_polynomial_alloc();
- lp_polynomial_construct_simple(p_x, ctx, &one, x->x, 1);
- lp_integer_destruct(&one);
- return p_x;
-}
-
-static PyObject*
-Variable_add_number(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_c = PyLong_Or_Int_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_sum = lp_polynomial_new(ctx);
- lp_polynomial_add(p_sum, p_x, p_c);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_c);
- free(p_x);
- free(p_c);
-
- return Polynomial_create(p_sum);
-}
-
-static PyObject*
-Variable_add_Variable(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_y = Variable_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_sum = lp_polynomial_new(ctx);
- lp_polynomial_add(p_sum, p_x, p_y);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_y);
- free(p_x);
- free(p_y);
-
- return Polynomial_create(p_sum);
-}
-
-static PyObject*
-Variable_add(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return Variable_add_number(self, other);
- } else if (PyLong_or_Int_Check(self)) {
- return Variable_add_number(other, self);
- } else if (PyVariable_CHECK(other)) {
- return Variable_add_Variable(self, other);
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static PyObject*
-Variable_neg(PyObject* self) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
-
- // -x polynomial
- lp_polynomial_t* p_neg = lp_polynomial_new(ctx);
- lp_polynomial_neg(p_neg, p_x);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- free(p_x);
-
- return Polynomial_create(p_neg);
-}
-
-static PyObject*
-Variable_sub_number(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_c = PyLong_Or_Int_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_sub = lp_polynomial_new(ctx);
- lp_polynomial_sub(p_sub, p_x, p_c);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_c);
- free(p_x);
- free(p_c);
-
- return Polynomial_create(p_sub);
-}
-
-static PyObject*
-Variable_sub_Variable(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_y = Variable_to_polynomial(other);
-
- // x - y polynomial
- lp_polynomial_t* p_sub = lp_polynomial_new(ctx);
- lp_polynomial_sub(p_sub, p_x, p_y);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_y);
- free(p_x);
- free(p_y);
-
- return Polynomial_create(p_sub);
-}
-
-static PyObject*
-Variable_sub(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return Variable_sub_number(self, other);
- } else if (PyLong_or_Int_Check(self)) {
- Polynomial* result = (Polynomial*) Variable_sub_number(other, self);
- lp_polynomial_neg(result->p, result->p);
- return (PyObject*) result;
- } else if (PyVariable_CHECK(other)) {
- return Variable_sub_Variable(self, other);
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static PyObject*
-Variable_mul_number(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_c = PyLong_Or_Int_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_mul = lp_polynomial_new(ctx);
- lp_polynomial_mul(p_mul, p_x, p_c);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_c);
- free(p_x);
- free(p_c);
-
- return Polynomial_create(p_mul);
-}
-
-static PyObject*
-Variable_mul_Variable(PyObject* self, PyObject* other) {
-
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
-
- // The x polynomial
- lp_polynomial_t* p_x = Variable_to_polynomial(self);
- // The c polynomial
- lp_polynomial_t* p_y = Variable_to_polynomial(other);
-
- // x + c polynomial
- lp_polynomial_t* p_mul = lp_polynomial_new(ctx);
- lp_polynomial_mul(p_mul, p_x, p_y);
-
- // Remove temporaries
- lp_polynomial_destruct(p_x);
- lp_polynomial_destruct(p_y);
- free(p_x);
- free(p_y);
-
- return Polynomial_create(p_mul);
-}
-
-static PyObject*
-Variable_mul(PyObject* self, PyObject* other) {
- // Integer addition
- if (PyLong_or_Int_Check(other)) {
- return Variable_mul_number(self, other);
- } else if (PyLong_or_Int_Check(self)) {
- return Variable_mul_number(other, self);
- } else if (PyVariable_CHECK(other)) {
- return Variable_mul_Variable(other, self);
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-}
-
-static PyObject*
-Variable_pow(PyObject* self, PyObject* other) {
- // Check arguments
- if (!PyVariable_CHECK(self) || !PyLong_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- } else {
- long n = PyLong_AsLong(other);
- if (n < 0) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- } else {
- const lp_polynomial_context_t* ctx = Polynomial_get_default_context();
- Variable* var = (Variable*) self;
- lp_integer_t one;
- lp_integer_construct_from_int(lp_Z, &one, 1);
- lp_polynomial_t* pow_x = lp_polynomial_alloc();
- lp_polynomial_construct_simple(pow_x, ctx, &one, var->x, n);
- lp_integer_destruct(&one);
- return Polynomial_create(pow_x);
- }
- }
-}
-
-static PyObject *
-Variable_richcompare(PyObject *self, PyObject *other, int op){
- PyObject *result = Py_NotImplemented;
-
- if (!PyVariable_CHECK(other)) {
- if(op == Py_EQ){ return Py_False; }
- if(op == Py_NE){ return Py_True; }
- } else {
- Variable* x = (Variable*) self;
- Variable* y = (Variable*) other;
-
- switch (op) {
- case Py_LT:
- result = (x->x < y->x ? Py_True : Py_False);
- break;
- case Py_LE:
- result = (x->x <= y->x ? Py_True : Py_False);
- break;
- case Py_EQ:
- result = (x->x == y->x ? Py_True : Py_False);
- break;
- case Py_NE:
- result = (x->x != y->x ? Py_True : Py_False);
- break;
- case Py_GT:
- result = (x->x > y->x ? Py_True : Py_False);
- break;
- case Py_GE:
- result = (x->x >= y->x ? Py_True : Py_False);
- break;
- }
- }
- return result;
-}
-
diff --git a/python/polypyVariableOrder.c b/python/polypyVariableOrder.c
index fd0b4eff..11f75741 100644
--- a/python/polypyVariableOrder.c
+++ b/python/polypyVariableOrder.c
@@ -17,12 +17,265 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
-#if PY_MAJOR_VERSION >= 3
-#include "polypyVariableOrder3.c"
-#else
-#include "polypyVariableOrder2.c"
-#endif
+#include "polypyVariableOrder.h"
+#include "polypyVariable.h"
+#include
+#include
+
+/** Default variable database */
+static lp_variable_order_t* default_var_order = NULL;
+
+lp_variable_order_t* VariableOrder_get_default_order(void) {
+ if (!default_var_order) {
+ default_var_order = lp_variable_order_new();
+ }
+ return default_var_order;
+}
+
+static PyObject*
+VariableOrder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+static int
+VariableOrder_init(VariableOrder* self, PyObject* args);
+
+static void
+VariableOrder_dealloc(VariableOrder* self);
+
+static PyObject*
+VariableOrder_str(PyObject* self);
+
+static PyObject*
+VariableOrder_repr(PyObject* self);
+
+static PyObject*
+VariableOrder_push(PyObject* self, PyObject* args);
+
+static PyObject*
+VariableOrder_pop(PyObject* self);
+
+static PyObject*
+VariableOrder_set(PyObject* self, PyObject* args);
+
+static PyObject*
+VariableOrder_cmp(PyObject* self, PyObject* args);
+
+PyMethodDef VariableOrder_methods[] = {
+ {"push", (PyCFunction)VariableOrder_push, METH_VARARGS, "Add a variable to the top of the order"},
+ {"pop", (PyCFunction)VariableOrder_pop, METH_NOARGS, "Remove the top variable from the order"},
+ {"cmp", (PyCFunction)VariableOrder_cmp, METH_VARARGS, "Compare two variables"},
+ {"set", (PyCFunction)VariableOrder_set, METH_VARARGS, "Set the order to the given list of variables"},
+ {NULL} /* Sentinel */
+};
+
+PyTypeObject VariableOrderType = {
+ {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
+ "polypy.VariableOrder", // const char *tp_name;
+ sizeof(VariableOrder), // Py_ssize_t tp_basicsize;
+ 0, // Py_ssize_t tp_itemsize;
+ (destructor)VariableOrder_dealloc, // destructor tp_dealloc;
+ 0, // printfunc tp_print;
+ NULL, // getattrfunc tp_getattr;
+ NULL, // setattrfunc tp_setattr;
+ NULL, // PyAsyncMethods *tp_as_async;
+ VariableOrder_repr, // reprfunc tp_repr;
+ NULL, // PyNumberMethods *tp_as_number;
+ NULL, // PySequenceMethods *tp_as_sequence;
+ NULL, // PyMappingMethods *tp_as_mapping;
+ NULL, // hashfunc tp_hash;
+ NULL, // ternaryfunc tp_call;
+ VariableOrder_str, // reprfunc tp_str;
+ NULL, // getattrofunc tp_getattro;
+ NULL, // setattrofunc tp_setattro;
+ NULL, // PyBufferProcs *tp_as_buffer;
+ Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
+ "VariableOrder objects", // const char *tp_doc;
+ NULL, // traverseproc tp_traverse;
+ NULL, // inquiry tp_clear;
+ NULL, // richcmpfunc tp_richcompare;
+ 0, // Py_ssize_t tp_weaklistoffset;
+ NULL, // getiterfunc tp_iter;
+ NULL, // iternextfunc tp_iternext;
+ VariableOrder_methods, // struct PyMethodDef *tp_methods;
+ NULL, // struct PyMemberDef *tp_members;
+ NULL, // struct PyGetSetDef *tp_getset;
+ NULL, // struct _typeobject *tp_base;
+ NULL, // PyObject *tp_dict;
+ NULL, // descrgetfunc tp_descr_get;
+ NULL, // descrsetfunc tp_descr_set;
+ 0, // Py_ssize_t tp_dictoffset;
+ (initproc)VariableOrder_init, // initproc tp_init;
+ NULL, // allocfunc tp_alloc;
+ VariableOrder_new, // newfunc tp_new;
+ NULL, // freefunc tp_free;
+ NULL, // inquiry tp_is_gc;
+ NULL, // PyObject *tp_bases;
+ NULL, // PyObject *tp_mro;
+ NULL, // PyObject *tp_cache;
+ NULL, // PyObject *tp_subclasses;
+ NULL, // PyObject *tp_weaklist;
+ NULL, // destructor tp_del;
+ 0, // unsigned int tp_version_tag;
+ NULL, // destructor tp_finalize;
+};
+
+PyObject*
+VariableOrder_create(lp_variable_order_t* var_order) {
+ VariableOrder *self = (VariableOrder*)VariableOrderType.tp_alloc(&VariableOrderType, 0);
+ if (self != NULL) {
+ self->var_order = var_order;
+ }
+ return (PyObject *)self;
+}
+
+static PyObject*
+VariableOrder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return VariableOrder_create(NULL);
+}
+
+static PyObject*
+VariableOrder_set(PyObject* self, PyObject* args) {
+
+ VariableOrder* order = (VariableOrder*) self;
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
+ PyObject* list = PyTuple_GetItem(args, 0);
+ if (PyList_Check(list)) {
+ int i;
+ for (i = 0; i < PyList_Size(list); ++ i) {
+ if (!PyVariable_CHECK(PyList_GetItem(list, i))) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ }
+ // Clear the current order
+ lp_variable_order_clear(order->var_order);
+ // Fill the order
+ for (i = 0; i < PyList_Size(list); ++ i) {
+ lp_variable_t var = ((Variable*) PyList_GetItem(list, i))->x;
+ if (!lp_variable_order_contains(order->var_order, var)) {
+ lp_variable_order_push(order->var_order, var);
+ }
+ }
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ } else {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static int
+VariableOrder_init(VariableOrder* self, PyObject* args)
+{
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
+ PyObject* list = PyTuple_GetItem(args, 0);
+ if (PyList_Check(list)) {
+ int i;
+ for (i = 0; i < PyList_Size(list); ++ i) {
+ if (!PyVariable_CHECK(PyList_GetItem(list, i))) {
+ return -1;
+ }
+ }
+ self->var_order = lp_variable_order_new();
+ for (i = 0; i < PyList_Size(list); ++ i) {
+ lp_variable_t var = ((Variable*) PyList_GetItem(list, i))->x;
+ lp_variable_order_push(self->var_order, var);
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static void
+VariableOrder_dealloc(VariableOrder* self)
+{
+ if (self->var_order) {
+ lp_variable_order_detach(self->var_order);
+ }
+ ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+}
+
+static PyObject*
+VariableOrder_str(PyObject* self) {
+ VariableOrder* var_order = (VariableOrder*) self;
+ char* var_order_str = lp_variable_order_to_string(var_order->var_order, Variable_get_default_db());
+ PyObject* str = PyUnicode_FromString(var_order_str);
+ free(var_order_str);
+ return str;
+}
+
+static PyObject*
+VariableOrder_repr(PyObject* self) {
+ VariableOrder* var_order = (VariableOrder*) self;
+ char* var_order_str = lp_variable_order_to_string(var_order->var_order, Variable_get_default_db());
+ char* var_order_repr = malloc(strlen(var_order_str) + strlen(VariableOrderType.tp_name) + 3);
+ sprintf(var_order_repr, "%s(%s)", VariableOrderType.tp_name, var_order_str);
+ PyObject* str = PyUnicode_FromString(var_order_repr);
+ free(var_order_repr);
+ free(var_order_str);
+ return str;
+}
+
+static PyObject*
+VariableOrder_push(PyObject* self, PyObject* args) {
+ int error = 0;
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
+ PyObject* variable = PyTuple_GetItem(args, 0);
+ if (PyVariable_CHECK(variable)) {
+ lp_variable_order_t* var_order = ((VariableOrder*) self)->var_order;
+ lp_variable_t x = ((Variable*) variable)->x;
+ if (!lp_variable_order_contains(var_order, x)) {
+ lp_variable_order_push(var_order, x);
+ }
+ } else {
+ error = 1;
+ }
+ } else {
+ error = 1;
+ }
+ if (error) {
+ PyErr_SetString(PyExc_BaseException, "Only variables can be pushed");
+ }
+
+ Py_RETURN_NONE;
+}
+
+
+static PyObject*
+VariableOrder_cmp(PyObject* self, PyObject* args) {
+ if (PyTuple_Check(args) && PyTuple_Size(args) == 2) {
+ PyObject* x_var = PyTuple_GetItem(args, 0);
+ PyObject* y_var = PyTuple_GetItem(args, 1);
+ if (PyVariable_CHECK(x_var) && PyVariable_CHECK(y_var)) {
+ lp_variable_order_t* var_order = ((VariableOrder*) self)->var_order;
+ lp_variable_t x = ((Variable*) x_var)->x;
+ lp_variable_t y = ((Variable*) y_var)->x;
+ int cmp = lp_variable_order_cmp(var_order, x, y);
+ if (cmp < 0) return PyLong_FromLong(-1);
+ else if (cmp > 0) return PyLong_FromLong(1);
+ else return PyLong_FromLong(0);
+ }
+ }
+ PyErr_SetString(PyExc_BaseException, "Only variables can be pushed");
+ Py_RETURN_NONE;
+}
+
+
+static PyObject*
+VariableOrder_pop(PyObject* self) {
+ lp_variable_order_t* var_order = ((VariableOrder*) self)->var_order;
+ if (lp_variable_order_size(var_order) > 0) {
+ lp_variable_order_pop(var_order);
+ }
+ Py_RETURN_NONE;
+}
diff --git a/python/polypyVariableOrder.h b/python/polypyVariableOrder.h
index 8e049c49..f1164256 100644
--- a/python/polypyVariableOrder.h
+++ b/python/polypyVariableOrder.h
@@ -19,8 +19,7 @@
#pragma once
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include
#include
diff --git a/python/polypyVariableOrder2.c b/python/polypyVariableOrder2.c
deleted file mode 100644
index 5f4216ba..00000000
--- a/python/polypyVariableOrder2.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/**
- * 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 "polypyVariableOrder.h"
-#include "polypyVariable.h"
-
-#include
-#include
-
-/** Default variable database */
-static lp_variable_order_t* default_var_order = 0;
-
-lp_variable_order_t* VariableOrder_get_default_order(void) {
- if (!default_var_order) {
- default_var_order = lp_variable_order_new();
- }
- return default_var_order;
-}
-
-static PyObject*
-VariableOrder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-VariableOrder_init(VariableOrder* self, PyObject* args);
-
-static void
-VariableOrder_dealloc(VariableOrder* self);
-
-static PyObject*
-VariableOrder_str(PyObject* self);
-
-static PyObject*
-VariableOrder_repr(PyObject* self);
-
-static PyObject*
-VariableOrder_push(PyObject* self, PyObject* args);
-
-static PyObject*
-VariableOrder_pop(PyObject* self);
-
-static PyObject*
-VariableOrder_set(PyObject* self, PyObject* args);
-
-static PyObject*
-VariableOrder_cmp(PyObject* self, PyObject* args);
-
-PyMethodDef VariableOrder_methods[] = {
- {"push", (PyCFunction)VariableOrder_push, METH_VARARGS, "Add a variable to the top of the order"},
- {"pop", (PyCFunction)VariableOrder_pop, METH_NOARGS, "Remove the top variable from the order"},
- {"cmp", (PyCFunction)VariableOrder_cmp, METH_VARARGS, "Compare two variables"},
- {"set", (PyCFunction)VariableOrder_set, METH_VARARGS, "Set the order to the given list of variables"},
- {NULL} /* Sentinel */
-};
-
-PyTypeObject VariableOrderType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "polypy.VariableOrder", /*tp_name*/
- sizeof(VariableOrder), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)VariableOrder_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- VariableOrder_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- VariableOrder_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
- "VariableOrder objects", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- VariableOrder_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)VariableOrder_init, /* tp_init */
- 0, /* tp_alloc */
- VariableOrder_new, /* tp_new */
-};
-
-PyObject*
-VariableOrder_create(lp_variable_order_t* var_order) {
- VariableOrder *self = (VariableOrder*)VariableOrderType.tp_alloc(&VariableOrderType, 0);
- if (self != NULL) {
- self->var_order = var_order;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-VariableOrder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return VariableOrder_create(0);
-}
-
-static PyObject*
-VariableOrder_set(PyObject* self, PyObject* args) {
-
- VariableOrder* order = (VariableOrder*) self;
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* list = PyTuple_GetItem(args, 0);
- if (PyList_Check(list)) {
- int i;
- for (i = 0; i < PyList_Size(list); ++ i) {
- if (!PyVariable_CHECK(PyList_GetItem(list, i))) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
- // Clear the current order
- lp_variable_order_clear(order->var_order);
- // Fill the order
- for (i = 0; i < PyList_Size(list); ++ i) {
- lp_variable_t var = ((Variable*) PyList_GetItem(list, i))->x;
- if (!lp_variable_order_contains(order->var_order, var)) {
- lp_variable_order_push(order->var_order, var);
- }
- }
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Py_RETURN_NONE;
-}
-
-static int
-VariableOrder_init(VariableOrder* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* list = PyTuple_GetItem(args, 0);
- if (PyList_Check(list)) {
- int i;
- for (i = 0; i < PyList_Size(list); ++ i) {
- if (!PyVariable_CHECK(PyList_GetItem(list, i))) {
- return -1;
- }
- }
- self->var_order = lp_variable_order_new();
- for (i = 0; i < PyList_Size(list); ++ i) {
- lp_variable_t var = ((Variable*) PyList_GetItem(list, i))->x;
- lp_variable_order_push(self->var_order, var);
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- return 0;
-}
-
-static void
-VariableOrder_dealloc(VariableOrder* self)
-{
- if (self->var_order) {
- lp_variable_order_detach(self->var_order);
- }
- self->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject*
-VariableOrder_str(PyObject* self) {
- VariableOrder* var_order = (VariableOrder*) self;
- char* var_order_str = lp_variable_order_to_string(var_order->var_order, Variable_get_default_db());
- PyObject* str = PyString_FromString(var_order_str);
- free(var_order_str);
- return str;
-}
-
-static PyObject*
-VariableOrder_repr(PyObject* self) {
- VariableOrder* var_order = (VariableOrder*) self;
- char* var_order_str = lp_variable_order_to_string(var_order->var_order, Variable_get_default_db());
- char* var_order_repr = malloc(strlen(var_order_str) + strlen(VariableOrderType.tp_name) + 3);
- sprintf(var_order_repr, "%s(%s)", VariableOrderType.tp_name, var_order_str);
- PyObject* str = PyString_FromString(var_order_repr);
- free(var_order_repr);
- free(var_order_str);
- return str;
-}
-
-static PyObject*
-VariableOrder_push(PyObject* self, PyObject* args) {
- int error = 0;
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* variable = PyTuple_GetItem(args, 0);
- if (PyVariable_CHECK(variable)) {
- lp_variable_order_t* var_order = ((VariableOrder*) self)->var_order;
- lp_variable_t x = ((Variable*) variable)->x;
- if (!lp_variable_order_contains(var_order, x)) {
- lp_variable_order_push(var_order, x);
- }
- } else {
- error = 1;
- }
- } else {
- error = 1;
- }
- if (error) {
- PyErr_SetString(PyExc_BaseException, "Only variables can be pushed");
- }
-
- Py_RETURN_NONE;
-}
-
-
-static PyObject*
-VariableOrder_cmp(PyObject* self, PyObject* args) {
- int error = 0;
- if (PyTuple_Check(args) && PyTuple_Size(args) == 2) {
- PyObject* x_var = PyTuple_GetItem(args, 0);
- PyObject* y_var = PyTuple_GetItem(args, 1);
- if (PyVariable_CHECK(x_var) && PyVariable_CHECK(y_var)) {
- lp_variable_order_t* var_order = ((VariableOrder*) self)->var_order;
- lp_variable_t x = ((Variable*) x_var)->x;
- lp_variable_t y = ((Variable*) y_var)->x;
- int cmp = lp_variable_order_cmp(var_order, x, y);
- if (cmp < 0) return PyInt_FromLong(-1);
- else if (cmp > 0) return PyInt_FromLong(1);
- else return PyInt_FromLong(0);
- } else {
- error = 1;
- }
- } else {
- error = 1;
- }
- if (error) {
- PyErr_SetString(PyExc_BaseException, "Only variables can be pushed");
- }
-
- Py_RETURN_NONE;
-}
-
-
-static PyObject*
-VariableOrder_pop(PyObject* self) {
- lp_variable_order_t* var_order = ((VariableOrder*) self)->var_order;
- if (lp_variable_order_size(var_order) > 0) {
- lp_variable_order_pop(var_order);
- }
- Py_RETURN_NONE;
-}
diff --git a/python/polypyVariableOrder3.c b/python/polypyVariableOrder3.c
deleted file mode 100644
index 7818cbd0..00000000
--- a/python/polypyVariableOrder3.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/**
- * 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 "polypyVariableOrder.h"
-#include "polypyVariable.h"
-
-#include
-#include
-
-/** Default variable database */
-static lp_variable_order_t* default_var_order = 0;
-
-lp_variable_order_t* VariableOrder_get_default_order(void) {
- if (!default_var_order) {
- default_var_order = lp_variable_order_new();
- }
- return default_var_order;
-}
-
-static PyObject*
-VariableOrder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static int
-VariableOrder_init(VariableOrder* self, PyObject* args);
-
-static void
-VariableOrder_dealloc(VariableOrder* self);
-
-static PyObject*
-VariableOrder_str(PyObject* self);
-
-static PyObject*
-VariableOrder_repr(PyObject* self);
-
-static PyObject*
-VariableOrder_push(PyObject* self, PyObject* args);
-
-static PyObject*
-VariableOrder_pop(PyObject* self);
-
-static PyObject*
-VariableOrder_set(PyObject* self, PyObject* args);
-
-static PyObject*
-VariableOrder_cmp(PyObject* self, PyObject* args);
-
-PyMethodDef VariableOrder_methods[] = {
- {"push", (PyCFunction)VariableOrder_push, METH_VARARGS, "Add a variable to the top of the order"},
- {"pop", (PyCFunction)VariableOrder_pop, METH_NOARGS, "Remove the top variable from the order"},
- {"cmp", (PyCFunction)VariableOrder_cmp, METH_VARARGS, "Compare two variables"},
- {"set", (PyCFunction)VariableOrder_set, METH_VARARGS, "Set the order to the given list of variables"},
- {NULL} /* Sentinel */
-};
-
-PyTypeObject VariableOrderType = {
- {PyObject_HEAD_INIT(NULL)}, // PyObject_VAR_HEAD
- "polypy.VariableOrder", // const char *tp_name;
- sizeof(VariableOrder), // Py_ssize_t tp_basicsize;
- 0, // Py_ssize_t tp_itemsize;
- (destructor)VariableOrder_dealloc, // destructor tp_dealloc;
- 0, // printfunc tp_print;
- 0, // getattrfunc tp_getattr;
- 0, // setattrfunc tp_setattr;
- 0, // PyAsyncMethods *tp_as_async;
- VariableOrder_repr, // reprfunc tp_repr;
- 0, // PyNumberMethods *tp_as_number;
- 0, // PySequenceMethods *tp_as_sequence;
- 0, // PyMappingMethods *tp_as_mapping;
- 0, // hashfunc tp_hash;
- 0, // ternaryfunc tp_call;
- VariableOrder_str, // reprfunc tp_str;
- 0, // getattrofunc tp_getattro;
- 0, // setattrofunc tp_setattro;
- 0, // PyBufferProcs *tp_as_buffer;
- Py_TPFLAGS_DEFAULT, // unsigned long tp_flags;
- "VariableOrder objects", // const char *tp_doc;
- 0, // traverseproc tp_traverse;
- 0, // inquiry tp_clear;
- 0, // richcmpfunc tp_richcompare;
- 0, // Py_ssize_t tp_weaklistoffset;
- 0, // getiterfunc tp_iter;
- 0, // iternextfunc tp_iternext;
- VariableOrder_methods, // struct PyMethodDef *tp_methods;
- 0, // struct PyMemberDef *tp_members;
- 0, // struct PyGetSetDef *tp_getset;
- 0, // struct _typeobject *tp_base;
- 0, // PyObject *tp_dict;
- 0, // descrgetfunc tp_descr_get;
- 0, // descrsetfunc tp_descr_set;
- 0, // Py_ssize_t tp_dictoffset;
- (initproc)VariableOrder_init, // initproc tp_init;
- 0, // allocfunc tp_alloc;
- VariableOrder_new, // newfunc tp_new;
- 0, // freefunc tp_free;
- 0, // inquiry tp_is_gc;
- 0, // PyObject *tp_bases;
- 0, // PyObject *tp_mro;
- 0, // PyObject *tp_cache;
- 0, // PyObject *tp_subclasses;
- 0, // PyObject *tp_weaklist;
- 0, // destructor tp_del;
- 0, // unsigned int tp_version_tag;
- 0, // destructor tp_finalize;
-};
-
-PyObject*
-VariableOrder_create(lp_variable_order_t* var_order) {
- VariableOrder *self = (VariableOrder*)VariableOrderType.tp_alloc(&VariableOrderType, 0);
- if (self != NULL) {
- self->var_order = var_order;
- }
- return (PyObject *)self;
-}
-
-static PyObject*
-VariableOrder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- return VariableOrder_create(0);
-}
-
-static PyObject*
-VariableOrder_set(PyObject* self, PyObject* args) {
-
- VariableOrder* order = (VariableOrder*) self;
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* list = PyTuple_GetItem(args, 0);
- if (PyList_Check(list)) {
- int i;
- for (i = 0; i < PyList_Size(list); ++ i) {
- if (!PyVariable_CHECK(PyList_GetItem(list, i))) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- }
- // Clear the current order
- lp_variable_order_clear(order->var_order);
- // Fill the order
- for (i = 0; i < PyList_Size(list); ++ i) {
- lp_variable_t var = ((Variable*) PyList_GetItem(list, i))->x;
- if (!lp_variable_order_contains(order->var_order, var)) {
- lp_variable_order_push(order->var_order, var);
- }
- }
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- } else {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- Py_RETURN_NONE;
-}
-
-static int
-VariableOrder_init(VariableOrder* self, PyObject* args)
-{
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* list = PyTuple_GetItem(args, 0);
- if (PyList_Check(list)) {
- int i;
- for (i = 0; i < PyList_Size(list); ++ i) {
- if (!PyVariable_CHECK(PyList_GetItem(list, i))) {
- return -1;
- }
- }
- self->var_order = lp_variable_order_new();
- for (i = 0; i < PyList_Size(list); ++ i) {
- lp_variable_t var = ((Variable*) PyList_GetItem(list, i))->x;
- lp_variable_order_push(self->var_order, var);
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- return 0;
-}
-
-static void
-VariableOrder_dealloc(VariableOrder* self)
-{
- if (self->var_order) {
- lp_variable_order_detach(self->var_order);
- }
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject*
-VariableOrder_str(PyObject* self) {
- VariableOrder* var_order = (VariableOrder*) self;
- char* var_order_str = lp_variable_order_to_string(var_order->var_order, Variable_get_default_db());
- PyObject* str = PyUnicode_FromString(var_order_str);
- free(var_order_str);
- return str;
-}
-
-static PyObject*
-VariableOrder_repr(PyObject* self) {
- VariableOrder* var_order = (VariableOrder*) self;
- char* var_order_str = lp_variable_order_to_string(var_order->var_order, Variable_get_default_db());
- char* var_order_repr = malloc(strlen(var_order_str) + strlen(VariableOrderType.tp_name) + 3);
- sprintf(var_order_repr, "%s(%s)", VariableOrderType.tp_name, var_order_str);
- PyObject* str = PyUnicode_FromString(var_order_repr);
- free(var_order_repr);
- free(var_order_str);
- return str;
-}
-
-static PyObject*
-VariableOrder_push(PyObject* self, PyObject* args) {
- int error = 0;
- if (PyTuple_Check(args) && PyTuple_Size(args) == 1) {
- PyObject* variable = PyTuple_GetItem(args, 0);
- if (PyVariable_CHECK(variable)) {
- lp_variable_order_t* var_order = ((VariableOrder*) self)->var_order;
- lp_variable_t x = ((Variable*) variable)->x;
- if (!lp_variable_order_contains(var_order, x)) {
- lp_variable_order_push(var_order, x);
- }
- } else {
- error = 1;
- }
- } else {
- error = 1;
- }
- if (error) {
- PyErr_SetString(PyExc_BaseException, "Only variables can be pushed");
- }
-
- Py_RETURN_NONE;
-}
-
-
-static PyObject*
-VariableOrder_cmp(PyObject* self, PyObject* args) {
- int error = 0;
- if (PyTuple_Check(args) && PyTuple_Size(args) == 2) {
- PyObject* x_var = PyTuple_GetItem(args, 0);
- PyObject* y_var = PyTuple_GetItem(args, 1);
- if (PyVariable_CHECK(x_var) && PyVariable_CHECK(y_var)) {
- lp_variable_order_t* var_order = ((VariableOrder*) self)->var_order;
- lp_variable_t x = ((Variable*) x_var)->x;
- lp_variable_t y = ((Variable*) y_var)->x;
- int cmp = lp_variable_order_cmp(var_order, x, y);
- if (cmp < 0) return PyLong_FromLong(-1);
- else if (cmp > 0) return PyLong_FromLong(1);
- else return PyLong_FromLong(0);
- } else {
- error = 1;
- }
- } else {
- error = 1;
- }
- if (error) {
- PyErr_SetString(PyExc_BaseException, "Only variables can be pushed");
- }
-
- Py_RETURN_NONE;
-}
-
-
-static PyObject*
-VariableOrder_pop(PyObject* self) {
- lp_variable_order_t* var_order = ((VariableOrder*) self)->var_order;
- if (lp_variable_order_size(var_order) > 0) {
- lp_variable_order_pop(var_order);
- }
- Py_RETURN_NONE;
-}
diff --git a/python/python.h b/python/python.h
new file mode 100644
index 00000000..cb09fcf2
--- /dev/null
+++ b/python/python.h
@@ -0,0 +1,26 @@
+/**
+* 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
+
+/** use this file to include Python.h to ensure that required defines
+ * are present. */
+
+#define PY_SSIZE_T_CLEAN
+#include
diff --git a/python/utils.c b/python/utils.c
index 7e395e4b..cc7c79c4 100644
--- a/python/utils.c
+++ b/python/utils.c
@@ -17,11 +17,100 @@
* along with LibPoly. If not, see .
*/
-#define PY_SSIZE_T_CLEAN
-#include "Python.h"
-
-#if PY_MAJOR_VERSION >= 3
-#include "utils3.c"
-#else
-#include "utils2.c"
-#endif
+#include "python.h"
+
+#include "utils.h"
+
+const char* pythonObject2CharStar(PyObject *pyobj){
+ const char* retval = NULL;
+ if(!pyobj){
+ return retval;
+ } else if(PyBytes_Check(pyobj)){
+ retval = PyBytes_AsString(pyobj);
+ return retval;
+ } else if(PyUnicode_Check(pyobj)) {
+ PyObject* str = PyUnicode_AsEncodedString(pyobj, "utf-8", "?");
+ retval = PyBytes_AS_STRING(str);
+ Py_XDECREF(str);
+ } else {
+ PyObject* pyob_str = PyObject_Str(pyobj);
+ PyObject* str = PyUnicode_AsEncodedString(pyob_str, "utf-8", "?");
+ retval = PyBytes_AS_STRING(str);
+ Py_XDECREF(pyob_str);
+ Py_XDECREF(str);
+ }
+ return retval;
+}
+
+int PyLong_or_Int_Check(PyObject* o) {
+ if (PyLong_Check(o)) {
+ return 1;
+ }
+ return 0;
+}
+
+void PyLong_or_Int_to_integer(PyObject* o, const lp_int_ring_t* K, lp_integer_t* c) {
+ if (PyLong_Check(o)) {
+ long c_long = PyLong_AsLong(o);
+ lp_integer_construct_from_int(K, c, c_long);
+ }
+}
+
+//IAM: unused in the python3 world
+PyObject* integer_to_PyInt(const lp_integer_t* x) {
+ char* str = lp_integer_to_string(x);
+ char* str_p = NULL;
+ PyObject* result = PyLong_FromString(str, &str_p, 10);
+ free(str);
+ return result;
+}
+
+PyObject* integer_to_PyLong(const lp_integer_t* x) {
+ char* str = lp_integer_to_string(x);
+ char* str_p = NULL;
+ PyObject* result = PyLong_FromString(str, &str_p, 10);
+ free(str);
+ return result;
+}
+
+void PyFloat_to_dyadic_rational(PyObject* o, lp_dyadic_rational_t* x) {
+ double o_double = PyFloat_AsDouble(o);
+ lp_dyadic_rational_construct_from_double(x, o_double);
+}
+
+PyObject* dyadic_rational_to_PyFloat(const lp_dyadic_rational_t* x) {
+ double x_double = lp_dyadic_rational_to_double(x);
+ return PyFloat_FromDouble(x_double);
+}
+
+
+PyObject* algebraic_number_to_PyFloat(const lp_algebraic_number_t* x) {
+ double x_double = lp_algebraic_number_to_double(x);
+ return PyFloat_FromDouble(x_double);
+}
+
+int PyLong_or_Int_or_Float_Check(PyObject* o) {
+ if (PyLong_Check(o)) {
+ return 1;
+ }
+ if (PyFloat_Check(o)) {
+ return 1;
+ }
+ return 0;
+}
+
+void PyLong_or_Int_or_float_to_value(PyObject* o, lp_value_t* v) {
+ if (PyLong_or_Int_Check(o)) {
+ lp_integer_t v_int;
+ PyLong_or_Int_to_integer(o, lp_Z, &v_int);
+ lp_value_construct(v, LP_VALUE_INTEGER, &v_int);
+ lp_integer_destruct(&v_int);
+ } else if (PyFloat_Check(o)) {
+ lp_dyadic_rational_t v_dy_q;
+ PyFloat_to_dyadic_rational(o, &v_dy_q);
+ lp_value_construct(v, LP_VALUE_INTEGER, &v_dy_q);
+ lp_dyadic_rational_destruct(&v_dy_q);
+ } else {
+ lp_value_construct(v, LP_VALUE_NONE, NULL);
+ }
+}
diff --git a/python/utils.h b/python/utils.h
index 69d6b083..080dbae0 100644
--- a/python/utils.h
+++ b/python/utils.h
@@ -19,8 +19,7 @@
#pragma once
-#define PY_SSIZE_T_CLEAN
-#include
+#include "python.h"
#include "integer.h"
#include "rational.h"
diff --git a/python/utils2.c b/python/utils2.c
deleted file mode 100644
index 5874fc2e..00000000
--- a/python/utils2.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * 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 "utils.h"
-
-const char* pythonObject2CharStar(PyObject *pyobj){
- const char* retval = NULL;
- if(!pyobj){
- return retval;
- } else if(PyString_Check(pyobj)){
- retval = PyString_AsString(pyobj);
- return retval;
- } else {
- PyObject* pyobj_str = PyObject_Str(pyobj);
- retval = PyString_AsString(pyobj_str);
- }
- return retval;
-}
-
-int PyLong_or_Int_Check(PyObject* o) {
- if (PyInt_Check(o)) {
- return 1;
- }
- if (PyLong_Check(o)) {
- return 1;
- }
- return 0;
-}
-
-void PyLong_or_Int_to_integer(PyObject* o, const lp_int_ring_t* K, lp_integer_t* c) {
- if (PyInt_Check(o)) {
- long c_long = PyInt_AsLong(o);
- lp_integer_construct_from_int(K, c, c_long);
- }
- if (PyLong_Check(o)) {
- PyObject* o_str = PyObject_Str(o);
- char* o_cstr = PyString_AsString(o_str);
- lp_integer_construct_from_string(K, c, o_cstr, 10);
- Py_DECREF(o_str);
- }
-}
-
-PyObject* integer_to_PyInt(const lp_integer_t* x) {
- char* str = lp_integer_to_string(x);
- char* str_p = 0;
- PyObject* result = PyInt_FromString(str, &str_p, 10);
- free(str);
- return result;
-}
-
-PyObject* integer_to_PyLong(const lp_integer_t* x) {
- char* str = lp_integer_to_string(x);
- char* str_p = 0;
- PyObject* result = PyLong_FromString(str, &str_p, 10);
- free(str);
- return result;
-}
-
-void PyFloat_to_dyadic_rational(PyObject* o, lp_dyadic_rational_t* x) {
- double o_double = PyFloat_AsDouble(o);
- lp_dyadic_rational_construct_from_double(x, o_double);
-}
-
-PyObject* dyadic_rational_to_PyFloat(const lp_dyadic_rational_t* x) {
- double x_double = lp_dyadic_rational_to_double(x);
- return PyFloat_FromDouble(x_double);
-}
-
-
-PyObject* algebraic_number_to_PyFloat(const lp_algebraic_number_t* x) {
- double x_double = lp_algebraic_number_to_double(x);
- return PyFloat_FromDouble(x_double);
-}
-
-int PyLong_or_Int_or_Float_Check(PyObject* o) {
- if (PyInt_Check(o)) {
- return 1;
- }
- if (PyLong_Check(o)) {
- return 1;
- }
- if (PyFloat_Check(o)) {
- return 1;
- }
- return 0;
-}
-
-void PyLong_or_Int_or_float_to_value(PyObject* o, lp_value_t* v) {
- if (PyLong_or_Int_Check(o)) {
- lp_integer_t v_int;
- PyLong_or_Int_to_integer(o, lp_Z, &v_int);
- lp_value_construct(v, LP_VALUE_INTEGER, &v_int);
- lp_integer_destruct(&v_int);
- } else if (PyFloat_Check(o)) {
- lp_dyadic_rational_t v_dy_q;
- PyFloat_to_dyadic_rational(o, &v_dy_q);
- lp_value_construct(v, LP_VALUE_INTEGER, &v_dy_q);
- lp_dyadic_rational_destruct(&v_dy_q);
- } else {
- lp_value_construct(v, LP_VALUE_NONE, 0);
- }
-}
diff --git a/python/utils3.c b/python/utils3.c
deleted file mode 100644
index b40c6c0b..00000000
--- a/python/utils3.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * 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 "utils.h"
-
-const char* pythonObject2CharStar(PyObject *pyobj){
- const char* retval = NULL;
- if(!pyobj){
- return retval;
- } else if(PyBytes_Check(pyobj)){
- retval = PyBytes_AsString(pyobj);
- return retval;
- } else if(PyUnicode_Check(pyobj)) {
- PyObject* str = PyUnicode_AsEncodedString(pyobj, "utf-8", "?");
- retval = PyBytes_AS_STRING(str);
- Py_XDECREF(str);
- } else {
- PyObject* pyob_str = PyObject_Str(pyobj);
- PyObject* str = PyUnicode_AsEncodedString(pyob_str, "utf-8", "?");
- retval = PyBytes_AS_STRING(str);
- Py_XDECREF(pyob_str);
- Py_XDECREF(str);
- }
- return retval;
-}
-
-int PyLong_or_Int_Check(PyObject* o) {
- if (PyLong_Check(o)) {
- return 1;
- }
- return 0;
-}
-
-void PyLong_or_Int_to_integer(PyObject* o, const lp_int_ring_t* K, lp_integer_t* c) {
- if (PyLong_Check(o)) {
- long c_long = PyLong_AsLong(o);
- lp_integer_construct_from_int(K, c, c_long);
- }
-}
-
-//IAM: unused in the python3 world
-PyObject* integer_to_PyInt(const lp_integer_t* x) {
- char* str = lp_integer_to_string(x);
- char* str_p = 0;
- PyObject* result = PyLong_FromString(str, &str_p, 10);
- free(str);
- return result;
-}
-
-PyObject* integer_to_PyLong(const lp_integer_t* x) {
- char* str = lp_integer_to_string(x);
- char* str_p = 0;
- PyObject* result = PyLong_FromString(str, &str_p, 10);
- free(str);
- return result;
-}
-
-void PyFloat_to_dyadic_rational(PyObject* o, lp_dyadic_rational_t* x) {
- double o_double = PyFloat_AsDouble(o);
- lp_dyadic_rational_construct_from_double(x, o_double);
-}
-
-PyObject* dyadic_rational_to_PyFloat(const lp_dyadic_rational_t* x) {
- double x_double = lp_dyadic_rational_to_double(x);
- return PyFloat_FromDouble(x_double);
-}
-
-
-PyObject* algebraic_number_to_PyFloat(const lp_algebraic_number_t* x) {
- double x_double = lp_algebraic_number_to_double(x);
- return PyFloat_FromDouble(x_double);
-}
-
-int PyLong_or_Int_or_Float_Check(PyObject* o) {
- if (PyLong_Check(o)) {
- return 1;
- }
- if (PyFloat_Check(o)) {
- return 1;
- }
- return 0;
-}
-
-void PyLong_or_Int_or_float_to_value(PyObject* o, lp_value_t* v) {
- if (PyLong_or_Int_Check(o)) {
- lp_integer_t v_int;
- PyLong_or_Int_to_integer(o, lp_Z, &v_int);
- lp_value_construct(v, LP_VALUE_INTEGER, &v_int);
- lp_integer_destruct(&v_int);
- } else if (PyFloat_Check(o)) {
- lp_dyadic_rational_t v_dy_q;
- PyFloat_to_dyadic_rational(o, &v_dy_q);
- lp_value_construct(v, LP_VALUE_INTEGER, &v_dy_q);
- lp_dyadic_rational_destruct(&v_dy_q);
- } else {
- lp_value_construct(v, LP_VALUE_NONE, 0);
- }
-}
diff --git a/src/polynomial/feasibility_set_int.c b/src/polynomial/feasibility_set_int.c
index b791635f..9c9ea0e5 100644
--- a/src/polynomial/feasibility_set_int.c
+++ b/src/polynomial/feasibility_set_int.c
@@ -231,7 +231,7 @@ void lp_feasibility_set_int_pick_value(const lp_feasibility_set_int_t* set, lp_i
// TODO proper implementation
// get random element between (incl.) 0 and (|K| - size)
// find and add number of <= element
- assert(false);
+ assert(0);
}
}
diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt
index 05932920..523ce22c 100644
--- a/test/python/CMakeLists.txt
+++ b/test/python/CMakeLists.txt
@@ -1,7 +1,7 @@
if(LIBPOLY_BUILD_PYTHON_API)
add_custom_target(check
COMMAND
- PYTHONPATH=${CMAKE_BINARY_DIR}/python ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/check.py
+ PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_BINARY_DIR}/python ${Python3_INTERPRETER} ${CMAKE_CURRENT_SOURCE_DIR}/check.py
DEPENDS
polypy
WORKING_DIRECTORY
diff --git a/test/python/check.py b/test/python/check.py
index 60cf1456..4250cd7d 100755
--- a/test/python/check.py
+++ b/test/python/check.py
@@ -5,7 +5,7 @@
def forkexec(test, env):
- if sys.version_info >= (3,0): #IAM: (3, 2) might be more accurate...
+ if sys.version_info >= (3,2):
with open(test) as testf:
code = compile(testf.read(), test, 'exec') #IAM: explicit compile makes debugging easier.
exec(code, env, env)