Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  normaliz.cc   Sprache: C

 
/*
 * NormalizInterface: GAP wrapper for Normaliz
 * Copyright (C) 2014  Sebastian Gutsche, Max Horn, Christof Söger
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */


/*
#! @Chapter Functions
#! @Section YOU FORGOT TO SET A SECTION
*/


#include "gap_all.h" // GAP headers

#if GAP_KERNEL_MAJOR_VERSION < 8
#define BOOL Int
#endif

#define mpn_tdiv_q    // workaround issue with FLINT's inline definition of
                      // mpn_tdiv_q

#include "libnormaliz/libnormaliz.h"

#include <vector>

#include <csignal>
using std::signal;

typedef void (*sighandler_t)(int);

// old versions of libnormaliz (before 2.99.1) did not include such a define
#if !defined(NMZ_RELEASE) || NMZ_RELEASE < 30504
#error Your Normaliz version is to old! Update to 3.5.4 or newer.
#endif

#define FUNC_BEGIN try {

#define FUNC_END                                                             \
    }                                                                        \
    catch (std::exception & e)                                               \
    {                                                                        \
        ErrorQuit(e.what(), 0, 0);                                           \
        return Fail;                                                         \
    }                                                                        \
    catch (const char * a)                                                   \
    {                                                                        \
        ErrorQuit(a, 0, 0);                                                  \
        return Fail;                                                         \
    }                                                                        \
    catch (const std::string & a)                                            \
    {                                                                        \
        ErrorQuit(a.c_str(), 0, 0);                                          \
        return Fail;                                                         \
    }                                                                        \
    catch (...)                                                              \
    {                                                                        \
        ErrorQuit("PANIC: caught general exception", 0, 0);                  \
        return Fail;                                                         \
    }

#define SIGNAL_HANDLER_BEGIN                                                 \
    sighandler_t current_interpreter_sigint_handler =                        \
        signal(SIGINT, signal_handler);                                      \
    try {

#define SIGNAL_HANDLER_END                                                   \
    }                                                                        \
    catch (libnormaliz::InterruptException & e)                              \
    {                                                                        \
        signal(SIGINT, current_interpreter_sigint_handler);                  \
        libnormaliz::nmz_interrupted = false;                                \
        ErrorQuit("computation interrupted", 0, 0);                          \
        return 0;                                                            \
    }                                                                        \
    catch (...)                                                              \
    {                                                                        \
        signal(SIGINT, current_interpreter_sigint_handler);                  \
        throw;                                                               \
    }                                                                        \
    signal(SIGINT, current_interpreter_sigint_handler);


// Paranoia check
#ifdef SYS_IS_64_BIT
#if GMP_LIMB_BITS != 64
#error GAP compiled in 64 bit mode, but GMP limbs are not 64 bit
#endif
#else
#if GMP_LIMB_BITS != 32
#error GAP compiled in 32 bit mode, but GMP limbs are not 32 bit
#endif
#endif


using libnormaliz::Cone;
// using libnormaliz::ConeProperty;
using libnormaliz::ConeProperties;
using libnormaliz::Sublattice_Representation;
using libnormaliz::Type::InputType;

#ifdef LIBNORMALIZ_DYNAMIC_BITSET_H
using libnormaliz::dynamic_bitset;
#else
typedef boost::dynamic_bitset<> dynamic_bitset;
#endif

using std::map;
using std::string;
using std::vector;

static void signal_handler(int signal)
{
    libnormaliz::nmz_interrupted = true;
}

static Obj TheTypeNormalizCone;

static UInt T_NORMALIZ = 0;

static inline bool IS_CONE(Obj o)
{
    return TNUM_OBJ(o) == T_NORMALIZ;
}

template <typename Integer>
static inline void SET_CONE(Obj o, libnormaliz::Cone<Integer> * p)
{
    ADDR_OBJ(o)[0] = reinterpret_cast<Obj>(p);
}

template <typename Integer>
static inline libnormaliz::Cone<Integer> * GET_CONE(Obj o)
{
    return reinterpret_cast<libnormaliz::Cone<Integer> *>(ADDR_OBJ(o)[0]);
}

static Obj NewCone(Cone<mpz_class> * C)
{
    Obj o;
    o = NewBag(T_NORMALIZ, 1 * sizeof(Obj));
    SET_CONE<mpz_class>(o, C);
    return o;
}

