GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/***************************************************************************1*2* Include3*4***************************************************************************/56#include <Python.h>7using namespace std;89#include <iostream>10using std::cout;11using std::cerr;12using std::endl;1314#include <string>15using std::string;1617#include <libnormaliz/cone.h>18#include <libnormaliz/map_operations.h>1920using libnormaliz::Cone;21//using libnormaliz::ConeProperty;22using libnormaliz::ConeProperties;23using libnormaliz::Sublattice_Representation;24using libnormaliz::Type::InputType;2526#include <vector>27using std::map;28using std::vector;29using std::pair;3031#include<csignal>3233typedef int py_size_t;3435/***************************************************************************36*37* Macros for exception handling38*39***************************************************************************/4041#define FUNC_BEGIN try {4243#define FUNC_END \44} catch (libnormaliz::InterruptException& e ) {\45PyOS_setsig(SIGINT,current_interpreter_sigint_handler);\46libnormaliz::nmz_interrupted = false; \47PyErr_SetInterrupt(); \48PyErr_CheckSignals(); \49return NULL; \50} catch (libnormaliz::NormalizException& e) { \51PyOS_setsig(SIGINT,current_interpreter_sigint_handler);\52PyErr_SetString( NormalizError, e.what() ); \53return NULL; \54} catch( exception& e ) { \55PyOS_setsig(SIGINT,current_interpreter_sigint_handler);\56PyErr_SetString( PyNormaliz_cppError, e.what() ); \57return NULL; \58}5960/***************************************************************************61*62* Signal handling63*64***************************************************************************/6566void signal_handler( int signal ){67libnormaliz::nmz_interrupted = true;68}6970/***************************************************************************71*72* Static objects73*74***************************************************************************/757677static PyObject * NormalizError;78static PyObject * PyNormaliz_cppError;79static const char* cone_name = "Cone";80static const char* cone_name_long = "Cone<long long>";81static string cone_name_str( cone_name );82static string cone_name_str_long( cone_name_long );8384static PyOS_sighandler_t current_interpreter_sigint_handler;8586/***************************************************************************87*88* Compiler version control89*90***************************************************************************/9192#if PY_MAJOR_VERSION >= 393#define string_check PyUnicode_Check94#else95#define string_check PyString_Check96#endif9798// Hacky 64-bit check. Works for windows and gcc, probably not clang.99// Check windows100#if _WIN32 || _WIN64101#if _WIN64102#define ENVIRONMENT64103#else104#define ENVIRONMENT32105#endif106#endif107108// Check GCC109#if __GNUC__110#if __x86_64__ || __ppc64__ || __aarch64__111#define ENVIRONMENT64112#else113#define ENVIRONMENT32114#endif115#endif116117#ifndef NMZ_RELEASE118static_assert(false,119"Your Normaliz version (unknown) is to old! Update to 3.2.0 or newer.");120#endif121#if NMZ_RELEASE < 30400122static_assert(false, "Your Normaliz version is to old! Update to 3.3.1 or newer.");123#endif124125/***************************************************************************126*127* Python-C data conversion functions128*129***************************************************************************/130131string PyUnicodeToString( PyObject* in ){132#if PY_MAJOR_VERSION >= 3133string out = "";134int length = PyUnicode_GET_SIZE( in );135for( int i = 0; i < length; i++ ){136out += PyUnicode_READ_CHAR( in, i );137}138return out;139#else140char* out = PyString_AsString( in );141return string(out);142#endif143}144145PyObject * StringToPyUnicode( string in ){146#if PY_MAJOR_VERSION >= 3147return PyUnicode_FromString( in.c_str() );148#else149return PyString_FromString( in.c_str() );150#endif151}152153// Boolean conversion154155inline PyObject* BoolToPyBool( bool in ){156return in ? Py_True : Py_False;157}158159// Converting MPZ's to PyLong and back via strings. Worst possible solution ever.160161bool PyNumberToNmz( PyObject * in, mpq_class& out ){162if( PyFloat_Check( in ) ){163mpq_class temp(PyFloat_AsDouble(in));164out.swap(temp);165return true;166}167PyObject * in_as_string = PyObject_Str( in );168const char* in_as_c_string = PyUnicodeToString( in_as_string ).c_str();169out.set_str( in_as_c_string, 10 );170return true;171}172173PyObject* NmzToPyNumber( mpz_class in ){174string mpz_as_string = in.get_str();175char* mpz_as_c_string = const_cast<char*>(mpz_as_string.c_str());176char * pend;177PyObject* ret_val = PyLong_FromString( mpz_as_c_string, &pend, 10 );178return ret_val;179}180181PyObject* NmzToPyList( mpq_class in ){182PyObject* out_list = PyList_New( 2 );183PyList_SetItem( out_list, 0, NmzToPyNumber( in.get_num() ) );184PyList_SetItem( out_list, 1, NmzToPyNumber( in.get_den() ) );185return out_list;186}187188bool PyNumberToNmz( PyObject* in, long long & out ){189190int overflow;191out = PyLong_AsLongLongAndOverflow( in, &overflow );192if( overflow == -1 )193return false;194return true;195196}197198PyObject* NmzToPyNumber( long long in ){199200return PyLong_FromLongLong( in );201202}203204PyObject* NmzToPyNumber( libnormaliz::key_t in ){205206return PyLong_FromLong( in );207208}209210#ifdef ENVIRONMENT64211PyObject* NmzToPyNumber( size_t in ){212213return PyLong_FromLong( in );214215}216#endif217218PyObject* NmzToPyNumber( long in ){219220return PyLong_FromLong( in );221222}223224PyObject* NmzToPyNumber( double in ){225226return PyFloat_FromDouble( in );227228}229230template<typename Integer>231bool PyNumberToNmz(Integer& x, Integer &out){232233return Integer::unimplemented_function;234235}236237template<typename Integer>238PyObject* NmzToPyNumber(Integer &in){239240return Integer::unimplemented_function;241242}243244template<typename Integer>245static bool PyListToNmz( vector<Integer>& out, PyObject* in ){246if (!PyList_Check(in))247return false;248const int n = PyList_Size(in);249out.resize(n);250for (int i = 0; i < n; ++i) {251PyObject* tmp = PyList_GetItem(in, i);252if (!PyNumberToNmz(tmp, out[i]))253return false;254}255return true;256}257258template<typename Integer>259static bool PyIntMatrixToNmz( vector<vector<Integer> >& out, PyObject* in ){260if (!PyList_Check( in ) )261return false;262const int nr = PyList_Size( in );263out.resize(nr);264for (int i = 0; i < nr; ++i) {265bool okay = PyListToNmz(out[i], PyList_GetItem(in, i));266if (!okay)267return false;268}269return true;270}271272template<typename Integer>273PyObject* NmzVectorToPyList(const vector<Integer>& in)274{275PyObject* vector;276const size_t n = in.size();277vector = PyList_New(n);278for (size_t i = 0; i < n; ++i) {279PyList_SetItem(vector, i, NmzToPyNumber(in[i]));280}281return vector;282}283284PyObject* NmzBoolVectorToPyList(const vector<bool>& in)285{286PyObject* vector;287const size_t n = in.size();288vector = PyList_New(n);289for (size_t i = 0; i < n; ++i) {290PyList_SetItem(vector, i, BoolToPyBool(in[i]));291}292return vector;293}294295PyObject* NmzBoolMatrixToPyList(const vector< vector<bool> >& in)296{297PyObject* matrix;298const size_t n = in.size();299matrix = PyList_New( n );300for (size_t i = 0; i < n; ++i) {301PyList_SetItem(matrix, i, NmzBoolVectorToPyList(in[i]));302}303return matrix;304}305306template<typename Integer>307PyObject* NmzMatrixToPyList(const vector< vector<Integer> >& in)308{309PyObject* matrix;310const size_t n = in.size();311matrix = PyList_New( n );312for (size_t i = 0; i < n; ++i) {313PyList_SetItem(matrix, i, NmzVectorToPyList(in[i]));314}315return matrix;316}317318PyObject* NmzHilbertSeriesToPyList(const libnormaliz::HilbertSeries& HS, bool is_HSOP)319{320PyObject* return_list = PyList_New( 3 );321if(is_HSOP){322PyList_SetItem(return_list, 0, NmzVectorToPyList(HS.getHSOPNum()));323PyList_SetItem(return_list, 1, NmzVectorToPyList(libnormaliz::to_vector(HS.getHSOPDenom())));324PyList_SetItem(return_list, 2, NmzToPyNumber(HS.getShift()));325}else{326PyList_SetItem(return_list, 0, NmzVectorToPyList(HS.getNum()));327PyList_SetItem(return_list, 1, NmzVectorToPyList(libnormaliz::to_vector(HS.getDenom())));328PyList_SetItem(return_list, 2, NmzToPyNumber(HS.getShift()));329}330return return_list;331}332333template<typename Integer>334PyObject* NmzWeightedEhrhartSeriesToPyList(const std::pair<libnormaliz::HilbertSeries,Integer>& HS)335{336PyObject* return_list = PyList_New( 4 );337PyList_SetItem(return_list, 0, NmzVectorToPyList(HS.first.getNum()));338PyList_SetItem(return_list, 1, NmzVectorToPyList(libnormaliz::to_vector(HS.first.getDenom())));339PyList_SetItem(return_list, 2, NmzToPyNumber(HS.first.getShift()));340PyList_SetItem(return_list, 3, NmzToPyNumber(HS.second) );341return return_list;342}343344template<typename Integer>345PyObject* NmzHilbertQuasiPolynomialToPyList(const libnormaliz::HilbertSeries& HS)346{347vector< vector<Integer> > HQ = HS.getHilbertQuasiPolynomial();348const size_t n = HS.getPeriod();349PyObject* return_list = PyList_New(n+1);350for (size_t i = 0; i < n; ++i) {351PyList_SetItem(return_list, i, NmzVectorToPyList(HQ[i]));352}353PyList_SetItem(return_list, n, NmzToPyNumber(HS.getHilbertQuasiPolynomialDenom()));354return return_list;355}356357template<typename Integer>358PyObject* NmzWeightedEhrhartQuasiPolynomialToPyList(const libnormaliz::IntegrationData& int_data)359{360vector< vector<Integer> > ehrhart_qp = int_data.getWeightedEhrhartQuasiPolynomial();361const size_t n = ehrhart_qp.size();362PyObject* return_list = PyList_New(n+1);363for (size_t i = 0; i < n; ++i) {364PyList_SetItem(return_list, i, NmzVectorToPyList(ehrhart_qp[i]));365}366PyList_SetItem(return_list, n, NmzToPyNumber(int_data.getWeightedEhrhartQuasiPolynomialDenom()));367return return_list;368}369370template<typename Integer>371PyObject* NmzTriangleListToPyList(const vector< pair<vector<libnormaliz::key_t>, Integer> >& in)372{373const size_t n = in.size();374PyObject* M = PyList_New( n );375for (size_t i = 0; i < n; ++i) {376// convert the pair377PyObject* pair = PyList_New(2);378PyList_SetItem(pair, 0, NmzVectorToPyList<libnormaliz::key_t>(in[i].first));379PyList_SetItem(pair, 1, NmzToPyNumber(in[i].second));380PyList_SetItem(M, i, pair);381}382return M;383}384385template<typename Integer>386PyObject* NmzStanleyDataToPyList(const libnormaliz::STANLEYDATA<Integer>& StanleyData)387{388PyObject* pair = PyList_New(2);389PyList_SetItem(pair, 0, NmzVectorToPyList<libnormaliz::key_t>(StanleyData.key));390PyList_SetItem(pair, 1, NmzMatrixToPyList(StanleyData.offsets.get_elements()));391return pair;392}393394template<typename Integer>395PyObject* NmzStanleyDecToPyList(const list<libnormaliz::STANLEYDATA<Integer> >& StanleyDec)396{397const size_t n = StanleyDec.size();398PyObject* M = PyList_New( n );399typename list<libnormaliz::STANLEYDATA<Integer> >::const_iterator S = StanleyDec.begin();400for (size_t i = 0; i < n; ++i) {401PyList_SetItem(M, i,NmzStanleyDataToPyList(*S) );402++S;403}404return M;405}406407template<typename Integer>408static PyObject* _NmzBasisChangeIntern(Cone<Integer>* C)409{410Sublattice_Representation<Integer> bc = C->getSublattice();411412PyObject* res = PyList_New( 3 );413PyList_SetItem(res, 0, NmzMatrixToPyList(bc.getEmbedding()));414PyList_SetItem(res, 1, NmzMatrixToPyList(bc.getProjection()));415PyList_SetItem(res, 2, NmzToPyNumber(bc.getAnnihilator()));416// Dim, Rank, Equations and Congruences are already covered by special functions417// ditto ExternalIndex418return res;419}420421/***************************************************************************422*423* PyCapsule handler functions424*425***************************************************************************/426427void delete_cone_mpz( PyObject* cone ){428Cone<mpz_class> * cone_ptr = reinterpret_cast<Cone<mpz_class>* >( PyCapsule_GetPointer( cone, cone_name ) );429delete cone_ptr;430}431432void delete_cone_long( PyObject* cone ){433Cone<long long> * cone_ptr = reinterpret_cast<Cone<long long>* >( PyCapsule_GetPointer( cone, cone_name_long ) );434delete cone_ptr;435}436437Cone<long long>* get_cone_long( PyObject* cone ){438return reinterpret_cast<Cone<long long>*>( PyCapsule_GetPointer( cone, cone_name_long ) );439}440441Cone<mpz_class>* get_cone_mpz( PyObject* cone ){442return reinterpret_cast<Cone<mpz_class>*>( PyCapsule_GetPointer( cone, cone_name ) );443}444445446PyObject* pack_cone( Cone<mpz_class>* C ){447return PyCapsule_New( reinterpret_cast<void*>( C ), cone_name, &delete_cone_mpz );448}449450PyObject* pack_cone( Cone<long long>* C ){451return PyCapsule_New( reinterpret_cast<void*>( C ), cone_name_long, &delete_cone_long );452}453454bool is_cone( PyObject* cone ){455if( PyCapsule_CheckExact( cone ) ){456// compare as string457return cone_name_str == string(PyCapsule_GetName( cone )) || cone_name_str_long == string(PyCapsule_GetName( cone ));458}459return false;460}461462/***************************************************************************463*464* Cone property list465*466***************************************************************************/467468static PyObject* NmzListConeProperties(PyObject* args)469{470FUNC_BEGIN471472PyObject* return_list = PyList_New( 2 );473474ConeProperties props;475for(int i=0; i < libnormaliz::ConeProperty::EnumSize;i++){476props.set( static_cast<libnormaliz::ConeProperty::Enum>(i) );477}478479ConeProperties goals = props.goals();480ConeProperties options = props.options();481482int number_goals = goals.count();483int number_options = options.count();484485PyObject* goal_list = PyList_New( number_goals );486PyObject* option_list = PyList_New( number_options );487488PyList_SetItem( return_list, 0, goal_list );489PyList_SetItem( return_list, 1, option_list );490491int list_position = 0;492for(int i=0; i < libnormaliz::ConeProperty::EnumSize;i++){493if(goals.test(static_cast<libnormaliz::ConeProperty::Enum>(i))){494string name = libnormaliz::toString(static_cast<libnormaliz::ConeProperty::Enum>(i));495PyList_SetItem( goal_list, list_position, StringToPyUnicode( name ) );496list_position++;497}498}499500list_position = 0;501for(int i=0; i < libnormaliz::ConeProperty::EnumSize;i++){502if(options.test(static_cast<libnormaliz::ConeProperty::Enum>(i))){503string name = libnormaliz::toString(static_cast<libnormaliz::ConeProperty::Enum>(i));504PyList_SetItem( option_list, list_position, StringToPyUnicode( name ) );505list_position++;506}507}508509return return_list;510511FUNC_END512513}514515/***************************************************************************516*517* NmzCone518*519***************************************************************************/520521template<typename Integer>522static PyObject* _NmzConeIntern(PyObject * args)523{524map <InputType, vector< vector<mpq_class> > > input;525526PyObject* input_list;527528bool grading_polynomial = false;529string polynomial;530531if( PyTuple_Size(args)==1 ){532input_list = PyTuple_GetItem( args, 0 );533if( ! PyList_Check( input_list ) ){534PyErr_SetString( PyNormaliz_cppError, "Single argument must be a list" );535return NULL;536}537input_list = PyList_AsTuple( input_list );538}else{539input_list = args;540}541542const int n = PyTuple_Size(input_list);543if (n&1) {544PyErr_SetString( PyNormaliz_cppError, "Number of arguments must be even" );545return NULL;546}547for (int i = 0; i < n; i += 2) {548PyObject* type = PyTuple_GetItem(input_list, i);549if (!string_check(type)) {550PyErr_SetString( PyNormaliz_cppError, "Odd entries must be strings" );551return NULL;552}553554string type_str = PyUnicodeToString( type );555556if( type_str.compare( "polynomial" ) == 0 ){557PyObject* M = PyTuple_GetItem(input_list, i+1);558polynomial = PyUnicodeToString( M );559grading_polynomial = true;560continue;561}562563PyObject* M = PyTuple_GetItem(input_list, i+1);564vector<vector<mpq_class> > Mat;565bool okay = PyIntMatrixToNmz(Mat, M);566if (!okay) {567PyErr_SetString( PyNormaliz_cppError, "Even entries must be matrices" );568return NULL;569}570571input[libnormaliz::to_type(type_str)] = Mat;572}573574Cone<Integer>* C = new Cone<Integer>(input);575576if( grading_polynomial ){577C->setPolynomial( polynomial );578}579580PyObject* return_container = pack_cone( C );581582return return_container;583}584585PyObject* _NmzCone(PyObject* self, PyObject* args, PyObject* keywds)586{587FUNC_BEGIN588589static const char* string_for_keyword_argument = "CreateAsLongLong";590PyObject* create_as_long_long;591592#if PY_MAJOR_VERSION >= 3593PyObject* key = PyUnicode_FromString( string_for_keyword_argument );594#else595PyObject* key = PyString_FromString( const_cast<char*>(string_for_keyword_argument) );596#endif597598if( keywds != NULL && PyDict_Contains( keywds, key ) == 1 ){599create_as_long_long = PyDict_GetItem( keywds, key );600}else{601create_as_long_long = Py_False;602}603604if( create_as_long_long!=Py_True ){605return _NmzConeIntern<mpz_class>(args);606}else{607return _NmzConeIntern<long long>(args);608}609610FUNC_END611}612613/***************************************************************************614*615* NmzHilbertSeries616*617***************************************************************************/618619template<typename Integer>620PyObject* NmzHilbertSeries(Cone<Integer>* C, PyObject* args)621{622FUNC_BEGIN623624const int arg_len = PyTuple_Size(args);625626if(arg_len==1){627bool is_HSOP = C->isComputed(libnormaliz::ConeProperty::HSOP);628return NmzHilbertSeriesToPyList(C->getHilbertSeries(),is_HSOP);629}630631PyObject* is_HSOP = PyTuple_GetItem( args, 1 );632633if( is_HSOP == Py_True ){634if (!C->isComputed(libnormaliz::ConeProperty::HSOP)) C->compute(libnormaliz::ConeProperty::HSOP);635return NmzHilbertSeriesToPyList(C->getHilbertSeries(),true);636}else{637return NmzHilbertSeriesToPyList(C->getHilbertSeries(),false);638}639640FUNC_END641}642643644PyObject* NmzHilbertSeries_Outer(PyObject* self, PyObject* args){645646FUNC_BEGIN647648PyObject* cone = PyTuple_GetItem( args, 0 );649650if( !is_cone(cone) ){651PyErr_SetString( PyNormaliz_cppError, "First argument must be a cone" );652return NULL;653}654655current_interpreter_sigint_handler = PyOS_setsig(SIGINT,signal_handler);656657if( cone_name_str == string(PyCapsule_GetName(cone)) ){658Cone<mpz_class>* cone_ptr = get_cone_mpz(cone);659PyObject* return_value = NmzHilbertSeries(cone_ptr, args);660PyOS_setsig( SIGINT, current_interpreter_sigint_handler );661return return_value;662}else{663Cone<long long>* cone_ptr = get_cone_long(cone);664PyObject* return_value = NmzHilbertSeries(cone_ptr,args);665PyOS_setsig( SIGINT, current_interpreter_sigint_handler );666return return_value;667}668669FUNC_END670671}672673/***************************************************************************674*675* NmzCompute676*677***************************************************************************/678679template<typename Integer>680PyObject* _NmzCompute(Cone<Integer>* C, PyObject* args)681{682FUNC_BEGIN683684const int arg_len = PyTuple_Size(args);685686PyObject* to_compute;687688if(arg_len==2){689PyObject* first_arg = PyTuple_GetItem(args,1);690if(PyList_CheckExact( first_arg )){691to_compute = first_arg;692}else{693to_compute = PyList_New( 1 );694int result = PyList_SetItem( to_compute, 0, first_arg );695if(result!=0){696PyErr_SetString( PyNormaliz_cppError, "List could not be created" );697return NULL;698}699}700}else{701to_compute = PyList_New( arg_len - 1 );702for( int i = 1;i<arg_len;i++){703PyList_SetItem( to_compute, i, PyTuple_GetItem( args, i ) );704}705}706707ConeProperties propsToCompute;708const int n = PyList_Size(to_compute);709710for (int i = 0; i < n; ++i) {711PyObject* prop = PyList_GetItem(to_compute, i);712if (!string_check(prop)) {713PyErr_SetString( PyNormaliz_cppError, "All elements must be strings" );714return NULL;715}716string prop_str(PyUnicodeToString(prop));717propsToCompute.set( libnormaliz::toConeProperty(prop_str) );718}719720ConeProperties notComputed = C->compute(propsToCompute);721722// Cone.compute returns the not computed properties723// we return a bool, true when everything requested was computed724return notComputed.none() ? Py_True : Py_False;725FUNC_END726}727728729PyObject* _NmzCompute_Outer(PyObject* self, PyObject* args){730731FUNC_BEGIN732733current_interpreter_sigint_handler = PyOS_setsig(SIGINT,signal_handler);734735PyObject* cone = PyTuple_GetItem( args, 0 );736737PyObject* result;738739if( !is_cone(cone) ){740PyErr_SetString( PyNormaliz_cppError, "First argument must be a cone" );741return NULL;742}743744if( cone_name_str == string(PyCapsule_GetName(cone)) ){745Cone<mpz_class>* cone_ptr = get_cone_mpz(cone);746result = _NmzCompute(cone_ptr, args);747}else{748Cone<long long>* cone_ptr = get_cone_long(cone);749result = _NmzCompute(cone_ptr,args);750}751752PyOS_setsig(SIGINT,current_interpreter_sigint_handler);753754return result;755756FUNC_END757758}759760/***************************************************************************761*762* NmzIsComputed763*764***************************************************************************/765766template<typename Integer>767PyObject* NmzIsComputed(Cone<Integer>* C, PyObject* prop)768{769FUNC_BEGIN770771libnormaliz::ConeProperty::Enum p = libnormaliz::toConeProperty(PyUnicodeToString( prop ) );772773return C->isComputed(p) ? Py_True : Py_False;774775FUNC_END776}777778PyObject* NmzIsComputed_Outer(PyObject* self, PyObject* args)779{780FUNC_BEGIN781782PyObject* cone = PyTuple_GetItem( args, 0 );783PyObject* to_compute = PyTuple_GetItem( args, 1 );784785if( !is_cone(cone) ){786PyErr_SetString( PyNormaliz_cppError, "First argument must be a cone" );787return NULL;788}789790if( cone_name_str == string(PyCapsule_GetName(cone)) ){791Cone<mpz_class>* cone_ptr = get_cone_mpz(cone);792return NmzIsComputed(cone_ptr, to_compute);793}else{794Cone<long long>* cone_ptr = get_cone_long(cone);795return NmzIsComputed(cone_ptr,to_compute);796}797798FUNC_END799}800801/***************************************************************************802*803* NmzResult804*805***************************************************************************/806807template<typename Integer>808PyObject* _NmzResultImpl(Cone<Integer>* C, PyObject* prop_obj)809{810811string prop = PyUnicodeToString( prop_obj );812813libnormaliz::ConeProperty::Enum p = libnormaliz::toConeProperty(prop);814815current_interpreter_sigint_handler = PyOS_setsig(SIGINT,signal_handler);816ConeProperties notComputed = C->compute(ConeProperties(p));817PyOS_setsig(SIGINT, current_interpreter_sigint_handler );818819if (notComputed.any()) {820return Py_None;821}822823switch (p) {824case libnormaliz::ConeProperty::Generators:825return NmzMatrixToPyList(C->getGenerators());826827case libnormaliz::ConeProperty::ExtremeRays:828return NmzMatrixToPyList(C->getExtremeRays());829830case libnormaliz::ConeProperty::VerticesOfPolyhedron:831return NmzMatrixToPyList(C->getVerticesOfPolyhedron());832833case libnormaliz::ConeProperty::SupportHyperplanes:834return NmzMatrixToPyList(C->getSupportHyperplanes());835836case libnormaliz::ConeProperty::TriangulationSize:837return NmzToPyNumber(C->getTriangulationSize());838839case libnormaliz::ConeProperty::TriangulationDetSum:840return NmzToPyNumber(C->getTriangulationDetSum());841842case libnormaliz::ConeProperty::Triangulation:843return NmzTriangleListToPyList<Integer>(C->getTriangulation());844845case libnormaliz::ConeProperty::Multiplicity:846return NmzToPyList(C->getMultiplicity());847848case libnormaliz::ConeProperty::Integral:849return NmzToPyList(C->getIntegral());850851case libnormaliz::ConeProperty::VirtualMultiplicity:852return NmzToPyList(C->getVirtualMultiplicity());853854case libnormaliz::ConeProperty::RecessionRank:855return NmzToPyNumber(C->getRecessionRank());856857case libnormaliz::ConeProperty::AffineDim:858return NmzToPyNumber(C->getAffineDim());859860case libnormaliz::ConeProperty::ModuleRank:861return NmzToPyNumber(C->getModuleRank());862863case libnormaliz::ConeProperty::HilbertBasis:864return NmzMatrixToPyList(C->getHilbertBasis());865866case libnormaliz::ConeProperty::MaximalSubspace:867return NmzMatrixToPyList(C->getMaximalSubspace());868869case libnormaliz::ConeProperty::ModuleGenerators:870return NmzMatrixToPyList(C->getModuleGenerators());871872case libnormaliz::ConeProperty::Deg1Elements:873return NmzMatrixToPyList(C->getDeg1Elements());874875case libnormaliz::ConeProperty::HilbertSeries:876{877bool is_HSOP = C->isComputed(libnormaliz::ConeProperty::HSOP);878return NmzHilbertSeriesToPyList(C->getHilbertSeries(),is_HSOP);879}880881case libnormaliz::ConeProperty::WeightedEhrhartSeries:882return NmzWeightedEhrhartSeriesToPyList(C->getWeightedEhrhartSeries());883884885case libnormaliz::ConeProperty::Grading:886{887vector<Integer> grad = C->getGrading();888grad.push_back(C->getGradingDenom());889return NmzVectorToPyList(grad);890}891892case libnormaliz::ConeProperty::IsPointed:893return BoolToPyBool(C->isPointed());894895case libnormaliz::ConeProperty::IsDeg1ExtremeRays:896return BoolToPyBool(C->isDeg1ExtremeRays());897898case libnormaliz::ConeProperty::IsDeg1HilbertBasis:899return BoolToPyBool(C->isDeg1HilbertBasis());900901case libnormaliz::ConeProperty::IsIntegrallyClosed:902return BoolToPyBool(C->isIntegrallyClosed());903904case libnormaliz::ConeProperty::OriginalMonoidGenerators:905return NmzMatrixToPyList(C->getOriginalMonoidGenerators());906907case libnormaliz::ConeProperty::IsReesPrimary:908return BoolToPyBool(C->isReesPrimary());909910case libnormaliz::ConeProperty::ReesPrimaryMultiplicity:911return NmzToPyNumber(C->getReesPrimaryMultiplicity());912913case libnormaliz::ConeProperty::StanleyDec:914return NmzStanleyDecToPyList(C->getStanleyDec());915916case libnormaliz::ConeProperty::ExcludedFaces:917return NmzMatrixToPyList(C->getExcludedFaces());918919case libnormaliz::ConeProperty::Dehomogenization:920return NmzVectorToPyList(C->getDehomogenization());921922case libnormaliz::ConeProperty::InclusionExclusionData:923return NmzTriangleListToPyList<long>(C->getInclusionExclusionData());924925case libnormaliz::ConeProperty::ClassGroup:926return NmzVectorToPyList(C->getClassGroup());927928case libnormaliz::ConeProperty::IsInhomogeneous:929return BoolToPyBool(C->isInhomogeneous());930931/* Sublattice properties */932933case libnormaliz::ConeProperty::Equations:934return NmzMatrixToPyList(C->getSublattice().getEquations());935936case libnormaliz::ConeProperty::Congruences:937return NmzMatrixToPyList(C->getSublattice().getCongruences());938939case libnormaliz::ConeProperty::EmbeddingDim:940return NmzToPyNumber(C->getEmbeddingDim());941942case libnormaliz::ConeProperty::Rank:943return NmzToPyNumber(C->getRank());944945case libnormaliz::ConeProperty::Sublattice:946return _NmzBasisChangeIntern(C);947948case libnormaliz::ConeProperty::ExternalIndex:949return NmzToPyNumber(C->getSublattice().getExternalIndex());950951case libnormaliz::ConeProperty::InternalIndex:952return NmzToPyNumber(C->getIndex());953954case libnormaliz::ConeProperty::WitnessNotIntegrallyClosed:955return NmzVectorToPyList(C->getWitnessNotIntegrallyClosed());956957958/* New stuff */959960case libnormaliz::ConeProperty::GradingDenom:961return NmzToPyNumber(C->getGradingDenom());962963case libnormaliz::ConeProperty::UnitGroupIndex:964return NmzToPyNumber(C->getUnitGroupIndex());965966case libnormaliz::ConeProperty::ModuleGeneratorsOverOriginalMonoid:967return NmzMatrixToPyList(C->getModuleGeneratorsOverOriginalMonoid());968969case libnormaliz::ConeProperty::IntegerHull:970{971Cone<Integer>* hull = new Cone<Integer>( C->getIntegerHullCone() );972return pack_cone( hull );973}974975case libnormaliz::ConeProperty::HilbertQuasiPolynomial:976return NmzHilbertQuasiPolynomialToPyList<mpz_class>(C->getHilbertSeries()); //FIXME: Why is this return value not parametrized, but mpz_class only?977978case libnormaliz::ConeProperty::WeightedEhrhartQuasiPolynomial:979return NmzWeightedEhrhartQuasiPolynomialToPyList<mpz_class>(C->getIntData());980981case libnormaliz::ConeProperty::IsTriangulationNested:982return BoolToPyBool(C->isTriangulationNested());983984case libnormaliz::ConeProperty::IsTriangulationPartial:985return BoolToPyBool(C->isTriangulationPartial());986987case libnormaliz::ConeProperty::ConeDecomposition:988return NmzBoolMatrixToPyList(C->getOpenFacets());989990case libnormaliz::ConeProperty::IsGorenstein:991return BoolToPyBool(C->isGorenstein());992993case libnormaliz::ConeProperty::GeneratorOfInterior:994return NmzVectorToPyList(C->getGeneratorOfInterior());995996case libnormaliz::ConeProperty::VerticesFloat:997return NmzMatrixToPyList(C->getVerticesFloat());998999// the following properties are compute options and do not return anything1000case libnormaliz::ConeProperty::DualMode:1001case libnormaliz::ConeProperty::DefaultMode:1002case libnormaliz::ConeProperty::Approximate:1003case libnormaliz::ConeProperty::BottomDecomposition:1004case libnormaliz::ConeProperty::KeepOrder:1005case libnormaliz::ConeProperty::NoBottomDec:1006case libnormaliz::ConeProperty::PrimalMode:1007case libnormaliz::ConeProperty::Symmetrize:1008case libnormaliz::ConeProperty::NoSymmetrization:1009case libnormaliz::ConeProperty::BigInt:1010case libnormaliz::ConeProperty::NoNestedTri:1011case libnormaliz::ConeProperty::HSOP:1012case libnormaliz::ConeProperty::Projection:1013case libnormaliz::ConeProperty::NoProjection:1014case libnormaliz::ConeProperty::ProjectionFloat:1015case libnormaliz::ConeProperty::SCIP:1016case libnormaliz::ConeProperty::NoPeriodBound:1017PyErr_SetString( PyNormaliz_cppError, "ConeProperty is input-only" );1018return NULL;1019#if NMZ_RELEASE >= 302001020case libnormaliz::ConeProperty::NoSubdivision:1021PyErr_SetString( PyNormaliz_cppError, "ConeProperty is input-only" );1022return NULL;1023#endif1024default:1025PyErr_SetString( PyNormaliz_cppError, "Unknown cone property" );1026return NULL;1027break;1028}10291030return Py_None;1031}10321033PyObject* _NmzResult( PyObject* self, PyObject* args ){10341035FUNC_BEGIN1036PyObject* cone = PyTuple_GetItem( args, 0 );1037PyObject* prop = PyTuple_GetItem( args, 1 );10381039if( !is_cone( cone ) ){1040PyErr_SetString( PyNormaliz_cppError, "First argument must be a cone" );1041return NULL;1042}10431044if( !string_check( prop ) ){1045PyErr_SetString( PyNormaliz_cppError, "Second argument must be a unicode string" );1046return NULL;1047}10481049if( cone_name_str == string(PyCapsule_GetName(cone)) ){1050Cone<mpz_class>* cone_ptr = get_cone_mpz(cone);1051return _NmzResultImpl(cone_ptr, prop);1052}else{1053Cone<long long>* cone_ptr = get_cone_long(cone);1054return _NmzResultImpl(cone_ptr, prop);1055}10561057FUNC_END1058}10591060/***************************************************************************1061*1062* Python verbosity1063*1064***************************************************************************/10651066PyObject* NmzSetVerboseDefault( PyObject* self, PyObject* args)1067{1068FUNC_BEGIN1069PyObject * value = PyTuple_GetItem( args, 0 );1070if (value != Py_True && value != Py_False){1071PyErr_SetString( PyNormaliz_cppError, "Argument must be True or False" );1072return NULL;1073}1074return BoolToPyBool(libnormaliz::setVerboseDefault(value == Py_True));1075FUNC_END1076}10771078template<typename Integer>1079PyObject* NmzSetVerbose(Cone<Integer>* C, PyObject* value)1080{1081FUNC_BEGIN1082bool old_value;1083old_value = C->setVerbose(value == Py_True);1084return BoolToPyBool(old_value);1085FUNC_END1086}10871088PyObject* NmzSetVerbose_Outer(PyObject* self, PyObject* args)1089{1090FUNC_BEGIN10911092PyObject* cone = PyTuple_GetItem( args, 0 );10931094if( !is_cone( cone ) ){1095PyErr_SetString( PyNormaliz_cppError, "First argument must be a cone" );1096return NULL;1097}10981099PyObject* value = PyTuple_GetItem( args, 1 );1100if (value != Py_True && value != Py_False){1101PyErr_SetString( PyNormaliz_cppError, "Second argument must be True or False" );1102return NULL;1103}11041105if( cone_name_str == string(PyCapsule_GetName(cone)) ){1106Cone<mpz_class>* cone_ptr = get_cone_mpz(cone);1107return NmzSetVerbose(cone_ptr, value);1108}else{1109Cone<long long>* cone_ptr = get_cone_long(cone);1110return NmzSetVerbose(cone_ptr, value);1111}11121113FUNC_END11141115}11161117/***************************************************************************1118*1119* Get Polynomial1120*1121***************************************************************************/11221123PyObject* NmzGetPolynomial(PyObject* self, PyObject* args ){11241125FUNC_BEGIN11261127PyObject* cone = PyTuple_GetItem( args, 0 );11281129if( !is_cone( cone ) ){1130PyErr_SetString( PyNormaliz_cppError, "First argument must be a cone" );1131return NULL;1132}11331134current_interpreter_sigint_handler = PyOS_setsig(SIGINT,signal_handler);11351136if( cone_name_str == string(PyCapsule_GetName(cone)) ){1137Cone<mpz_class>* cone_ptr = get_cone_mpz(cone);1138PyObject* return_value = StringToPyUnicode( (cone_ptr->getIntData()).getPolynomial() );1139PyOS_setsig( SIGINT, current_interpreter_sigint_handler );1140return return_value;1141}else{1142Cone<long long>* cone_ptr = get_cone_long(cone);1143PyObject* return_value = StringToPyUnicode( (cone_ptr->getIntData()).getPolynomial() );1144PyOS_setsig( SIGINT, current_interpreter_sigint_handler );1145return return_value;1146}11471148FUNC_END11491150}11511152/***************************************************************************1153*1154* NrCoeffQuasiPol1155*1156***************************************************************************/11571158PyObject* NmzSetNrCoeffQuasiPol( PyObject* self, PyObject* args ){11591160FUNC_BEGIN11611162PyObject* cone = PyTuple_GetItem( args, 0 );11631164if( !is_cone( cone ) ){1165PyErr_SetString( PyNormaliz_cppError, "First argument must be a cone" );1166return NULL;1167}11681169PyObject* bound_py = PyTuple_GetItem( args, 1 );11701171int overflow;1172long bound = PyLong_AsLongLongAndOverflow( bound_py, &overflow );1173if( cone_name_str == string(PyCapsule_GetName(cone)) ){1174Cone<mpz_class>* cone_ptr = get_cone_mpz(cone);1175cone_ptr->setNrCoeffQuasiPol(bound);1176return Py_True;1177}else{1178Cone<long long>* cone_ptr = get_cone_long(cone);1179cone_ptr->setNrCoeffQuasiPol(bound);1180return Py_True;1181}11821183FUNC_END11841185}11861187/***************************************************************************1188*1189* Get Symmetrized cone1190*1191***************************************************************************/11921193PyObject* NmzSymmetrizedCone(PyObject* self, PyObject* args ){11941195FUNC_BEGIN11961197PyObject* cone = PyTuple_GetItem( args, 0 );11981199if( !is_cone( cone ) ){1200PyErr_SetString( PyNormaliz_cppError, "First argument must be a cone" );1201return NULL;1202}12031204current_interpreter_sigint_handler = PyOS_setsig(SIGINT,signal_handler);12051206if( cone_name_str == string(PyCapsule_GetName(cone)) ){1207Cone<mpz_class>* cone_ptr = get_cone_mpz(cone);1208Cone<mpz_class>* symm_cone = &(cone_ptr->getSymmetrizedCone());1209PyOS_setsig( SIGINT, current_interpreter_sigint_handler );1210if( symm_cone==0 ){1211return Py_None;1212}1213symm_cone = new Cone<mpz_class>( *symm_cone );1214return pack_cone( symm_cone );1215}else{1216Cone<long long>* cone_ptr = get_cone_long(cone);1217Cone<long long>* symm_cone = &(cone_ptr->getSymmetrizedCone());1218PyOS_setsig( SIGINT, current_interpreter_sigint_handler );1219if( symm_cone==0 ){1220return Py_None;1221}1222symm_cone = new Cone<long long>( *symm_cone );1223return pack_cone( symm_cone );1224}12251226FUNC_END12271228}12291230/***************************************************************************1231*1232* Set number of threads1233*1234***************************************************************************/12351236PyObject* NmzSetNumberOfNormalizThreads(PyObject* self, PyObject* args ){12371238FUNC_BEGIN12391240PyObject* num_treads = PyTuple_GetItem( args, 0 );12411242if( !PyLong_Check( num_treads ) ){1243PyErr_SetString( PyNormaliz_cppError, "First argument must be an integer" );1244return NULL;1245}12461247long num_threads_long = PyLong_AsLong( num_treads );12481249num_threads_long = libnormaliz::set_thread_limit( num_threads_long );12501251return PyLong_FromLong( num_threads_long );12521253FUNC_END12541255}12561257/***************************************************************************1258*1259* Python init stuff1260*1261***************************************************************************/12621263struct module_state {1264PyObject *error;1265};12661267#if PY_MAJOR_VERSION >= 31268#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))1269#else1270#define GETSTATE(m) (&_state)1271static struct module_state _state;1272#endif12731274static PyObject * error_out(PyObject *m) {1275struct module_state *st = GETSTATE(m);1276PyErr_SetString(st->error, "something bad happened");1277return NULL;1278}12791280static PyMethodDef PyNormaliz_cppMethods[] = {1281{"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},1282{"NmzCone", (PyCFunction)_NmzCone, METH_VARARGS|METH_KEYWORDS,1283"Create a cone"},1284{"NmzCompute", (PyCFunction)_NmzCompute_Outer, METH_VARARGS,1285"Compute some stuff"},1286{"NmzIsComputed", (PyCFunction)NmzIsComputed_Outer, METH_VARARGS,1287"Check if property is computed "},1288{"NmzResult", (PyCFunction)_NmzResult, METH_VARARGS,1289"Return cone property" },1290{ "NmzSetVerboseDefault", (PyCFunction)NmzSetVerboseDefault, METH_VARARGS,1291"Set verbosity" },1292{ "NmzSetVerbose", (PyCFunction)NmzSetVerbose_Outer, METH_VARARGS,1293"Set verbosity of cone" },1294{ "NmzListConeProperties", (PyCFunction)NmzListConeProperties,METH_NOARGS,1295"List all available properties" },1296{ "NmzHilbertSeries", (PyCFunction)NmzHilbertSeries_Outer, METH_VARARGS,1297"Returns Hilbert series, either HSOP or not" },1298{ "NmzGetPolynomial", (PyCFunction)NmzGetPolynomial, METH_VARARGS,1299"Returns grading polynomial" },1300{ "NmzSymmetrizedCone", (PyCFunction)NmzSymmetrizedCone, METH_VARARGS,1301"Returns symmetrized cone" },1302{ "NmzSetNumberOfNormalizThreads", (PyCFunction)NmzSetNumberOfNormalizThreads, METH_VARARGS,1303"Sets the Normaliz thread limit" },1304{ "NmzSetNrCoeffQuasiPol", (PyCFunction)NmzSetNrCoeffQuasiPol, METH_VARARGS,1305"Sets the period bound for the quasi-polynomial" },1306{NULL, } /* Sentinel */1307};130813091310#if PY_MAJOR_VERSION >= 313111312static int PyNormaliz_cpp_traverse(PyObject *m, visitproc visit, void *arg) {1313Py_VISIT(GETSTATE(m)->error);1314return 0;1315}13161317static int PyNormaliz_cpp_clear(PyObject *m) {1318Py_CLEAR(GETSTATE(m)->error);1319return 0;1320}132113221323static struct PyModuleDef moduledef = {1324PyModuleDef_HEAD_INIT,1325"PyNormaliz_cpp",1326NULL,1327sizeof(struct module_state),1328PyNormaliz_cppMethods,1329NULL,1330PyNormaliz_cpp_traverse,1331PyNormaliz_cpp_clear,1332NULL1333};13341335#define INITERROR return NULL13361337PyMODINIT_FUNC PyInit_PyNormaliz_cpp(void)13381339#else1340#define INITERROR return13411342extern "C" void initPyNormaliz_cpp(void)1343#endif1344{1345#if PY_MAJOR_VERSION >= 31346PyObject *module = PyModule_Create(&moduledef);1347#else1348PyObject *module = Py_InitModule("PyNormaliz_cpp", PyNormaliz_cppMethods);1349#endif13501351if (module == NULL)1352INITERROR;1353struct module_state *st = GETSTATE(module);13541355st->error = PyErr_NewException(const_cast<char*>("PyNormaliz_cpp.INITError"), NULL, NULL);1356if (st->error == NULL) {1357Py_DECREF(module);1358INITERROR;1359}13601361NormalizError = PyErr_NewException(const_cast<char*>("Normaliz.error"), NULL, NULL );1362Py_INCREF( NormalizError );1363PyNormaliz_cppError = PyErr_NewException(const_cast<char*>("Normaliz.interface_error"), NULL, NULL );1364Py_INCREF( PyNormaliz_cppError );13651366PyModule_AddObject( module, "error", NormalizError );1367PyModule_AddObject( module, "error", PyNormaliz_cppError );13681369current_interpreter_sigint_handler = PyOS_getsig( SIGINT );13701371#if PY_MAJOR_VERSION >= 31372return module;1373#endif1374}1375137613771378