static Obj NewProxyCone(Cone<mpz_class> * C, Obj parentCone)
{
    Obj o;
    o = NewBag(T_NORMALIZ, 2 * sizeof(Obj));
    SET_CONE<mpz_class>(o, C);
    ADDR_OBJ(o)[1] = parentCone;
    return o;
}

/* Free function */
static void NormalizFreeFunc(Obj o)
{
    if (SIZE_OBJ(o) != 2 * sizeof(Obj)) {
        delete GET_CONE<mpz_class>(o);
    }
}

/* Type object function for the object */
static Obj NormalizTypeFunc(Obj o)
{
    return TheTypeNormalizCone;
}

static Obj NormalizCopyFunc(Obj o, Int mut)
{
    // Cone objects are mathematically immutable, so
    // we don't need to do anything,
    return o;
}

static void NormalizCleanFunc(Obj o)
{
}

static BOOL NormalizIsMutableObjFuncs(Obj o)
{
    // Cone objects are mathematically immutable.
    return 0L;
}

//
// conversion of various C++ types to GAP objects
//

template <typename T, typename U>
static Obj NmzToGAP(const std::pair<T, U> & in);

template <typename T>
static Obj NmzToGAP(const vector<T> & in);

static Obj NmzToGAP(const dynamic_bitset & in);


static Obj NmzToGAP(const mpz_t x)
{
#if GAP_KERNEL_MAJOR_VERSION >= 7
    return MakeObjInt((const UInt *)x->_mp_d,
                      x->_mp_size);    // added in GAP 4.11
#else
    Obj res;
    Int size = x->_mp_size;
    int sign;
    if (size == 0) {
        return INTOBJ_INT(0);
    }
    else if (size < 0) {
        size = -size;
        sign = -1;
    }
    else {
        sign = +1;
    }
    if (size == 1) {
        res = ObjInt_UInt(x->_mp_d[0]);
        if (sign < 0)
            res = AInvInt(res);
    }
    else {
        size = sizeof(mp_limb_t) * size;
        if (sign > 0)
            res = NewBag(T_INTPOS, size);
        else
            res = NewBag(T_INTNEG, size);
        memcpy(ADDR_INT(res), x->_mp_d, size);
    }
    return res;
#endif
}

static Obj NmzToGAP(unsigned int x)    // key_t = unsigned int
{
    return ObjInt_UInt(x);
}

static Obj NmzToGAP(unsigned long x)    // size_t = unsigned long
{
    return ObjInt_UInt(x);
}

static Obj NmzToGAP(int x)
{
    return ObjInt_Int(x);
}

static Obj NmzToGAP(long x)
{
    return ObjInt_Int(x);
}

static Obj NmzToGAP(const mpz_class x)
{
    return NmzToGAP(x.get_mpz_t());
}

static Obj NmzToGAP(const mpq_class x)
{
    Obj num = NmzToGAP(x.get_num());
    Obj den = NmzToGAP(x.get_den());
    return QUO(num, den);
}

static Obj NmzToGAP(double x)
{
    return NEW_MACFLOAT(x);
}

template <typename T>
static Obj NmzToGAP(const libnormaliz::STANLEYDATA<T> & sd)
{
    Obj ret = NEW_PLIST(T_PLIST, 2);
    ASS_LIST(ret, 1, NmzToGAP(sd.key));
    ASS_LIST(ret, 2, NmzToGAP(sd.offsets));
    return ret;
}

/* TODO: HSOP
 *       There are two representations for Hilbert series in Normaliz,
 * standard and HSOP. Currently, only the standard representation is returned.
 */

static Obj NmzToGAP(const libnormaliz::HilbertSeries & HS)
{
    Obj ret;
    ret = NEW_PLIST(T_PLIST, 3);
    ASS_LIST(ret, 1, NmzToGAP(HS.getNum()));
    ASS_LIST(ret, 2, NmzToGAP(libnormaliz::to_vector(HS.getDenom())));
    ASS_LIST(ret, 3, NmzToGAP(HS.getShift()));
    return ret;
}

static Obj
NmzHilbertQuasiPolynomialToGAP(const libnormaliz::HilbertSeries & HS)
{
    Obj ret = NmzToGAP(HS.getHilbertQuasiPolynomial());
    AddList(ret, NmzToGAP(HS.getHilbertQuasiPolynomialDenom()));
    return ret;
}

//
// generic recursive conversion of C++ containers to GAP objects
//

// convert maps to list of [key,value] pairs
template <typename K, typename V>
static Obj NmzToGAP(const map<K, V> & in)
{
    Obj list = NEW_PLIST(T_PLIST, in.size());
    for (const auto & it : in) {
        AddList(list, NmzToGAP(it));
    }
    return list;
}

template <typename T>
static Obj NmzToGAP(const std::list<T> & in)
{
    Obj list = NEW_PLIST(T_PLIST, in.size());
    for (const auto & it : in) {
        AddList(list, NmzToGAP(it));
    }
    return list;
}

template <typename T>
static Obj NmzToGAP(const vector<T> & in)
{
    const size_t n = in.size();
    Obj          list = NEW_PLIST(T_PLIST, n);
    for (size_t i = 0; i < n; ++i) {
        ASS_LIST(list, i + 1, NmzToGAP(in[i]));
    }
    return list;
}

template <>
Obj NmzToGAP(const vector<bool> & in)
{
    const size_t n = in.size();
    Obj          list = NewBag(T_BLIST, SIZE_PLEN_BLIST(n));
    SET_LEN_BLIST(list, n);
    for (size_t i = 0; i < n; ++i) {
        if (in[i])
            SET_BIT_BLIST(list, i + 1);
    }
    return list;
}

static Obj NmzToGAP(const dynamic_bitset & in)
{
    const size_t n = in.size();
    Obj          list = NewBag(T_BLIST, SIZE_PLEN_BLIST(n));
    SET_LEN_BLIST(list, n);
    for (size_t i = 0; i < n; ++i) {
        if (in.test(i))
            SET_BIT_BLIST(list, i + 1);
    }
    return list;
}

template <typename T, typename U>
static Obj NmzToGAP(const std::pair<T, U> & in)
{
    Obj pair = NEW_PLIST(T_PLIST, 2);
    ASS_LIST(pair, 1, NmzToGAP(in.first));
    ASS_LIST(pair, 2, NmzToGAP(in.second));
    return pair;
}

// TODO: generate a "proper" MatrixObj, once available
template <typename T>
static Obj NmzToGAP(const libnormaliz::Matrix<T> & in)
{
    return NmzToGAP(in.get_elements());
}

template <typename T>
static Obj NmzToGAP(const libnormaliz::SHORTSIMPLEX<T> & in)
{
    Obj simplex = NEW_PREC(5);
    ASS_REC(simplex, RNamName("key"), NmzToGAP(in.key));
    ASS_REC(simplex, RNamName("height"), NmzToGAP(in.height));
    ASS_REC(simplex, RNamName("vol"), NmzToGAP(in.vol));
    ASS_REC(simplex, RNamName("mult"), NmzToGAP(in.mult));
    ASS_REC(simplex, RNamName("Excluded"), NmzToGAP(in.Excluded));
    return simplex;
}

bool GAPToNmz(long & out, Obj x)
{
    if (IS_INTOBJ(x)) {
        out = INT_INTOBJ(x);
        return true;
    }
    else if (TNUM_OBJ(x) == T_INTPOS || TNUM_OBJ(x) == T_INTNEG) {
        UInt size = SIZE_INT(x);
        if (size == 1) {
            out = *ADDR_INT(x);
            if (out < 0)
                return false;    // overflow
            if (TNUM_OBJ(x) == T_INTNEG)
                out = -out;
            return true;
        }
    }
    return false;
}

bool GAPToNmz(mpz_class & out, Obj x)
{
    if (IS_INTOBJ(x)) {
        out = INT_INTOBJ(x);
        return true;
    }
    else if (TNUM_OBJ(x) == T_INTPOS || TNUM_OBJ(x) == T_INTNEG) {
        UInt    size = SIZE_INT(x);
        mpz_ptr m = out.get_mpz_t();
        mpz_realloc2(m, size * GMP_NUMB_BITS);
        memcpy(m->_mp_d, ADDR_INT(x), sizeof(mp_limb_t) * size);
        m->_mp_size = (TNUM_OBJ(x) == T_INTPOS) ? (Int)size : -(Int)size;
        return true;
    }
    return false;
}

bool GAPToNmz(mpq_class & out, Obj x)
{
    if (IS_INTOBJ(x)) {
        out = INT_INTOBJ(x);
        return true;
    }
    else if (TNUM_OBJ(x) == T_INTPOS || TNUM_OBJ(x) == T_INTNEG) {
        out.get_den() = 1;
        return GAPToNmz(out.get_num(), x);
    }
    else if (TNUM_OBJ(x) == T_RAT) {
        return GAPToNmz(out.get_num(), NUM_RAT(x)) &&
               GAPToNmz(out.get_den(), DEN_RAT(x));
    }
    return false;
}

template <typename Number>
static bool GAPToNmz(vector<Number> & out, Obj V)
{
    if (!IS_PLIST(V) || !IS_DENSE_LIST(V))
        return false;
    const int n = LEN_PLIST(V);
    out.resize(n);
    for (int i = 0; i < n; ++i) {
        Obj tmp = ELM_PLIST(V, i + 1);
        if (!GAPToNmz(out[i], tmp))
            return false;
    }
    return true;
}

// take either a GAP string, or a GAP small integer, and try to convert
// it to a Normaliz ConeProperty enum value.
static libnormaliz::ConeProperty::Enum GetConeProperty(Obj prop)
{
    if (IS_STRING_REP(prop))
        return libnormaliz::toConeProperty(CSTR_STRING(prop));
    if (IS_NONNEG_INTOBJ(prop))
        return (libnormaliz::ConeProperty::Enum)UInt8_ObjInt(prop);

    ErrorQuit(" must be a string or a non-negative small integer", 0,
              0);
}

template <typename Integer>
static Obj _NmzConeIntern(Obj input_list)
{
    bool                                      has_polynomial_input = false;
    string                                    polynomial;
    map<InputType, vector<vector<mpq_class>>> input;
    const int                                 n = LEN_PLIST(input_list);
    if (n & 1) {
        throw std::runtime_error(
            "Input list must have even number of elements");
    }
    for (int i = 0; i < n; i += 2) {
        Obj type = ELM_PLIST(input_list, i + 1);
        if (!IS_STRING_REP(type)) {
            throw std::runtime_error(
                "Element " + std::to_string(i + 1) +
                " of the input list must be a type string");
        }
        string type_str(CSTR_STRING(type));
        Obj    M = ELM_PLIST(input_list, i + 2);
        if (type_str.compare("polynomial") == 0) {
            if (!IS_STRING_REP(M)) {
                throw std::runtime_error(
                    "Element " + std::to_string(i + 2) +
                    " of the input list must be a string");
            }
            polynomial = string(CSTR_STRING(M));
            has_polynomial_input = true;
            continue;
        }
        vector<vector<mpq_class>> Mat;
        bool                      okay = GAPToNmz(Mat, M);
        if (!okay) {
            throw std::runtime_error(
                "Element " + std::to_string(i + 2) +
                " of the input list must be an integer matrix");
        }

        input[libnormaliz::to_type(type_str)] = Mat;
    }

    Cone<Integer> * C = new Cone<Integer>(input);
    if (has_polynomial_input) {
        C->setPolynomial(polynomial);
    }
    Obj Cone = NewCone(C);
    return Cone;
}

static Obj Func_NmzCone(Obj self, Obj input_list)
{
    if (!IS_PLIST(input_list) || !IS_DENSE_LIST(input_list))
        ErrorQuit("Input argument must be a list", 0, 0);

    FUNC_BEGIN
    return _NmzConeIntern<mpz_class>(input_list);
    FUNC_END
}

static Obj Func_NmzCompute(Obj self, Obj cone, Obj to_compute)
{
    if (!IS_CONE(cone))
        ErrorQuit(" must be a Normaliz cone", 0, 0);
    if (!IS_PLIST(to_compute) || !IS_DENSE_LIST(to_compute))
        ErrorQuit(" must be a list of strings", 0, 0);

    FUNC_BEGIN
    ConeProperties propsToCompute;
    // we have a list
    const int n = LEN_PLIST(to_compute);

    for (int i = 0; i < n; ++i) {
        Obj prop = ELM_PLIST(to_compute, i + 1);
        if (!IS_STRING_REP(prop)) {
            throw std::runtime_error(
                "Element " + std::to_string(i + 1) +
                " of the input list must be a type string");
        }
        string prop_str(CSTR_STRING(prop));
        propsToCompute.set(libnormaliz::toConeProperty(prop_str));
    }

    Cone<mpz_class> * C = GET_CONE<mpz_class>(cone);

    ConeProperties notComputed;
    SIGNAL_HANDLER_BEGIN
    notComputed = C->compute(propsToCompute);
    SIGNAL_HANDLER_END

    // Cone.compute returns the not computed properties
    // we return a bool, true when everything requested was computed
    return notComputed.none() ? True : False;
    FUNC_END
}


/*
#! @Section Use a NmzCone
#! @Arguments cone property
#! @Returns whether the cone has already computed the given property
#! @Description
#! See <Ref Func="NmzConeProperty"/> for a list of recognized properties.
#!
#! @InsertChunk NmzHasConeProperty_example
DeclareGlobalFunction("NmzHasConeProperty");
*/

static Obj FuncNmzHasConeProperty(Obj self, Obj cone, Obj prop)
{
    if (!IS_CONE(cone))
        ErrorQuit(" must be a Normaliz cone", 0, 0);

    libnormaliz::ConeProperty::Enum p = GetConeProperty(prop);

    FUNC_BEGIN
    Cone<mpz_class> * C = GET_CONE<mpz_class>(cone);
    return C->isComputed(p) ? True : False;
    FUNC_END
}

static Obj Func_NmzConePropertiesNamesRecord(Obj self)
{
    FUNC_BEGIN

    Obj M = NEW_PREC(libnormaliz::ConeProperty::EnumSize);

    for (int i = 0; i < libnormaliz::ConeProperty::EnumSize; ++i) {
        libnormaliz::ConeProperty::Enum p =
            (libnormaliz::ConeProperty::Enum)i;

#if NMZ_RELEASE >= 30500
        // skip internal control properties
        if (
#if NMZ_RELEASE < 30800
            p == libnormaliz::ConeProperty::ExplicitHilbertSeries ||
#endif
            p == libnormaliz::ConeProperty::NakedDual)
            continue;
#endif
        AssPRec(M, RNamName(libnormaliz::toString(p).c_str()),
                ObjInt_UInt8(p));
    }
    return M;

    FUNC_END
}

/*
#! @Section Use a NmzCone
#! @Arguments cone
#! @Returns a list of strings representing the known (computed) cone
#!   properties
#! @Description
#! Given a Normaliz cone object, return a list of all properties already
#! computed for the cone.
#!
#! @InsertChunk NmzKnownConeProperties_example
DeclareGlobalFunction("NmzKnownConeProperties");
*/

static Obj FuncNmzKnownConeProperties(Obj self, Obj cone)
{
    if (!IS_CONE(cone))
        ErrorQuit(" must be a Normaliz cone", 0, 0);

    FUNC_BEGIN

    size_t n = 0;
    Obj    M = NEW_PLIST(T_PLIST, libnormaliz::ConeProperty::EnumSize);
    Cone<mpz_class> * C = GET_CONE<mpz_class>(cone);

    // FIXME: This code could be a lot simpler if there was
    // a Cone method for reading the value of is_Computed.
    for (int i = 0; i < libnormaliz::ConeProperty::EnumSize; ++i) {
        libnormaliz::ConeProperty::Enum p =
            (libnormaliz::ConeProperty::Enum)i;

        // skip internal control properties
        if (
#if NMZ_RELEASE < 30800
            p == libnormaliz::ConeProperty::ExplicitHilbertSeries ||
#endif
            p == libnormaliz::ConeProperty::NakedDual)
            continue;

        if (C->isComputed(p)) {
            string prop_name(libnormaliz::toString(p));

            ASS_LIST(M, ++n, MakeImmString(prop_name.c_str()));
            if (p == libnormaliz::ConeProperty::HilbertSeries) {
                const libnormaliz::HilbertSeries & HS = C->getHilbertSeries();
                HS.computeHilbertQuasiPolynomial();
                if (HS.isHilbertQuasiPolynomialComputed()) {
                    ASS_LIST(M, ++n, MakeImmString("HilbertQuasiPolynomial"));
                }
            }
        }
    }
    SORT_LIST(M);
    return M;

    FUNC_END
}

template <typename Integer>
static Obj _NmzConePropertyImpl(Obj cone, libnormaliz::ConeProperty::Enum p)
{
    Cone<Integer> * C = GET_CONE<Integer>(cone);
    ConeProperties  notComputed;

    SIGNAL_HANDLER_BEGIN
    notComputed = C->compute(ConeProperties(p));
    SIGNAL_HANDLER_END

#if NMZ_RELEASE >= 30700
    // workaround a bug where computing HilbertQuasiPolynomial after
    // HilbertSeries was already computed returned notComputed equal to
    // NoGradingDenom, even though of course the quasi polynomial was
    // available.
    notComputed.reset(libnormaliz::ConeProperty::NoGradingDenom);
#endif
    if (notComputed.any()) {
        ErrorQuit("Failed to compute %s, missing properties: %s",
                  (Int)(libnormaliz::toString(p).c_str()),
                  (Int)(libnormaliz::toString(notComputed).c_str()));
        return Fail;
    }

    // workaround bug in certain Normaliz versions, where the output type for
    // ClassGroups is reported as libnormaliz::OutputType::Vector, but calling
    // getVectorConeProperty on it produces an error
    if (p == libnormaliz::ConeProperty::ClassGroup)
        return NmzToGAP(C->getClassGroup());

#if NMZ_RELEASE >= 30700 && NMZ_RELEASE < 30703
    // workaround bug where getMachineIntegerConeProperty does not support
    // NumberLatticePoints
    if (p == libnormaliz::ConeProperty::NumberLatticePoints)
        return NmzToGAP(C->getNumberLatticePoints());
#endif

#if NMZ_RELEASE < 30804
    // workaround: these two properties are marked as having output type
    // "void"
    if (p == libnormaliz::ConeProperty::IsTriangulationNested)
        return C->isTriangulationNested() ? True : False;
    if (p == libnormaliz::ConeProperty::IsTriangulationPartial)
        return C->isTriangulationPartial() ? True : False;
#endif

    switch (libnormaliz::output_type(p)) {
    case libnormaliz::OutputType::Matrix:
        // TODO: switch to getMatrixConePropertyMatrix ?
        return NmzToGAP(C->getMatrixConeProperty(p));

    case libnormaliz::OutputType::MatrixFloat:
        // TODO: switch to getFloatMatrixConePropertyMatrix ?
        return NmzToGAP(C->getFloatMatrixConeProperty(p));

    case libnormaliz::OutputType::Vector:
        return NmzToGAP(C->getVectorConeProperty(p));

    case libnormaliz::OutputType::Integer:
        return NmzToGAP(C->getIntegerConeProperty(p));

    case libnormaliz::OutputType::GMPInteger:
        return NmzToGAP(C->getGMPIntegerConeProperty(p));

    case libnormaliz::OutputType::Rational:
        return NmzToGAP(C->getRationalConeProperty(p));

#if NMZ_RELEASE >= 30700
    case libnormaliz::OutputType::FieldElem:
        throw "OutputType::FieldElem not yet supported";
#endif

    case libnormaliz::OutputType::Float:
        return NmzToGAP(C->getFloatConeProperty(p));

    case libnormaliz::OutputType::MachineInteger:
        return NmzToGAP(C->getMachineIntegerConeProperty(p));

    case libnormaliz::OutputType::Bool:
        return C->getBooleanConeProperty(p) ? True : False;

    case libnormaliz::OutputType::Complex:
        // more complex data structures are handled below
        break;

    case libnormaliz::OutputType::Void:
        // throw "cone property is input-only";
        return Fail;

    default:
        throw "unsupported output_type";
    }

    switch (p) {
#if NMZ_RELEASE >= 30703
    case libnormaliz::ConeProperty::AmbientAutomorphisms:
    case libnormaliz::ConeProperty::Automorphisms:
    case libnormaliz::ConeProperty::CombinatorialAutomorphisms:
    case libnormaliz::ConeProperty::EuclideanAutomorphisms:
    case libnormaliz::ConeProperty::RationalAutomorphisms:
        throw "querying automorphisms not yet supported";
#endif

    case libnormaliz::ConeProperty::ConeDecomposition:
#if NMZ_RELEASE >= 30810
        return NmzToGAP(C->getConeDecomposition());
#else
        return NmzToGAP(C->getOpenFacets());
#endif

#if NMZ_RELEASE >= 30600
    case libnormaliz::ConeProperty::EhrhartQuasiPolynomial:
#if NMZ_RELEASE >= 30700
        return NmzHilbertQuasiPolynomialToGAP(C->getEhrhartSeries());
#else
        throw "Extracting EhrhartQuasiPolynomial requires Normaliz >= 3.7.0";
#endif
#endif

    case libnormaliz::ConeProperty::EhrhartSeries:
#if NMZ_RELEASE >= 30700
        return NmzToGAP(C->getEhrhartSeries());
#else
        throw "Extracting EhrhartSeries requires Normaliz >= 3.7.0";
#endif

#if NMZ_RELEASE >= 30700
    case libnormaliz::ConeProperty::FaceLattice:
        return NmzToGAP(C->getFaceLattice());

    case libnormaliz::ConeProperty::FVector:
        return NmzToGAP(C->getFVector());
#endif

    case libnormaliz::ConeProperty::Incidence:
        return NmzToGAP(C->getIncidence());

    case libnormaliz::ConeProperty::HilbertQuasiPolynomial:
        return NmzHilbertQuasiPolynomialToGAP(C->getHilbertSeries());

    case libnormaliz::ConeProperty::HilbertSeries:
        return NmzToGAP(C->getHilbertSeries());

    case libnormaliz::ConeProperty::InclusionExclusionData:
        return NmzToGAP(C->getInclusionExclusionData());

    case libnormaliz::ConeProperty::IntegerHull:
        return NewProxyCone(&(C->getIntegerHullCone()), cone);

    case libnormaliz::ConeProperty::ProjectCone:
        return NewProxyCone(&(C->getProjectCone()), cone);

    case libnormaliz::ConeProperty::Sublattice:
        return _NmzBasisChangeIntern(C);

    case libnormaliz::ConeProperty::StanleyDec:
        return NmzToGAP(C->getStanleyDec());

    case libnormaliz::ConeProperty::Triangulation:
        return NmzToGAP(C->getTriangulation());

    case libnormaliz::ConeProperty::WeightedEhrhartQuasiPolynomial:
        return NmzHilbertQuasiPolynomialToGAP(
            C->getWeightedEhrhartSeries().first);

    case libnormaliz::ConeProperty::WeightedEhrhartSeries:
        return NmzToGAP(C->getWeightedEhrhartSeries());

    default:
        throw "unsupported cone property " + libnormaliz::toString(p);
    }

    return Fail;
}

static Obj Func_NmzConeProperty(Obj self, Obj cone, Obj prop)
{
    if (!IS_CONE(cone))
        ErrorQuit(" must be a Normaliz cone", 0, 0);

    libnormaliz::ConeProperty::Enum p = GetConeProperty(prop);

    FUNC_BEGIN
    return _NmzConePropertyImpl<mpz_class>(cone, p);
    FUNC_END
}


/*
#! @Section Use a NmzCone
#! @Arguments verboseFlag
#! @Returns the previous verbosity
#! @Description
#! Set the global default verbosity state in libnormaliz.
#! This will influence all NmzCone created afterwards, but not any existing
#! ones.
#!
#! See also <Ref Func="NmzSetVerbose"/>
DeclareGlobalFunction("NmzSetVerboseDefault");
*/

static Obj FuncNmzSetVerboseDefault(Obj self, Obj value)
{
    if (value != True && value != False)
        ErrorQuit(" must be a boolean value", 0, 0);
    FUNC_BEGIN
    return libnormaliz::setVerboseDefault(value == True) ? True : False;
    FUNC_END
}


/*
#! @Arguments cone verboseFlag
#! @Returns the previous verbosity
#! @Description
#! Set the verbosity state for a cone.
#!
#! See also <Ref Func="NmzSetVerboseDefault"/>
DeclareGlobalFunction("NmzSetVerbose");
*/

static Obj FuncNmzSetVerbose(Obj self, Obj cone, Obj value)
{
    if (!IS_CONE(cone))
        ErrorQuit(" must be a Normaliz cone", 0, 0);
    if (value != True && value != False)
        ErrorQuit(" must be a boolean value", 0, 0);
    bool old_value;

    FUNC_BEGIN
    Cone<mpz_class> * C = GET_CONE<mpz_class>(cone);
    old_value = C->setVerbose(value == True);
    return old_value ? True : False;
    FUNC_END
}

/*
#! @Section Cone properties
*/



template <typename Integer>
static Obj _NmzBasisChangeIntern(Cone<Integer> * C)
{
    Sublattice_Representation<Integer> bc;
    SIGNAL_HANDLER_BEGIN
    bc = C->getSublattice();
    SIGNAL_HANDLER_END

    Obj res = NEW_PLIST(T_PLIST, 3);
    ASS_LIST(res, 1, NmzToGAP(bc.getEmbedding()));
    ASS_LIST(res, 2, NmzToGAP(bc.getProjection()));
    ASS_LIST(res, 3, NmzToGAP(bc.getAnnihilator()));
    // Dim, Rank, Equations and Congruences are already covered by special
    // functions The index is not always computed and not so relevant
    return res;
}


static Obj Func_NmzVersion(Obj self)
{
    Obj res = NEW_PLIST(T_PLIST, 3);
    ASS_LIST(res, 1, INTOBJ_INT(NMZ_VERSION_MAJOR));
    ASS_LIST(res, 2, INTOBJ_INT(NMZ_VERSION_MINOR));
    ASS_LIST(res, 3, INTOBJ_INT(NMZ_VERSION_PATCH));
    return res;
}

// GVAR_FUNC in GAP 4.9 and 4.10 triggers warnings when used in C++ code; so
// we force it to the definition from GAP 4.11
#undef GVAR_FUNC
#define GVAR_FUNC(name, nargs, args)                                         \
    {                                                                        \
#name, nargs, args, (ObjFunc)Func##name, __FILE__ ":" #name          \
    }

// Table of functions to export
static StructGVarFunc GVarFuncs[] = {
    GVAR_FUNC(_NmzCone, 1, "list"),

    GVAR_FUNC(_NmzCompute, 2, "cone, props"),
    GVAR_FUNC(NmzSetVerboseDefault, 1, "value"),
    GVAR_FUNC(NmzSetVerbose, 2, "cone, value"),

    GVAR_FUNC(NmzHasConeProperty, 2, "cone, prop"),
    GVAR_FUNC(_NmzConeProperty, 2, "cone, prop"),
    GVAR_FUNC(NmzKnownConeProperties, 1, "cone"),
    GVAR_FUNC(_NmzConePropertiesNamesRecord, 0, ""),

    GVAR_FUNC(_NmzVersion, 0, ""),

    { 0 } /* Finish with an empty entry */

};

// initialise kernel data structures
static Int InitKernel(StructInitInfo * module)
{
    /* init filters and functions                                          */
    InitHdlrFuncsFromTable(GVarFuncs);

    InitCopyGVar("TheTypeNormalizCone", &TheTypeNormalizCone);

    T_NORMALIZ = RegisterPackageTNUM("NormalizCone", NormalizTypeFunc);

    InitMarkFuncBags(T_NORMALIZ, &MarkAllSubBags);
    InitFreeFuncBag(T_NORMALIZ, &NormalizFreeFunc);

    CopyObjFuncs[T_NORMALIZ] = &NormalizCopyFunc;
    CleanObjFuncs[T_NORMALIZ] = &NormalizCleanFunc;
    IsMutableObjFuncs[T_NORMALIZ] = &NormalizIsMutableObjFuncs;

    /* return success                                                      */
    return 0;
}

// initialise library data structures
static Int InitLibrary(StructInitInfo * module)
{
    /* init filters and functions */
    InitGVarFuncsFromTable(GVarFuncs);

    /* return success                                                      */
    return 0;
}

// table of init functions
static StructInitInfo module = {
    /* type        = */ MODULE_DYNAMIC,
    /* name        = */ "Normaliz",
    /* revision_c  = */ 0,
    /* revision_h  = */ 0,
    /* version     = */ 0,
    /* crc         = */ 0,
    /* initKernel  = */ InitKernel,
    /* initLibrary = */ InitLibrary,
    /* checkInit   = */ 0,
    /* preSave     = */ 0,
    /* postSave    = */ 0,
    /* postRestore = */ 0
};

extern "C" StructInitInfo * Init__Dynamic(void)
{
    return &module;
}

100%


¤ Dauer der Verarbeitung: 0.48 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge
 




SSL  | sichere Verbindung  | rahmenlose Ansicht  | Kontakt  | Seitenstruktur  | © 2026 JDD |