From 0b5a8c5de0aebd607875b4df35b56feb63f21dd4 Mon Sep 17 00:00:00 2001 From: Sebastian Gutsche Date: Tue, 14 May 2019 22:48:52 +0200 Subject: [PATCH 01/16] First version of caller - WIP --- .gitignore | 1 + deps/build.jl | 3 + deps/parselibs.jl | 46 ++++ deps/src/CMakeLists.txt | 4 +- deps/src/caller.cpp | 358 ++++++++++++++++++++++++++++++ deps/src/caller.h | 8 + deps/src/coeffs.cpp | 7 +- deps/src/ideals.cpp | 4 +- deps/src/singular.cpp | 90 ++++---- src/LibSingular.jl | 2 + src/Meta.jl | 34 +++ src/Singular.jl | 11 + src/caller.jl | 189 ++++++++++++++++ src/ideal/ideal.jl | 20 +- src/module/ModuleTypes.jl | 24 ++ src/module/module.jl | 12 +- src/number/NumberTypes.jl | 2 +- src/poly/PolyTypes.jl | 7 + src/poly/poly.jl | 4 + src/resolution/ResolutionTypes.jl | 11 +- src/resolution/resolution.jl | 48 ++-- test/caller-test.jl | 46 ++++ test/runtests.jl | 21 +- 23 files changed, 849 insertions(+), 103 deletions(-) create mode 100644 deps/parselibs.jl create mode 100644 deps/src/caller.cpp create mode 100644 deps/src/caller.h create mode 100644 src/Meta.jl create mode 100644 src/caller.jl create mode 100644 test/caller-test.jl diff --git a/.gitignore b/.gitignore index b064b7d66..0ef780992 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ docs/build *.jl.*.cov *.jl.mem .gitattributes +/src/libraryfuncdictionary.jl diff --git a/deps/build.jl b/deps/build.jl index f6bd3dba4..0a4d72a3a 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -98,6 +98,7 @@ withenv("CPP_FLAGS"=>"-I$vdir/include", "LD_LIBRARY_PATH"=>"$vdir/lib:$nemodir/l cmd = split( """ $srcs/configure + --with-libparse --prefix=$vdir --libdir=$vdir/lib --disable-static @@ -152,3 +153,5 @@ print("Running cmake") run(`make VERBOSE=1`) run(`make install`) +include("parselibs.jl") + diff --git a/deps/parselibs.jl b/deps/parselibs.jl new file mode 100644 index 000000000..2510a9295 --- /dev/null +++ b/deps/parselibs.jl @@ -0,0 +1,46 @@ +function execute(cmd::Cmd) + out = Pipe() + err = Pipe() + + process = run(pipeline(ignorestatus(cmd), stdout = out, stderr = err)) + close(out.in) + close(err.in) + + (stdout = String(read(out)), + stderr = String(read(err)), + code = process.exitcode) +end + +libparsepath = abspath(joinpath(@__DIR__, "..", "local", "bin", "libparse")) + +library_dir = "" + +if haskey(ENV, "SINGULAR_LIBRARY_DIR") + library_dir = ENV["SINGULAR_LIBRARY_DIR"] +else + library_dir = abspath(joinpath(@__DIR__, "..", "local", "share", "singular", "LIB")) +end + +filenames = filter(x -> endswith(x, ".lib"), readdir(library_dir)) + +output_filename = abspath(joinpath(@__DIR__, "..", "src", "libraryfuncdictionary.jl")) + +open(output_filename, "w") do outputfile + println(outputfile, "libraryfunctiondictionary = Dict(") + for i in filenames + full_path = joinpath(library_dir, i) + libs = execute(`$libparsepath $full_path`) + if libs.stderr != "" + error("from libparse: $(libs.stderr)") + end + libs_splitted = split(libs.stdout,"\n")[4:end-1] + libs_splitted = [ split(i," ") for i in libs_splitted ] + libs_splitted = [ [ j for j in i if j != ""] for i in libs_splitted ] + println(outputfile, ":$(i[1:end - 4]) => [") + for j in libs_splitted + println(outputfile, """[ "$(j[1])", "$(j[3])" ],""") + end + println(outputfile, "],\n") + end + println(outputfile, ")\n") +end diff --git a/deps/src/CMakeLists.txt b/deps/src/CMakeLists.txt index acd8e8000..26c9c4d27 100644 --- a/deps/src/CMakeLists.txt +++ b/deps/src/CMakeLists.txt @@ -10,10 +10,10 @@ include_directories(${nemo_includes}) include_directories(${singular_includes}) include_directories(${singular_includes}/singular) -SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14" ) +SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -g" ) SET( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L${JULIA_LIB_DIR} -Wl,-rpath,${JULIA_LIB_DIR} -L${singular_libdir} -Wl,-rpath,${singular_libdir}" ) -add_library(singularwrap SHARED singular.cpp rings.cpp coeffs.cpp ideals.cpp matrices.cpp) +add_library(singularwrap SHARED singular.cpp rings.cpp coeffs.cpp ideals.cpp matrices.cpp caller.cpp) target_link_libraries(singularwrap JlCxx::cxxwrap_julia -ljulia "-lSingular -lpolys -lsingular_resources -lfactory -lomalloc -ldl") install(TARGETS diff --git a/deps/src/caller.cpp b/deps/src/caller.cpp new file mode 100644 index 000000000..b606a10a4 --- /dev/null +++ b/deps/src/caller.cpp @@ -0,0 +1,358 @@ +#include "caller.h" + +#include +#include +#include +#include +#include + +// #include + +static jl_value_t * jl_int64_vector_type; +static jl_value_t * jl_int64_matrix_type; +static jl_value_t * jl_singular_number_type; +static jl_value_t * jl_singular_poly_type; +static jl_value_t * jl_singular_ring_type; +static jl_value_t * jl_singular_ideal_type; +static jl_value_t * jl_singular_matrix_type; +static jl_value_t * jl_singular_bigint_type; +static jl_value_t * jl_singular_bigintmat_type; +static jl_value_t * jl_singular_map_type; +static jl_value_t * jl_singular_resolution_type; +static jl_value_t * jl_singular_vector_type; + +static jl_value_t * get_type_mapper() +{ + std::vector> types = { + std::pair(BIGINT_CMD, "BIGINT_CMD"), + std::pair(NUMBER_CMD, "NUMBER_CMD"), + std::pair(RING_CMD, "RING_CMD"), + std::pair(POLY_CMD, "POLY_CMD"), + std::pair(IDEAL_CMD, "IDEAL_CMD"), + std::pair(INT_CMD, "INT_CMD"), + std::pair(STRING_CMD, "STRING_CMD"), + std::pair(LIST_CMD, "LIST_CMD"), + std::pair(INTMAT_CMD, "INTMAT_CMD"), + std::pair(BIGINTMAT_CMD, "BIGINTMAT_CMD"), + std::pair(MAP_CMD, "MAP_CMD"), + std::pair(RESOLUTION_CMD, "RESOLUTION_CMD"), + std::pair(MODUL_CMD, "MODUL_CMD"), + std::pair(VECTOR_CMD, "VECTOR_CMD"), + std::pair(INTVEC_CMD, "INTVEC_CMD")}; + + jl_array_t * return_array = + jl_alloc_array_1d(jl_array_any_type, types.size()); + + for (int i = 0; i < types.size(); i++) { + jl_array_t * current_return = jl_alloc_array_1d(jl_array_any_type, 2); + jl_arrayset(current_return, jl_box_int64(types[i].first), 0); + jl_arrayset(current_return, + reinterpret_cast( + jl_symbol(types[i].second.c_str())), + 1); + jl_arrayset(return_array, + reinterpret_cast(current_return), i); + } + return reinterpret_cast(return_array); +} + +static void initialize_jl_c_types(jl_value_t * module_value) +{ + jl_module_t * module = reinterpret_cast(module_value); + jl_int64_vector_type = + jl_apply_array_type((jl_value_t *)jl_int64_type, 1); + jl_int64_matrix_type = + jl_apply_array_type((jl_value_t *)jl_int64_type, 2); + jl_singular_number_type = jl_get_global(module, jl_symbol("number")); + jl_singular_poly_type = jl_get_global(module, jl_symbol("poly")); + jl_singular_ring_type = jl_get_global(module, jl_symbol("ring")); + jl_singular_ideal_type = jl_get_global(module, jl_symbol("ideal")); + jl_singular_matrix_type = jl_get_global(module, jl_symbol("ip_smatrix")); + jl_singular_bigint_type = + jl_get_global(module, jl_symbol("__mpz_struct")); + jl_singular_bigintmat_type = + jl_get_global(module, jl_symbol("bigintmat")); + jl_singular_map_type = jl_get_global(module, jl_symbol("sip_smap")); + jl_singular_resolution_type = + jl_get_global(module, jl_symbol("resolvente")); +} + +static inline void * get_ptr_from_cxxwrap_obj(jl_value_t * obj) +{ + return *reinterpret_cast(obj); +} + +// Safe way +// void* get_ptr_from_cxxwrap_obj(jl_value_t* obj){ +// return jl_unbox_voidpointer(jl_get_field(obj,"cpp_object")); +// } + +jl_value_t * intvec_to_jl_array(intvec * v) +{ + int size = v->length(); + jl_array_t * result = jl_alloc_array_1d(jl_int64_vector_type, size); + int * v_content = v->ivGetVec(); + for (int i = 0; i < size; i++) { + jl_arrayset(result, jl_box_int64(static_cast(v_content[i])), + i); + } + return reinterpret_cast(result); +} + +jl_value_t * intmat_to_jl_array(intvec * v) +{ + int rows = v->rows(); + int cols = v->cols(); + jl_array_t * result = jl_alloc_array_2d(jl_int64_matrix_type, rows, cols); + int64_t * result_ptr = reinterpret_cast jl_array_data(result); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + result_ptr[j + (i * cols)] = IMATELEM(*v, i, j); + } + } + return reinterpret_cast(result); +} + +void * jl_array_to_intvec(jl_value_t * array_val) +{ + jl_array_t * array = reinterpret_cast(array_val); + int size = jl_array_len(array); + intvec * result = new intvec(size); + int * result_content = result->ivGetVec(); + for (int i = 0; i < size; i++) { + result_content[i] = + static_cast(jl_unbox_int64(jl_arrayref(array, i))); + } + return reinterpret_cast(result); +} + +void * jl_array_to_intmat(jl_value_t * array_val) +{ + jl_array_t * array = reinterpret_cast(array_val); + int rows = jl_array_dim(array, 0); + int cols = jl_array_dim(array, 1); + intvec * result = new intvec(rows, cols, 0); + int64_t * array_data = reinterpret_cast(jl_array_data(array)); + int * vec_data = result->ivGetVec(); + for (int i = 0; i < cols; i++) { + for (int j = 0; j < rows; j++) { + IMATELEM(*result, i + 1, j + 1) = + static_cast(array_data[j + (i * rows)]); + } + } + return reinterpret_cast(result); +} + +static void * get_ring_ref(ring r) +{ + r->ref++; + return reinterpret_cast(r); +} + +static jl_value_t * copy_polyptr_to_void(poly p, ring r) +{ + poly p_copy = p_Copy(p, r); + return jl_box_voidpointer(reinterpret_cast(p_copy)); +} + +static jl_value_t * copy_idealptr_to_void(ideal i, ring r) +{ + ideal i_copy = id_Copy(i, r); + return jl_box_voidpointer(reinterpret_cast(i_copy)); +} + +static void * copy_string_to_void(std::string s) +{ + return reinterpret_cast(omStrDup(s.c_str())); +} + +bool translate_singular_type(jl_value_t * obj, + void ** args, + int * argtypes, + int i) +{ + jl_array_t * array = reinterpret_cast(obj); + int cmd = static_cast(jl_unbox_int64(jl_arrayref(array, 0))); + void * arg = jl_unbox_voidpointer(jl_arrayref(array, 1)); + args[i] = arg; + argtypes[i] = cmd; + return true; +} + +jl_value_t * get_julia_type_from_sleftv(leftv ret) +{ + jl_array_t * result = jl_alloc_array_1d(jl_array_any_type, 3); + jl_arrayset(result, jl_false, 0); + jl_arrayset(result, jl_box_voidpointer(ret->data), 1); + ret->data = 0; + jl_arrayset(result, jl_box_int64(ret->Typ()), 2); + ret->rtyp = 0; + return reinterpret_cast(result); +} + +jl_value_t * get_ring_content(ring r) +{ + // count elements + idhdl h = r->idroot; + int nr = 0; + while (h != NULL) { + nr++; + h = IDNEXT(h); + } + jl_array_t * result = jl_alloc_array_1d(jl_array_any_type, nr); + h = r->idroot; + nr = 0; + while (h != NULL) { + jl_array_t * current = jl_alloc_array_1d(jl_array_any_type, 3); + jl_arrayset(current, jl_box_int64(IDTYP(h)), 0); + jl_arrayset(current, + reinterpret_cast(jl_symbol(IDID(h))), 1); + jl_arrayset(current, jl_box_voidpointer(IDDATA(h)), 2); + jl_arrayset(result, reinterpret_cast(current), nr); + h = IDNEXT(h); + nr++; + } + return reinterpret_cast(result); +} + +jl_value_t * call_singular_library_procedure( + std::string s, ring r, jlcxx::ArrayRef arguments) +{ + int len = arguments.size(); + void * args[len]; + int argtypes[len + 1]; + argtypes[len] = 0; + for (int i = 0; i < len; i++) { + bool result = + translate_singular_type(arguments[i], args, argtypes, i); + if (!result) { + jl_error("Could not convert argument"); + } + } + BOOLEAN err; + jl_value_t * retObj; + leftv ret = ii_CallLibProcM(s.c_str(), args, argtypes, r, err); + if (err) { + jl_error("Could not call function"); + } + if (ret->next != NULL) { + int len = ret->listLength(); + jl_array_t * list = jl_alloc_array_1d(jl_array_any_type, len + 1); + jl_arrayset(list, jl_true, 0); + for (int i = 0; i < len; ++i) { + leftv next = ret->next; + ret->next = 0; + jl_arrayset(list, get_julia_type_from_sleftv(ret), i + 1); + if (i > 0) + omFreeBin(ret, sleftv_bin); + ret = next; + } + retObj = reinterpret_cast(list); + } + else { + retObj = get_julia_type_from_sleftv(ret); + omFreeBin(ret, sleftv_bin); + } + return retObj; +} + +jl_value_t * call_singular_library_procedure_wo_ring( + std::string name, jlcxx::ArrayRef arguments) +{ + return call_singular_library_procedure(name, NULL, arguments); +} + +jl_value_t * convert_nested_list(void * l_void) +{ + lists l = reinterpret_cast(l_void); + int len = lSize(l) + 1; + jl_array_t * result_array = jl_alloc_array_1d(jl_array_any_type, len); + for (int i = 0; i < len; i++) { + leftv current = &(l->m[i]); + if (current->Typ() == LIST_CMD) { + jl_arrayset( + result_array, + convert_nested_list(reinterpret_cast(current->data)), + i); + } + else { + jl_arrayset(result_array, get_julia_type_from_sleftv(current), i); + } + } + return reinterpret_cast(result_array); +} + +void * create_syStrategy_data(syStrategy res, ring o) +{ + const ring origin = currRing; + rChangeCurrRing(o); + syStrategy temp = syCopy(res); + rChangeCurrRing(origin); + return reinterpret_cast(temp); +} + +void singular_define_caller(jlcxx::Module & Singular) +{ + Singular.method("load_library", [](std::string name) { + char * plib = iiConvName(name.c_str()); + idhdl h = ggetid(plib); + omFree(plib); + if (h == NULL) { + BOOLEAN bo = iiLibCmd(omStrDup(name.c_str()), TRUE, TRUE, FALSE); + if (bo) + return jl_false; + } + return jl_true; + }); + Singular.method("call_singular_library_procedure", + &call_singular_library_procedure); + Singular.method("call_singular_library_procedure", + &call_singular_library_procedure_wo_ring); + Singular.method("get_type_mapper", &get_type_mapper); + Singular.method("initialize_jl_c_types", &initialize_jl_c_types); + + + Singular.method("NUMBER_CMD_CASTER", + [](void * obj) { return reinterpret_cast(obj); }); + Singular.method("RING_CMD_CASTER", + [](void * obj) { return reinterpret_cast(obj); }); + Singular.method("POLY_CMD_CASTER", + [](void * obj) { return reinterpret_cast(obj); }); + Singular.method("IDEAL_CMD_CASTER", + [](void * obj) { return reinterpret_cast(obj); }); + Singular.method("INT_CMD_CASTER", [](void * obj) { + return jl_box_int64(reinterpret_cast(obj)); + }); + Singular.method("STRING_CMD_CASTER", [](void * obj) { + return std::string(reinterpret_cast(obj)); + }); + Singular.method("INTVEC_CMD_CASTER", [](void * obj) { + return intvec_to_jl_array(reinterpret_cast(obj)); + }); + Singular.method("INTMAT_CMD_CASTER", [](void * obj) { + return intmat_to_jl_array(reinterpret_cast(obj)); + }); + Singular.method("BIGINT_CMD_CASTER", [](void * obj) { + return reinterpret_cast<__mpz_struct *>(obj); + }); + Singular.method("BIGINTMAT_CMD_CASTER", [](void * obj) { + return reinterpret_cast(obj); + }); + Singular.method("MAP_CMD_CASTER", [](void * obj) { + return reinterpret_cast(obj); + }); + Singular.method("RESOLUTION_CMD_CASTER", [](void * obj) { + return reinterpret_cast(obj); + }); + Singular.method("LIST_CMD_TRAVERSAL", &convert_nested_list); + Singular.method("get_ring_content", &get_ring_content); + Singular.method("get_ring_ref", &get_ring_ref); + Singular.method("copy_polyptr_to_void", ©_polyptr_to_void); + Singular.method("copy_idealptr_to_void", ©_idealptr_to_void); + Singular.method("jl_array_to_intvec", &jl_array_to_intvec); + Singular.method("jl_array_to_intmat", &jl_array_to_intmat); + Singular.method("copy_string_to_void", ©_string_to_void); + + Singular.method("create_syStrategy_data", &create_syStrategy_data); + +} diff --git a/deps/src/caller.h b/deps/src/caller.h new file mode 100644 index 000000000..bf49c67da --- /dev/null +++ b/deps/src/caller.h @@ -0,0 +1,8 @@ +#ifndef CALLER_INCLUDE +#define CALLER_INCLUDE + +#include "includes.h" + +void singular_define_caller(jlcxx::Module &); + +#endif diff --git a/deps/src/coeffs.cpp b/deps/src/coeffs.cpp index 7d1ded8ae..b7457f2b3 100644 --- a/deps/src/coeffs.cpp +++ b/deps/src/coeffs.cpp @@ -44,11 +44,10 @@ void singular_define_coeffs(jlcxx::Module & Singular) } }); - Singular.method("n_Delete_Q", [](void * n, coeffs cf) { - number tt = reinterpret_cast(n); - number * t = &tt; + Singular.method("n_Delete_Q", [](snumber * n, coeffs cf) { + ; if (n != NULL) { - n_Delete(t, cf); + n_Delete(&n, cf); } }); diff --git a/deps/src/ideals.cpp b/deps/src/ideals.cpp index a174bc635..05cc9f2a3 100644 --- a/deps/src/ideals.cpp +++ b/deps/src/ideals.cpp @@ -12,7 +12,7 @@ auto id_sres_helper(sip_sideal * m, int n, ring R) r = s->fullres; minimal = false; } - return std::make_tuple(reinterpret_cast(r), s->length, minimal); + return std::make_tuple(s, minimal); } @@ -28,7 +28,7 @@ auto id_fres_helper(sip_sideal * I, int n, std::string method, ring R) r = s->fullres; minimal = false; } - return std::make_tuple(reinterpret_cast(r), s->length, minimal); + return std::make_tuple(s, minimal); } diff --git a/deps/src/singular.cpp b/deps/src/singular.cpp index 932d424b1..f3fef6fc6 100644 --- a/deps/src/singular.cpp +++ b/deps/src/singular.cpp @@ -4,6 +4,7 @@ #include "rings.h" #include "ideals.h" #include "matrices.h" +#include "caller.h" static std::string singular_return; static std::string singular_error; @@ -48,6 +49,7 @@ JLCXX_MODULE define_julia_module(jlcxx::Module & Singular) Singular.add_type("ip_smatrix"); Singular.add_type("syStrategy"); Singular.add_type("sip_smap"); + Singular.add_type("bigintmat"); /* monomial orderings */ Singular.set_const("ringorder_no", ringorder_no); @@ -73,6 +75,7 @@ JLCXX_MODULE define_julia_module(jlcxx::Module & Singular) singular_define_rings(Singular); singular_define_ideals(Singular); singular_define_matrices(Singular); + singular_define_caller(Singular); // Calls the Singular interpreter with `input`. @@ -124,60 +127,69 @@ JLCXX_MODULE define_julia_module(jlcxx::Module & Singular) ** from resolutions.jl ***************************/ - Singular.method("res_Delete_helper", [](void * ra_void, int len, ring o) { - auto ra = reinterpret_cast(ra_void); - for (int i = 0; i < len; i++) { - id_Delete(ra + i, o); - } - omFreeSize((ADDRESS)ra, (len + 1) * sizeof(ideal)); - }); + Singular.method("res_Delete_helper", + [](syStrategy ra, ring o) { syKillComputation(ra, o); }); - Singular.method("res_Copy", [](void * ra_void, int len, ring o) { - auto ra = reinterpret_cast(ra_void); - resolvente res = (resolvente)omAlloc0((len + 1) * sizeof(ideal)); + Singular.method("res_Copy", [](syStrategy ra, ring o) { + const ring origin = currRing; rChangeCurrRing(o); - for (int i = len - 1; i >= 0; i--) { - if (ra[i] != NULL) - res[i] = id_Copy(ra[i], o); - } - return reinterpret_cast(res); + syStrategy temp = syCopy(ra); + rChangeCurrRing(origin); + return temp; }); + Singular.method("getindex_internal", + [](syStrategy ra, int64_t k, bool minimal) { + if (minimal) { + return ra->minres[k]; + } + return (ideal)ra->fullres[k]; + }); - Singular.method("getindex", [](void * ra_void, int k) { - auto ra = reinterpret_cast(ra_void); - return (ideal)ra[k]; - }); - - Singular.method("syMinimize", [](void * ra_void, int len, ring o) { - auto ra = reinterpret_cast(ra_void); + Singular.method("syMinimize", [](syStrategy ra, ring o) { const ring origin = currRing; - syStrategy temp = (syStrategy)omAlloc0(sizeof(ssyStrategy)); - resolvente result; rChangeCurrRing(o); - temp->fullres = (resolvente)omAlloc0((len + 1) * sizeof(ideal)); - for (int i = len - 1; i >= 0; i--) { - if (ra[i] != NULL) - temp->fullres[i] = idCopy(ra[i]); - } - temp->length = len; + syStrategy temp = syCopy(ra); syMinimize(temp); - result = temp->minres; - temp->minres = NULL; - // syMinimize increments this as it returns a value we ignore - temp->references--; - syKillComputation(temp, o); rChangeCurrRing(origin); - return reinterpret_cast(result); + return reinterpret_cast(temp); }); + Singular.method("get_minimal_res", [](syStrategy ra) { + return reinterpret_cast(ra->minres); + }); + + Singular.method("get_full_res", [](syStrategy ra) { + return reinterpret_cast(ra->fullres); + }); + + Singular.method("get_sySize", [](syStrategy ra) { + return static_cast(sySize(ra)); + }); + + Singular.method("create_SyStrategy", [](void * res_void, int64_t len, + ring r) { + resolvente res = reinterpret_cast(res_void); + syStrategy result = (syStrategy)omAlloc0(sizeof(ssyStrategy)); + result->list_length = static_cast(len); + result->length = static_cast(len); + resolvente res_cp = (resolvente)omAlloc0((len + 1) * sizeof(ideal)); + for (int i = 0; i <= len; i++) { + if (res[i] != NULL) { + res_cp[i] = id_Copy(res[i], r); + } + } + result->fullres = res_cp; + result->syRing = r; + return result; + }); - Singular.method("syBetti", [](void * ra_void, int len, ring o) { - auto ra = reinterpret_cast(ra_void); + Singular.method("syBetti_internal", [](void * ra, int len, ring o) { const ring origin = currRing; rChangeCurrRing(o); int dummy; - intvec * iv = syBetti(ra, len, &dummy, NULL, FALSE, NULL); + intvec * iv = syBetti(reinterpret_cast(ra), len, &dummy, + NULL, FALSE, NULL); rChangeCurrRing(origin); int nrows = iv->rows(); int ncols = iv->cols(); diff --git a/src/LibSingular.jl b/src/LibSingular.jl index 7d6d1d9b5..5f4ec47de 100644 --- a/src/LibSingular.jl +++ b/src/LibSingular.jl @@ -1,11 +1,13 @@ module libSingular import Libdl + using CxxWrap @wrapmodule(realpath(joinpath(@__DIR__, "..", "local", "lib", "libsingularwrap." * Libdl.dlext))) function __init__() @initcxx + initialize_jl_c_types(@__MODULE__) end include("libsingular/LibSingularTypes.jl") diff --git a/src/Meta.jl b/src/Meta.jl new file mode 100644 index 000000000..67141de9f --- /dev/null +++ b/src/Meta.jl @@ -0,0 +1,34 @@ +include("libraryfuncdictionary.jl") + +input_manipulator_funcs = Dict( + :dummy => Dict( + # :dummy => i->[ x + 1 for x in i] + ) +) + +output_manipulator_funcs = Dict( + :dummy => Dict( + # :dummy => i -> i + 1 + ) +) + +for (name,funcs) in libraryfunctiondictionary + name_caps = Symbol( "Lib" * uppercasefirst(string(name))) + func_calls = Any[] + name_string = string(name) * ".lib" + for i in funcs + if i[1] == "g" + func_name = i[2] + symb = Symbol(func_name) + input_manipulator = haskey(input_manipulator_funcs,name) && haskey(input_manipulator_funcs[name],symb) ? input_manipulator_funcs[name][symb] : identity + output_manipulator = haskey(output_manipulator_funcs,name) && haskey(output_manipulator_funcs[name],symb) ? output_manipulator_funcs[name][symb] : identity + push!(func_calls, :($symb(args...) = $(output_manipulator)(low_level_caller($(name_string),$func_name,$(input_manipulator)(args)...)) )) + push!(func_calls, :($symb(ring::PolyRing,args...) = $(output_manipulator)(low_level_caller_rng($(name_string),$func_name,ring,$(input_manipulator)(args)...)) )) + end + end + eval(:(baremodule $name_caps + import ..Singular: PolyRing, low_level_caller, low_level_caller_rng + import Base: * + $(func_calls...) + end)) +end diff --git a/src/Singular.jl b/src/Singular.jl index 1b9e08f01..5486f01f8 100644 --- a/src/Singular.jl +++ b/src/Singular.jl @@ -47,6 +47,9 @@ const libsingular = joinpath(pkgdir, "local", "lib", "libSingular") prefix = realpath(joinpath(@__DIR__, "..", "local")) +mapping_types = nothing +mapping_types_reversed = nothing + function __init__() # Initialise Singular @@ -90,6 +93,10 @@ function __init__() :comp1max => ringorder_c, :comp1min => ringorder_C ) + global mapping_types, mapping_types_reversed, casting_functions + mapping_types = Dict( i[1] => i[2] for i in libSingular.get_type_mapper() ) + mapping_types_reversed = Dict( j => i for (i, j) in mapping_types ) + casting_functions = create_casting_functions() end ############################################################################### @@ -116,4 +123,8 @@ include("Vector.jl") include("Resolution.jl") +include("caller.jl") + +include("Meta.jl") + end # module diff --git a/src/caller.jl b/src/caller.jl new file mode 100644 index 000000000..d2e4d2438 --- /dev/null +++ b/src/caller.jl @@ -0,0 +1,189 @@ + +function recursive_translate(x, R) + if length(x) > 0 && x[1] isa Bool + return convert_return_list(x, R) + else + return [ recursive_translate(i, R) for i in x] + end +end + +# function LIST_CMD_CASTER(x) +# x_new = LIST_CMD_TRAVERSAL(x) +# end + +casting_functions_pre = Dict(:NUMBER_CMD => (libSingular.NUMBER_CMD_CASTER, true, ()), + :RING_CMD => (libSingular.RING_CMD_CASTER, false, ()), + :POLY_CMD => (libSingular.POLY_CMD_CASTER, true, ()), + :IDEAL_CMD => (libSingular.IDEAL_CMD_CASTER, true, ()), + :MODUL_CMD => (libSingular.IDEAL_CMD_CASTER, true, (:module,)), + :VECTOR_CMD => (libSingular.POLY_CMD_CASTER, true, (:vector,)), + :INT_CMD => (libSingular.INT_CMD_CASTER, false, ()), + :STRING_CMD => (libSingular.STRING_CMD_CASTER, false, ()), + :LIST_CMD => (libSingular.LIST_CMD_TRAVERSAL, false, ()), + :INTVEC_CMD => (libSingular.INTVEC_CMD_CASTER, false, ()), + :INTMAT_CMD => (libSingular.INTMAT_CMD_CASTER, false, ()), + :BIGINT_CMD => (libSingular.BIGINT_CMD_CASTER, false, ()), + :BIGINTMAT_CMD => (libSingular.BIGINTMAT_CMD_CASTER, false, ()), + :MAP_CMD => (libSingular.MAP_CMD_CASTER, false, ()), + :RESOLUTION_CMD => (libSingular.RESOLUTION_CMD_CASTER, true, (:resolution,))) + +casting_functions = nothing + +function create_casting_functions() + pair_array = Any[] + for (sym, func) in casting_functions_pre + push!(pair_array, mapping_types_reversed[sym] => func) + end + return Dict(pair_array...) +end + +function convert_ring_content(value_list, rng) + return_dict = Dict{Symbol,Any}() + for i in value_list + return_dict[i[2]] = convert_return_value([false,i[3],i[1]], rng) + end + return return_dict +end + +function convert_return_value(single_value, rng = nothing) + if single_value[1] + error("recieved list instead of single value") + end + cast = casting_functions[single_value[3]][1](single_value[2]) + if cast isa Array{Any} + return recursive_translate(cast, rng) + elseif cast isa libSingular.ring + new_ring = rng(cast) + return [ new_ring, convert_ring_content(libSingular.get_ring_content(cast), new_ring) ] + elseif casting_functions[single_value[3]][2] + if length(casting_functions[single_value[3]][3]) > 0 + cast = rng(cast, Val(casting_functions[single_value[3]][3][1])) + else + cast = rng(cast) + end + end + return cast +end + + +function convert_return_list(list_value, ring = nothing) + if list_value[1] + return map(i -> convert_return_value(i, ring), list_value[2:end]) + end + return convert_return_value(list_value, ring) +end + +function get_ring(arg_list) + ring = nothing + for i in arg_list + current_ptr = nothing + try + current_ptr = i.ptr + catch + continue + end + if current_ptr isa poly + return parent(i) + elseif current_ptr isa ideal + return parent(i).base_ring + end + end + return ring +end + +function prepare_argument(x::Array{Int64,1}) + return Any[ mapping_types_reversed[:INTVEC_CMD], libSingular.jl_array_to_intvec(x) ], nothing +end + +function prepare_argument(x::Array{Int64,2}) + return Any[ mapping_types_reversed[:INTMAT_CMD], libSingular.jl_array_to_intmat(x) ], nothing +end + +function prepare_argument(x::Int64) + return Any[ mapping_types_reversed[:INT_CMD], Ptr{Cvoid}(x) ], nothing +end + +function prepare_argument(x::String) + return Any[ mapping_types_reversed[:STRING_CMD], libSingular.copy_string_to_void(x) ], nothing +end + +function prepare_argument(x::PolyRing) + new_ptr = libSingular.get_ring_ref(x.ptr) + return Any[ mapping_types_reversed[:RING_CMD], new_ptr ], x +end + +function prepare_argument(x::spoly) + rng = parent(x) + rng_ptr = rng.ptr + return Any[ mapping_types_reversed[:POLY_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng_ptr) ], rng +end + +function prepare_argument(x::svector) + rng = parent(x).base_ring + rng_ptr = rng.ptr + return Any[ mapping_types_reversed[:VECTOR_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng_ptr) ], rng +end + +function prepare_argument(x::sideal) + rng = parent(x).base_ring + rng_ptr = rng.ptr + return Any[ mapping_types_reversed[:IDEAL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng_ptr)], rng +end + +function prepare_argument(x::smodule) + rng = parent(x).base_ring + rng_ptr = rng.ptr + return Any[ mapping_types_reversed[:MODUL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng_ptr)], rng +end + +function prepare_argument(x::sresolution) + rng = base_ring(x) + res = Any[ mapping_types_reversed[:RESOLUTION_CMD], libSingular.create_syStrategy_data(x.ptr, rng.ptr) ] + return res, rng +end + +function prepare_argument(x::Any) + if x.ptr isa libSingular.number + ptr = x.ptr + rng = parent(x) + new_ptr = libSingular.n_Copy(ptr, rng.ptr) + return Any[ mapping_types_reversed[:NUMBER_CMD], new_ptr.cpp_object ], nothing + elseif x.ptr isa libSingular.ip_smatrix + rng = parent(x) + return Any[ mapping_types_reversed[:MATRIX_CMD], libSingular.mpCopy(x.ptr, rng.ptr).cpp_object ], rng + elseif x.ptr isa libSingular.__mpz_struct + return Any[ mapping_types_reversed[:BIGINT_CMD], x.ptr.cpp_object ], nothing + elseif x.ptr isa libSingular.sip_smap + return Any[ mapping_types_reversed[:MAP_CMD], x.ptr.cpp_object ], nothing + elseif x.ptr isa libSingular.bigintmat + return Any[ mapping_types_reversed[:BIGINTMAT_CMD], x.ptr.cpp_object ], nothing + end + +end + +function low_level_caller_rng(lib::String, name::String, ring, args...) + libSingular.load_library(lib) + arguments = [prepare_argument(i) for i in args] + arguments = Any[ i for (i, j) in arguments ] + return_value = libSingular.call_singular_library_procedure(name, ring.ptr, arguments) + return convert_return_list(return_value, ring) +end + +function low_level_caller(lib::String, name::String, args...) + libSingular.load_library(lib) + arguments = [prepare_argument(i) for i in args] + rng = nothing + for (i, j) in arguments + if j != nothing + rng = j + end + end + arguments = Any[ i for (i, j) in arguments ] + return_values = nothing + if rng == nothing + return_value = libSingular.call_singular_library_procedure(name, arguments) + else + return_value = libSingular.call_singular_library_procedure(name, rng.ptr, arguments) + end + return convert_return_list(return_value, rng) +end diff --git a/src/ideal/ideal.jl b/src/ideal/ideal.jl index 38984d9b1..418301488 100644 --- a/src/ideal/ideal.jl +++ b/src/ideal/ideal.jl @@ -484,8 +484,8 @@ function fres(id::Union{sideal{T}, smodule{T}}, max_length::Int, method::String && method != "single module") error("wrong optional argument for fres") end - r, length, minimal = libSingular.id_fres(id.ptr, Cint(max_length + 1), method, R.ptr) - return sresolution{T}(R, Int(length), r, minimal) + r, minimal = libSingular.id_fres(id.ptr, Cint(max_length + 1), method, R.ptr) + return sresolution{T}(R, r, minimal) end @doc Markdown.doc""" @@ -503,16 +503,8 @@ function sres(I::sideal{T}, max_length::Int) where T <: Nemo.RingElem max_length = nvars(R) # TODO: consider qrings end - r, length, minimal = libSingular.id_sres(I.ptr, Cint(max_length + 1), R.ptr) - for i = 1:length - ptr = libSingular.getindex(r, Cint(i - 1)) - if ptr.cpp_object == C_NULL - length = i - 1 - break - end - libSingular.idSkipZeroes(ptr) - end - return sresolution{T}(R, length, r, minimal) + r, minimal = libSingular.id_sres(I.ptr, Cint(max_length + 1), R.ptr) + return sresolution{T}(R, r, minimal) end ############################################################################### @@ -536,6 +528,10 @@ function Ideal(R::PolyRing{T}, id::libSingular.ideal) where T <: Nemo.RingElem return sideal{S}(R, id) end +function (R::PolyRing{T})(id::libSingular.ideal) where T <: Nemo.RingElem + return Ideal(R,id) +end + # maximal ideal in degree d function MaximalIdeal(R::PolyRing{T}, d::Int) where T <: Nemo.RingElem (d > typemax(Cint) || d < 0) && throw(DomainError()) diff --git a/src/module/ModuleTypes.jl b/src/module/ModuleTypes.jl index 7d881d054..d6fb2b0ca 100644 --- a/src/module/ModuleTypes.jl +++ b/src/module/ModuleTypes.jl @@ -32,6 +32,18 @@ mutable struct svector{T <: Nemo.RingElem} <: Nemo.ModuleElem{T} end end +""" + (R::PolyRing{T})(m::libSingular.poly,::Val{:vector}) where T + +If R is called with a low-level poly pointer, along with +Val(:vector), it will interpret the poly pointer as a vector. +This needs to be indicated due to the fact that Singulars +vectors and polys are both stored in the poly data structure. +""" +function (R::PolyRing{T})(m::libSingular.poly,::Val{:vector}) where T + return svector{T}(R,1,m) +end + function _svector_clear_fn(p::svector) R = p.base_ring libSingular.p_Delete(p.ptr, R.ptr) @@ -88,6 +100,18 @@ mutable struct smodule{T <: Nemo.RingElem} <: Module{T} end end +""" + (R::PolyRing{T})(m::libSingular.ideal,::Val{:module}) where T + +If R is called with a low-level ideal pointer, along with +Val(:module), it will interpret the ideal pointer as a module. +This needs to be indicated due to the fact that Singulars +modules and ideals are both stored in the ideal data structure. +""" +function (R::PolyRing{T})(m::libSingular.ideal,::Val{:module}) where T + return smodule{T}(R,m) +end + function _smodule_clear_fn(I::smodule) R = I.base_ring libSingular.id_Delete(I.ptr, R.ptr) diff --git a/src/module/module.jl b/src/module/module.jl index 891794fb1..cf4174260 100644 --- a/src/module/module.jl +++ b/src/module/module.jl @@ -160,16 +160,8 @@ function sres(I::smodule{T}, max_length::Int) where T <: Nemo.RingElem max_length = nvars(R) # TODO: consider qrings end - r, length, minimal = libSingular.id_sres(I.ptr, Cint(max_length + 1), R.ptr) - for i = 1:length - ptr = libSingular.getindex(r, Cint(i - 1)) - if ptr.cpp_object == C_NULL - length = i - 1 - break - end - libSingular.idSkipZeroes(ptr) - end - return sresolution{T}(R, length, r, minimal) + r, minimal = libSingular.id_sres(I.ptr, Cint(max_length + 1), R.ptr) + return sresolution{T}(R, r, minimal) end ############################################################################### diff --git a/src/number/NumberTypes.jl b/src/number/NumberTypes.jl index 6f4051eec..ce94b02fb 100644 --- a/src/number/NumberTypes.jl +++ b/src/number/NumberTypes.jl @@ -133,7 +133,7 @@ end function _n_Q_clear_fn(n::n_Q) R = parent(n) - libSingular.n_Delete_Q(n.ptr.cpp_object, parent(n).ptr) + libSingular.n_Delete_Q(n.ptr, parent(n).ptr) _Rationals_clear_fn(R) nothing end diff --git a/src/poly/PolyTypes.jl b/src/poly/PolyTypes.jl index f4e2f7391..1622c053b 100644 --- a/src/poly/PolyTypes.jl +++ b/src/poly/PolyTypes.jl @@ -63,6 +63,13 @@ mutable struct PolyRing{T <: Nemo.RingElem} <: Nemo.MPolyRing{T} end end +function (R::PolyRing{T})(r::libSingular.ring) where T + new_r = deepcopy(R) + new_ptr = new_r.ptr + new_r.ptr = r + return new_r +end + function _PolyRing_clear_fn(R::PolyRing) R.refcount -= 1 if R.refcount == 0 diff --git a/src/poly/poly.jl b/src/poly/poly.jl index c1658e6eb..9546d7a22 100644 --- a/src/poly/poly.jl +++ b/src/poly/poly.jl @@ -813,6 +813,10 @@ function (R::PolyRing)(p::spoly) return p end +function(R::PolyRing)(n::libSingular.number) + return R.base_ring(n) +end + ############################################################################### # # PolynomialRing constructor diff --git a/src/resolution/ResolutionTypes.jl b/src/resolution/ResolutionTypes.jl index 9e27bba62..194ad07e9 100644 --- a/src/resolution/ResolutionTypes.jl +++ b/src/resolution/ResolutionTypes.jl @@ -19,22 +19,21 @@ mutable struct ResolutionSet{T <: Nemo.RingElem} <: Set end mutable struct sresolution{T <: Nemo.RingElem} <: Nemo.SetElem - ptr::Ptr{Nothing} - len::Int + ptr::libSingular.syStrategyRef minimal::Bool base_ring::PolyRing # really takes a Singular module, which has type ideal - function sresolution{T}(R::PolyRing, n::Int, ptr::Ptr{Nothing}, minimal::Bool=false) where T + function sresolution{T}(R::PolyRing, ptr::libSingular.syStrategy, minimal::Bool=false) where T R.refcount += 1 - z = new(ptr, n, minimal, R) + z = new(ptr, minimal, R) finalizer(_sresolution_clear_fn, z) return z end end function _sresolution_clear_fn(r::sresolution) - R = base_ring(r) - libSingular.res_Delete_helper(r.ptr, Cint(r.len), R.ptr) + R = base_ring(r) + libSingular.res_Delete_helper(r.ptr, R.ptr) _PolyRing_clear_fn(R) end diff --git a/src/resolution/resolution.jl b/src/resolution/resolution.jl index 87416acf5..0290360f1 100644 --- a/src/resolution/resolution.jl +++ b/src/resolution/resolution.jl @@ -21,13 +21,13 @@ elem_type(::ResolutionSet{T}) where T <: AbstractAlgebra.RingElem = sresolution{ parent_type(::Type{sresolution{T}}) where T <: AbstractAlgebra.RingElem = ResolutionSet{T} function checkbounds(r::sresolution, i::Int) - (i < 1 || i > r.len) && throw(BoundsError(I, i)) + (i < 1 || i > libSingular.get_sySize(r.ptr)) && throw(BoundsError(r, i)) end function getindex(r::sresolution, i::Int) checkbounds(r, i) R = base_ring(r) - ptr = libSingular.getindex(r.ptr, Cint(i - 1)) + ptr = libSingular.getindex_internal(r.ptr, i-1, r.minimal ) if ptr.cpp_object != C_NULL ptr = libSingular.id_Copy(ptr, R.ptr) end @@ -40,13 +40,13 @@ end > length of a resolution. Over a field, this should be at most the number of variables > in the polynomial ring. """ -length(r::sresolution) = r.len - 1 +length(r::sresolution) = libSingular.get_sySize(r.ptr) function deepcopy_internal(r::sresolution, dict::IdDict) R = base_ring(r) - ptr = libSingular.res_Copy(r.ptr, Cint(r.len), R.ptr) + ptr = libSingular.res_Copy(r.ptr, R.ptr) S = parent(r) - return S(ptr, r.len) + return S(ptr) end ############################################################################### @@ -62,7 +62,12 @@ end > output of this command is useful only in the graded case. """ function betti(r::sresolution) - array = libSingular.syBetti(r.ptr, Cint(r.len), r.base_ring.ptr) + if r.minimal + ideal_list = libSingular.get_minimal_res(r.ptr) + else + ideal_list = libSingular.get_full_res(r.ptr) + end + array = libSingular.syBetti_internal(ideal_list, length(r), r.base_ring.ptr) return unsafe_wrap(Array, array[1], array[2:3]; own=true) end @@ -83,8 +88,8 @@ function minres(r::sresolution{T}) where T <: AbstractAlgebra.RingElem return r end R = base_ring(r) - ptr = libSingular.syMinimize(r.ptr, Cint(r.len), R.ptr) - return sresolution{T}(R, r.len, ptr, true) + ptr = libSingular.syMinimize(r.ptr, R.ptr) + return sresolution{T}(R, ptr, true) end ############################################################################### @@ -100,13 +105,16 @@ end function show(io::IO, r::sresolution) println(io, "Singular Resolution:") - if r.len > 0 - ptr = libSingular.getindex(r.ptr, Cint(0)) - print(io, "R^", libSingular.rank(ptr)) + len = libSingular.get_sySize(r.ptr) + if len > 0 + ptr = libSingular.getindex_internal(r.ptr,0,r.minimal) + if ptr.cpp_object != C_NULL + print(io, "R^", libSingular.rank(ptr)) + end end - for i = 1:r.len - 1 - ptr = libSingular.getindex(r.ptr, Cint(i-1)) - if ptr == C_NULL + for i = 1:len - 1 + ptr = libSingular.getindex_internal(r.ptr,i-1,r.minimal) + if ptr.cpp_object == C_NULL break end print(io, " <- R^", libSingular.ngens(ptr)) @@ -119,9 +127,13 @@ end # ############################################################################### -function (S::ResolutionSet{T})(ptr::Ptr{Nothing}, len::Int) where T <: AbstractAlgebra.RingElem +function (S::ResolutionSet{T})(ptr::libSingular.syStrategy, len::Int = 0) where T <: AbstractAlgebra.RingElem R = base_ring(S) - return sresolution{T}(R, len, ptr) + return sresolution{T}(R, ptr) +end + +function (R::PolyRing{T})(ptr::libSingular.syStrategy, ::Val{:resolution}) where T <: AbstractAlgebra.RingElement + return sresolution{T}(R, ptr, libSingular.get_minimal_res(ptr) != C_NULL ) end ############################################################################### @@ -143,7 +155,7 @@ function Resolution(C::Array{smodule{T}, 1}) where T <: AbstractAlgebra.RingElem R = base_ring(C[1]) CC = (m -> m.ptr).(C) C_ptr = reinterpret(Ptr{Nothing}, pointer(CC)) - ptr = libSingular.res_Copy(C_ptr, Cint(len), R.ptr) - return sresolution{T}(R, len, ptr) + ptr = libSingular.create_SyStrategy(C_ptr, len, R.ptr) + return sresolution{T}(R, ptr) end diff --git a/test/caller-test.jl b/test/caller-test.jl new file mode 100644 index 000000000..752d72b3a --- /dev/null +++ b/test/caller-test.jl @@ -0,0 +1,46 @@ +function test_caller() + print("caller...") + + R, (x, y) = PolynomialRing(Singular.ZZ, ["x", "y"]) + @test Singular.LibSets.isEqualInt(R, Singular.ZZ(1), Singular.ZZ(1)) == 1 + + R, (x, y) = PolynomialRing(Singular.QQ, ["x", "y"]) + + # Input tests + @test 1 == Singular.LibSets.isEqualInt(R, 1, 1) + @test 1 == Singular.LibSets.isEqualInt(R, x, x) + @test 1 == Singular.LibSets.isEqualInt(R, "aa", "aa") + @test 1 == Singular.LibSets.isEqualInt(R, Singular.QQ(1), Singular.QQ(1)) + @test 1 == Singular.LibSets.isEqualInt(R, [1,2,3], [1,2,3]) + @test 1 == Singular.LibSets.isEqualInt(R, [1 2; 3 4], [1 2; 3 4]) + + R, (x,y,z) = PolynomialRing(Singular.QQ, ["x", "y", "z"]) + + i1 = Singular.LibPoly.cyclic(R, 3) + i2 = Ideal( R, x+y+z, x*y+x*z+y*z, x*y*z-1 ) + @test equal(i1, i2) + + vec = FreeModule(R,2)([x,y]) + mod = Singular.Module(R, vec) + i1 = Singular.LibPoly.mod2id(R,mod,[1,2]) + i2 = Ideal(R, x^2, x*y, y^2, x^2 ) + @test equal(i1, i2) + + i1 = Ideal(R, x, y) + i2 = Ideal(R, x^2, x*y, y^2, x, y) + mod = Singular.LibPoly.id2mod(R, i1, [1,2]) + i1 = Singular.LibPoly.mod2id(R, mod, [1,2]) + @test equal(i1,i2) + @test Singular.LibPoly.content(R,vec) == 1 + @test Singular.LibPoly.lcm(R,x) == x + + i1 = Ideal(R, x*z, y*z, x^3-y^3) + @test Singular.LibStandard.res(R,i1,0) isa Singular.sresolution + i1 = Ideal(R, x*z, y*z, x^3-y^3) + @test Singular.LibPrimdec.primdecGTZ(R,i1) isa Array + + i1 = Ideal(R, x*z, y*z, x^3-y^3) + @test Singular.LibNormal.normal(i1, "withDelta", "prim") isa Array + + println("PASS") +end diff --git a/test/runtests.jl b/test/runtests.jl index 7d7e40063..dc5d3b3ec 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -16,14 +16,17 @@ include("../test/matrix-test.jl") include("../test/resolution-test.jl") include("../test/module-test.jl") include("../test/call_interpreter-test.jl") +include("../test/caller-test.jl") # include("../test/libsingular-test.jl") -test_number() -test_poly() -test_ideal() -test_matrix() -test_resolution() -test_module() -test_call_interpreter() -# test_libsingular() - +@testset "Singular" begin + test_caller() + test_number() + test_poly() + test_ideal() + test_matrix() + test_resolution() + test_module() + test_call_interpreter() + # test_libsingular() +end From 4f321a2ebe59965ff427fb29c7fd62e506324f64 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 24 Jul 2019 22:03:51 +0200 Subject: [PATCH 02/16] fixup! First version of caller - WIP --- deps/parselibs.jl | 3 +-- deps/src/caller.cpp | 2 -- deps/src/coeffs.cpp | 4 +--- src/LibSingular.jl | 1 - src/caller.jl | 2 +- src/resolution/resolution.jl | 4 ++-- 6 files changed, 5 insertions(+), 11 deletions(-) diff --git a/deps/parselibs.jl b/deps/parselibs.jl index 2510a9295..afe471bba 100644 --- a/deps/parselibs.jl +++ b/deps/parselibs.jl @@ -34,8 +34,7 @@ open(output_filename, "w") do outputfile error("from libparse: $(libs.stderr)") end libs_splitted = split(libs.stdout,"\n")[4:end-1] - libs_splitted = [ split(i," ") for i in libs_splitted ] - libs_splitted = [ [ j for j in i if j != ""] for i in libs_splitted ] + libs_splitted = [ split(i," ", keepempty = false) for i in libs_splitted ] println(outputfile, ":$(i[1:end - 4]) => [") for j in libs_splitted println(outputfile, """[ "$(j[1])", "$(j[3])" ],""") diff --git a/deps/src/caller.cpp b/deps/src/caller.cpp index b606a10a4..6237284f4 100644 --- a/deps/src/caller.cpp +++ b/deps/src/caller.cpp @@ -6,8 +6,6 @@ #include #include -// #include - static jl_value_t * jl_int64_vector_type; static jl_value_t * jl_int64_matrix_type; static jl_value_t * jl_singular_number_type; diff --git a/deps/src/coeffs.cpp b/deps/src/coeffs.cpp index b7457f2b3..608f3b57a 100644 --- a/deps/src/coeffs.cpp +++ b/deps/src/coeffs.cpp @@ -38,14 +38,12 @@ void singular_define_coeffs(jlcxx::Module & Singular) }); Singular.method("n_Delete", [](snumber * n, coeffs cf) { - number * t = &n; if (n != NULL) { - n_Delete(t, cf); + n_Delete(&n, cf); } }); Singular.method("n_Delete_Q", [](snumber * n, coeffs cf) { - ; if (n != NULL) { n_Delete(&n, cf); } diff --git a/src/LibSingular.jl b/src/LibSingular.jl index 5f4ec47de..d1974b01b 100644 --- a/src/LibSingular.jl +++ b/src/LibSingular.jl @@ -1,7 +1,6 @@ module libSingular import Libdl - using CxxWrap @wrapmodule(realpath(joinpath(@__DIR__, "..", "local", "lib", "libsingularwrap." * Libdl.dlext))) diff --git a/src/caller.jl b/src/caller.jl index d2e4d2438..f6254f12f 100644 --- a/src/caller.jl +++ b/src/caller.jl @@ -47,7 +47,7 @@ end function convert_return_value(single_value, rng = nothing) if single_value[1] - error("recieved list instead of single value") + error("received list instead of single value") end cast = casting_functions[single_value[3]][1](single_value[2]) if cast isa Array{Any} diff --git a/src/resolution/resolution.jl b/src/resolution/resolution.jl index 0290360f1..c6ead15d2 100644 --- a/src/resolution/resolution.jl +++ b/src/resolution/resolution.jl @@ -21,7 +21,7 @@ elem_type(::ResolutionSet{T}) where T <: AbstractAlgebra.RingElem = sresolution{ parent_type(::Type{sresolution{T}}) where T <: AbstractAlgebra.RingElem = ResolutionSet{T} function checkbounds(r::sresolution, i::Int) - (i < 1 || i > libSingular.get_sySize(r.ptr)) && throw(BoundsError(r, i)) + (i < 1 || i > length(r)) && throw(BoundsError(r, i)) end function getindex(r::sresolution, i::Int) @@ -105,7 +105,7 @@ end function show(io::IO, r::sresolution) println(io, "Singular Resolution:") - len = libSingular.get_sySize(r.ptr) + len = length(r) if len > 0 ptr = libSingular.getindex_internal(r.ptr,0,r.minimal) if ptr.cpp_object != C_NULL From 86ad587811153e1a697aaafc1e328790dbf1766b Mon Sep 17 00:00:00 2001 From: Sebastian Gutsche Date: Sun, 28 Jul 2019 13:44:33 +0200 Subject: [PATCH 03/16] Fixes from code commit: * Check overflow when converting Julia arrays/matrices to internal Singualr vector structure * Use C-structs for type mapper instead of stl * Added comments * Remove unnecessary `rng_ptr` variable from `prepare_argument` * In Meta.jl, use `get` instead of `&&?:` * Simplified internal library caller code --- deps/parselibs.jl | 6 ++++ deps/src/caller.cpp | 84 +++++++++++++++++++++++++++++---------------- src/Meta.jl | 22 ++++++++++-- src/caller.jl | 34 +++++++++--------- 4 files changed, 96 insertions(+), 50 deletions(-) diff --git a/deps/parselibs.jl b/deps/parselibs.jl index afe471bba..3162d5b6c 100644 --- a/deps/parselibs.jl +++ b/deps/parselibs.jl @@ -25,6 +25,12 @@ filenames = filter(x -> endswith(x, ".lib"), readdir(library_dir)) output_filename = abspath(joinpath(@__DIR__, "..", "src", "libraryfuncdictionary.jl")) +## Loops over all libraries and executes libparse on it. +## The first three lines of the libparse output are general information +## about the library, so we ignore it. We are only interested in the +## first column (library name) and the third column (globally exposed or not). +## All other columns (containing info such as line numbers, library name, etc) +## are ignored. open(output_filename, "w") do outputfile println(outputfile, "libraryfunctiondictionary = Dict(") for i in filenames diff --git a/deps/src/caller.cpp b/deps/src/caller.cpp index 6237284f4..5672cda07 100644 --- a/deps/src/caller.cpp +++ b/deps/src/caller.cpp @@ -21,32 +21,33 @@ static jl_value_t * jl_singular_vector_type; static jl_value_t * get_type_mapper() { - std::vector> types = { - std::pair(BIGINT_CMD, "BIGINT_CMD"), - std::pair(NUMBER_CMD, "NUMBER_CMD"), - std::pair(RING_CMD, "RING_CMD"), - std::pair(POLY_CMD, "POLY_CMD"), - std::pair(IDEAL_CMD, "IDEAL_CMD"), - std::pair(INT_CMD, "INT_CMD"), - std::pair(STRING_CMD, "STRING_CMD"), - std::pair(LIST_CMD, "LIST_CMD"), - std::pair(INTMAT_CMD, "INTMAT_CMD"), - std::pair(BIGINTMAT_CMD, "BIGINTMAT_CMD"), - std::pair(MAP_CMD, "MAP_CMD"), - std::pair(RESOLUTION_CMD, "RESOLUTION_CMD"), - std::pair(MODUL_CMD, "MODUL_CMD"), - std::pair(VECTOR_CMD, "VECTOR_CMD"), - std::pair(INTVEC_CMD, "INTVEC_CMD")}; + // clang-format off + struct { int cmd; const char * name; } types[] = { + {BIGINT_CMD, "BIGINT_CMD"}, + {NUMBER_CMD, "NUMBER_CMD"}, + {RING_CMD, "RING_CMD"}, + {POLY_CMD, "POLY_CMD"}, + {IDEAL_CMD, "IDEAL_CMD"}, + {INT_CMD, "INT_CMD"}, + {STRING_CMD, "STRING_CMD"}, + {LIST_CMD, "LIST_CMD"}, + {INTMAT_CMD, "INTMAT_CMD"}, + {BIGINTMAT_CMD, "BIGINTMAT_CMD"}, + {MAP_CMD, "MAP_CMD"}, + {RESOLUTION_CMD, "RESOLUTION_CMD"}, + {MODUL_CMD, "MODUL_CMD"}, + {VECTOR_CMD, "VECTOR_CMD"}, + {INTVEC_CMD, "INTVEC_CMD"}}; + // clang-format on - jl_array_t * return_array = - jl_alloc_array_1d(jl_array_any_type, types.size()); + jl_array_t * return_array = jl_alloc_array_1d( + jl_array_any_type, sizeof(types) / sizeof(types[0])); - for (int i = 0; i < types.size(); i++) { + for (int i = 0; i < sizeof(types) / sizeof(types[0]); i++) { jl_array_t * current_return = jl_alloc_array_1d(jl_array_any_type, 2); - jl_arrayset(current_return, jl_box_int64(types[i].first), 0); + jl_arrayset(current_return, jl_box_int64(types[i].cmd), 0); jl_arrayset(current_return, - reinterpret_cast( - jl_symbol(types[i].second.c_str())), + reinterpret_cast(jl_symbol(types[i].name)), 1); jl_arrayset(return_array, reinterpret_cast(current_return), i); @@ -118,8 +119,18 @@ void * jl_array_to_intvec(jl_value_t * array_val) intvec * result = new intvec(size); int * result_content = result->ivGetVec(); for (int i = 0; i < size; i++) { - result_content[i] = - static_cast(jl_unbox_int64(jl_arrayref(array, i))); + jl_value_t * current_entry = jl_arrayref(array, i); + if (jl_is_int32(current_entry)) { + result_content[i] = + static_cast(jl_unbox_int32(current_entry)); + } + else if (jl_is_int64(current_entry)) { + int64_t current_int64 = jl_unbox_int64(current_entry); + result_content[i] = static_cast(current_int64); + if (result_content[i] != current_int64) { + jl_error("Input entry does not fit in 32 bit integer"); + } + } } return reinterpret_cast(result); } @@ -130,12 +141,20 @@ void * jl_array_to_intmat(jl_value_t * array_val) int rows = jl_array_dim(array, 0); int cols = jl_array_dim(array, 1); intvec * result = new intvec(rows, cols, 0); + if (!jl_subtype(reinterpret_cast(jl_typeof(array_val)), + reinterpret_cast(jl_int64_matrix_type))) { + jl_error("Input is not an Int64 matrix"); + } int64_t * array_data = reinterpret_cast(jl_array_data(array)); int * vec_data = result->ivGetVec(); for (int i = 0; i < cols; i++) { for (int j = 0; j < rows; j++) { - IMATELEM(*result, i + 1, j + 1) = - static_cast(array_data[j + (i * rows)]); + int64_t current_elem = array_data[j + (i * rows)]; + int current_elem_32 = static_cast(current_elem); + if (current_elem != current_elem_32) { + jl_error("Input entry does not fit in 32 bit integer"); + } + IMATELEM(*result, i + 1, j + 1) = current_elem_32; } } return reinterpret_cast(result); @@ -143,6 +162,9 @@ void * jl_array_to_intmat(jl_value_t * array_val) static void * get_ring_ref(ring r) { + // Since a call to a Singular library function destroys its arguments, + // the call will decrease the number of references to the ring. So we + // increase the reference count. r->ref++; return reinterpret_cast(r); } @@ -254,12 +276,14 @@ jl_value_t * call_singular_library_procedure( return retObj; } -jl_value_t * call_singular_library_procedure_wo_ring( - std::string name, jlcxx::ArrayRef arguments) +jl_value_t * call_singular_library_procedure_wo_rng( + std::string name, void* rng, jlcxx::ArrayRef arguments) { - return call_singular_library_procedure(name, NULL, arguments); + return call_singular_library_procedure(name, reinterpret_cast(rng), arguments); } + + jl_value_t * convert_nested_list(void * l_void) { lists l = reinterpret_cast(l_void); @@ -305,7 +329,7 @@ void singular_define_caller(jlcxx::Module & Singular) Singular.method("call_singular_library_procedure", &call_singular_library_procedure); Singular.method("call_singular_library_procedure", - &call_singular_library_procedure_wo_ring); + &call_singular_library_procedure_wo_rng); Singular.method("get_type_mapper", &get_type_mapper); Singular.method("initialize_jl_c_types", &initialize_jl_c_types); diff --git a/src/Meta.jl b/src/Meta.jl index 67141de9f..753c00d9f 100644 --- a/src/Meta.jl +++ b/src/Meta.jl @@ -1,17 +1,35 @@ +## This file generates (at precompilation time) wrapper for all Singular library functions +## All wrappers are given by LIBRARYNAME.functionname. We currently use all caps library names +## to avoid confusion between the LIBRARYNAME modules and other types, for example "Ideal" or "Poly". + + +## This script calls singulars parse_libs and creates a dictionary +## containing Singulars libraries and the functions contained in those libraries. include("libraryfuncdictionary.jl") +## In the dictionary `input_manipulator_funcs` for each library a dictionary +## can be added, and for each function in this library a preprocesing function +## can be added. The function gets executed on the input, before the library function +## is called. input_manipulator_funcs = Dict( :dummy => Dict( # :dummy => i->[ x + 1 for x in i] ) ) +## The same as `input_manipulator_funcs`, but the function gets executed on the output of +## a function. output_manipulator_funcs = Dict( :dummy => Dict( # :dummy => i -> i + 1 ) ) +## For each library `lib` a module `LIB` is created, which contains wrappers for all globally exposed +## functions of the library. Each library function `foo` can be called either as `foo(ring, args...)`, +## where `ring` is the ring the arguments belong to, or as `foo(args...)` if no ring is needed or the +## ring con be determined from the input arguments. Furthermore, if applicaple, input and output manipulator +## functions are added to the call. for (name,funcs) in libraryfunctiondictionary name_caps = Symbol( "Lib" * uppercasefirst(string(name))) func_calls = Any[] @@ -20,8 +38,8 @@ for (name,funcs) in libraryfunctiondictionary if i[1] == "g" func_name = i[2] symb = Symbol(func_name) - input_manipulator = haskey(input_manipulator_funcs,name) && haskey(input_manipulator_funcs[name],symb) ? input_manipulator_funcs[name][symb] : identity - output_manipulator = haskey(output_manipulator_funcs,name) && haskey(output_manipulator_funcs[name],symb) ? output_manipulator_funcs[name][symb] : identity + input_manipulator = get(get(input_manipulator_funcs, name, Dict()), symb, identity) + output_manipulator = get(get(output_manipulator_funcs, name, Dict()), symb, identity) push!(func_calls, :($symb(args...) = $(output_manipulator)(low_level_caller($(name_string),$func_name,$(input_manipulator)(args)...)) )) push!(func_calls, :($symb(ring::PolyRing,args...) = $(output_manipulator)(low_level_caller_rng($(name_string),$func_name,ring,$(input_manipulator)(args)...)) )) end diff --git a/src/caller.jl b/src/caller.jl index f6254f12f..61d6ad0fe 100644 --- a/src/caller.jl +++ b/src/caller.jl @@ -7,10 +7,12 @@ function recursive_translate(x, R) end end -# function LIST_CMD_CASTER(x) -# x_new = LIST_CMD_TRAVERSAL(x) -# end - +## Entries in this array are as follows +## 1. CMD type of return lvar +## 2. Casting function to correct CxxWrap pointer type +## 3. True if this pointer needs to be passed to a ring to construct the right object +## 4. If the pointer type if ambigious (module, ideal), an additional argument that +## needs to be passed to the ring to construct the right object. casting_functions_pre = Dict(:NUMBER_CMD => (libSingular.NUMBER_CMD_CASTER, true, ()), :RING_CMD => (libSingular.RING_CMD_CASTER, false, ()), :POLY_CMD => (libSingular.POLY_CMD_CASTER, true, ()), @@ -45,6 +47,8 @@ function convert_ring_content(value_list, rng) return return_dict end +## Converts a single return value back to Julia, i.e., +## a single lvar, not a linked list of such. function convert_return_value(single_value, rng = nothing) if single_value[1] error("received list instead of single value") @@ -65,7 +69,8 @@ function convert_return_value(single_value, rng = nothing) return cast end - +## Converts a linked list of lvars (already converted to Julia array) back +## to Singular.jl types. function convert_return_list(list_value, ring = nothing) if list_value[1] return map(i -> convert_return_value(i, ring), list_value[2:end]) @@ -114,26 +119,22 @@ end function prepare_argument(x::spoly) rng = parent(x) - rng_ptr = rng.ptr - return Any[ mapping_types_reversed[:POLY_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng_ptr) ], rng + return Any[ mapping_types_reversed[:POLY_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng.ptr) ], rng end function prepare_argument(x::svector) rng = parent(x).base_ring - rng_ptr = rng.ptr - return Any[ mapping_types_reversed[:VECTOR_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng_ptr) ], rng + return Any[ mapping_types_reversed[:VECTOR_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng.ptr) ], rng end function prepare_argument(x::sideal) rng = parent(x).base_ring - rng_ptr = rng.ptr - return Any[ mapping_types_reversed[:IDEAL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng_ptr)], rng + return Any[ mapping_types_reversed[:IDEAL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng.ptr)], rng end function prepare_argument(x::smodule) rng = parent(x).base_ring - rng_ptr = rng.ptr - return Any[ mapping_types_reversed[:MODUL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng_ptr)], rng + return Any[ mapping_types_reversed[:MODUL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng.ptr)], rng end function prepare_argument(x::sresolution) @@ -180,10 +181,7 @@ function low_level_caller(lib::String, name::String, args...) end arguments = Any[ i for (i, j) in arguments ] return_values = nothing - if rng == nothing - return_value = libSingular.call_singular_library_procedure(name, arguments) - else - return_value = libSingular.call_singular_library_procedure(name, rng.ptr, arguments) - end + rng = (rng == nothing) ? C_NULL : rng.ptr + return_value = libSingular.call_singular_library_procedure(name, rng, arguments) return convert_return_list(return_value, rng) end From c244bb7eb1407e561cf5ca865e4ac6672b7c51ce Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 15:20:34 +0200 Subject: [PATCH 04/16] Fix bug in length that causes test code to fail. --- src/resolution/resolution.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resolution/resolution.jl b/src/resolution/resolution.jl index c6ead15d2..819ad1d91 100644 --- a/src/resolution/resolution.jl +++ b/src/resolution/resolution.jl @@ -40,7 +40,7 @@ end > length of a resolution. Over a field, this should be at most the number of variables > in the polynomial ring. """ -length(r::sresolution) = libSingular.get_sySize(r.ptr) +length(r::sresolution) = libSingular.get_sySize(r.ptr) - 1 function deepcopy_internal(r::sresolution, dict::IdDict) R = base_ring(r) From ce9bbbd0bc36add954fb4d43d4492c3ebe96632f Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 15:25:21 +0200 Subject: [PATCH 05/16] Fix return type of syMinimize --- deps/src/singular.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deps/src/singular.cpp b/deps/src/singular.cpp index fd03397e8..a0ac55fb8 100644 --- a/deps/src/singular.cpp +++ b/deps/src/singular.cpp @@ -151,10 +151,10 @@ JLCXX_MODULE define_julia_module(jlcxx::Module & Singular) Singular.method("syMinimize", [](syStrategy ra, ring o) { const ring origin = currRing; rChangeCurrRing(o); - syStrategy temp = syCopy(ra); - syMinimize(temp); + syStrategy result = syCopy(ra); + syMinimize(result); rChangeCurrRing(origin); - return reinterpret_cast(temp); + return result; }); Singular.method("get_minimal_res", [](syStrategy ra) { From 51ee35f980b629df330a98c6682a97ce9096b0cd Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 16:17:08 +0200 Subject: [PATCH 06/16] Minor formatting cleanup. --- deps/parselibs.jl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/deps/parselibs.jl b/deps/parselibs.jl index 3162d5b6c..42897fe2c 100644 --- a/deps/parselibs.jl +++ b/deps/parselibs.jl @@ -25,12 +25,14 @@ filenames = filter(x -> endswith(x, ".lib"), readdir(library_dir)) output_filename = abspath(joinpath(@__DIR__, "..", "src", "libraryfuncdictionary.jl")) -## Loops over all libraries and executes libparse on it. -## The first three lines of the libparse output are general information -## about the library, so we ignore it. We are only interested in the -## first column (library name) and the third column (globally exposed or not). -## All other columns (containing info such as line numbers, library name, etc) -## are ignored. +#= + Loops over all libraries and executes libparse on it. + The first three lines of the libparse output are general information + about the library, so we ignore it. We are only interested in the + first column (library name) and the third column (globally exposed or not). + All other columns (containing info such as line numbers, library name, etc) + are ignored. +=# open(output_filename, "w") do outputfile println(outputfile, "libraryfunctiondictionary = Dict(") for i in filenames @@ -40,7 +42,7 @@ open(output_filename, "w") do outputfile error("from libparse: $(libs.stderr)") end libs_splitted = split(libs.stdout,"\n")[4:end-1] - libs_splitted = [ split(i," ", keepempty = false) for i in libs_splitted ] + libs_splitted = [split(i, " ", keepempty = false) for i in libs_splitted] println(outputfile, ":$(i[1:end - 4]) => [") for j in libs_splitted println(outputfile, """[ "$(j[1])", "$(j[3])" ],""") From 6d2add298e29744b27e3b5b3bf4977a170886854 Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 16:17:56 +0200 Subject: [PATCH 07/16] Another minor formatting fix. --- deps/parselibs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/parselibs.jl b/deps/parselibs.jl index 42897fe2c..8a2c82816 100644 --- a/deps/parselibs.jl +++ b/deps/parselibs.jl @@ -41,7 +41,7 @@ open(output_filename, "w") do outputfile if libs.stderr != "" error("from libparse: $(libs.stderr)") end - libs_splitted = split(libs.stdout,"\n")[4:end-1] + libs_splitted = split(libs.stdout,"\n")[4:end - 1] libs_splitted = [split(i, " ", keepempty = false) for i in libs_splitted] println(outputfile, ":$(i[1:end - 4]) => [") for j in libs_splitted From 0d0d35552cece5c6de0fcd481efc2fa00509ffb2 Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 16:21:09 +0200 Subject: [PATCH 08/16] Minor text formatting issues. --- src/Meta.jl | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/Meta.jl b/src/Meta.jl index 753c00d9f..f12b43559 100644 --- a/src/Meta.jl +++ b/src/Meta.jl @@ -1,36 +1,41 @@ -## This file generates (at precompilation time) wrapper for all Singular library functions -## All wrappers are given by LIBRARYNAME.functionname. We currently use all caps library names -## to avoid confusion between the LIBRARYNAME modules and other types, for example "Ideal" or "Poly". +#= + This file generates (at precompilation time) wrapper for all Singular library functions + All wrappers are given by LIBRARYNAME.functionname. We currently use all caps library names + to avoid confusion between the LIBRARYNAME modules and other types, for example "Ideal" or "Poly". +=# - -## This script calls singulars parse_libs and creates a dictionary -## containing Singulars libraries and the functions contained in those libraries. +This script calls singulars parse_libs and creates a dictionary +# containing Singulars libraries and the functions contained in those libraries. include("libraryfuncdictionary.jl") -## In the dictionary `input_manipulator_funcs` for each library a dictionary -## can be added, and for each function in this library a preprocesing function -## can be added. The function gets executed on the input, before the library function -## is called. +#= + In the dictionary `input_manipulator_funcs` for each library a dictionary + can be added, and for each function in this library a preprocesing function + can be added. The function gets executed on the input, before the library function + is called. +=# input_manipulator_funcs = Dict( :dummy => Dict( # :dummy => i->[ x + 1 for x in i] ) ) -## The same as `input_manipulator_funcs`, but the function gets executed on the output of -## a function. +# The same as `input_manipulator_funcs`, but the function gets executed on the output of +# a function. output_manipulator_funcs = Dict( :dummy => Dict( # :dummy => i -> i + 1 ) ) -## For each library `lib` a module `LIB` is created, which contains wrappers for all globally exposed -## functions of the library. Each library function `foo` can be called either as `foo(ring, args...)`, -## where `ring` is the ring the arguments belong to, or as `foo(args...)` if no ring is needed or the -## ring con be determined from the input arguments. Furthermore, if applicaple, input and output manipulator -## functions are added to the call. -for (name,funcs) in libraryfunctiondictionary +#= + For each library `lib` a module `LIB` is created, which contains wrappers for all globally exposed + functions of the library. Each library function `foo` can be called either as `foo(ring, args...)`, + where `ring` is the ring the arguments belong to, or as `foo(args...)` if no ring is needed or the + ring con be determined from the input arguments. Furthermore, if applicaple, input and output manipulator + functions are added to the call. +=# +for (name, funcs) in libraryfunctiondictionary name_caps = Symbol( "Lib" * uppercasefirst(string(name))) func_calls = Any[] name_string = string(name) * ".lib" @@ -40,8 +45,8 @@ for (name,funcs) in libraryfunctiondictionary symb = Symbol(func_name) input_manipulator = get(get(input_manipulator_funcs, name, Dict()), symb, identity) output_manipulator = get(get(output_manipulator_funcs, name, Dict()), symb, identity) - push!(func_calls, :($symb(args...) = $(output_manipulator)(low_level_caller($(name_string),$func_name,$(input_manipulator)(args)...)) )) - push!(func_calls, :($symb(ring::PolyRing,args...) = $(output_manipulator)(low_level_caller_rng($(name_string),$func_name,ring,$(input_manipulator)(args)...)) )) + push!(func_calls, :($symb(args...) = $(output_manipulator)(low_level_caller($(name_string), $func_name, $(input_manipulator)(args)...)) )) + push!(func_calls, :($symb(ring::PolyRing,args...) = $(output_manipulator)(low_level_caller_rng($(name_string), $func_name, ring, $(input_manipulator)(args)...)) )) end end eval(:(baremodule $name_caps From 81d55b2f7f2b093c00dd8fa3aaebb057e6e35076 Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 16:26:43 +0200 Subject: [PATCH 09/16] Minor textual changes. --- src/caller.jl | 62 ++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/caller.jl b/src/caller.jl index 61d6ad0fe..0d067a4c0 100644 --- a/src/caller.jl +++ b/src/caller.jl @@ -7,12 +7,14 @@ function recursive_translate(x, R) end end -## Entries in this array are as follows -## 1. CMD type of return lvar -## 2. Casting function to correct CxxWrap pointer type -## 3. True if this pointer needs to be passed to a ring to construct the right object -## 4. If the pointer type if ambigious (module, ideal), an additional argument that -## needs to be passed to the ring to construct the right object. +#= + Entries in this array are as follows + 1. CMD type of return lvar + 2. Casting function to correct CxxWrap pointer type + 3. True if this pointer needs to be passed to a ring to construct the right object + 4. If the pointer type if ambigious (module, ideal), an additional argument that + needs to be passed to the ring to construct the right object. +=# casting_functions_pre = Dict(:NUMBER_CMD => (libSingular.NUMBER_CMD_CASTER, true, ()), :RING_CMD => (libSingular.RING_CMD_CASTER, false, ()), :POLY_CMD => (libSingular.POLY_CMD_CASTER, true, ()), @@ -40,15 +42,15 @@ function create_casting_functions() end function convert_ring_content(value_list, rng) - return_dict = Dict{Symbol,Any}() + return_dict = Dict{Symbol, Any}() for i in value_list - return_dict[i[2]] = convert_return_value([false,i[3],i[1]], rng) + return_dict[i[2]] = convert_return_value([false, i[3], i[1]], rng) end return return_dict end -## Converts a single return value back to Julia, i.e., -## a single lvar, not a linked list of such. +# Converts a single return value back to Julia, i.e., +# a single lvar, not a linked list of such. function convert_return_value(single_value, rng = nothing) if single_value[1] error("received list instead of single value") @@ -58,7 +60,7 @@ function convert_return_value(single_value, rng = nothing) return recursive_translate(cast, rng) elseif cast isa libSingular.ring new_ring = rng(cast) - return [ new_ring, convert_ring_content(libSingular.get_ring_content(cast), new_ring) ] + return [new_ring, convert_ring_content(libSingular.get_ring_content(cast), new_ring)] elseif casting_functions[single_value[3]][2] if length(casting_functions[single_value[3]][3]) > 0 cast = rng(cast, Val(casting_functions[single_value[3]][3][1])) @@ -69,8 +71,8 @@ function convert_return_value(single_value, rng = nothing) return cast end -## Converts a linked list of lvars (already converted to Julia array) back -## to Singular.jl types. +# Converts a linked list of lvars (already converted to Julia array) back +# to Singular.jl types. function convert_return_list(list_value, ring = nothing) if list_value[1] return map(i -> convert_return_value(i, ring), list_value[2:end]) @@ -97,49 +99,49 @@ function get_ring(arg_list) end function prepare_argument(x::Array{Int64,1}) - return Any[ mapping_types_reversed[:INTVEC_CMD], libSingular.jl_array_to_intvec(x) ], nothing + return Any[mapping_types_reversed[:INTVEC_CMD], libSingular.jl_array_to_intvec(x)], nothing end function prepare_argument(x::Array{Int64,2}) - return Any[ mapping_types_reversed[:INTMAT_CMD], libSingular.jl_array_to_intmat(x) ], nothing + return Any[mapping_types_reversed[:INTMAT_CMD], libSingular.jl_array_to_intmat(x)], nothing end function prepare_argument(x::Int64) - return Any[ mapping_types_reversed[:INT_CMD], Ptr{Cvoid}(x) ], nothing + return Any[mapping_types_reversed[:INT_CMD], Ptr{Cvoid}(x)], nothing end function prepare_argument(x::String) - return Any[ mapping_types_reversed[:STRING_CMD], libSingular.copy_string_to_void(x) ], nothing + return Any[mapping_types_reversed[:STRING_CMD], libSingular.copy_string_to_void(x)], nothing end function prepare_argument(x::PolyRing) new_ptr = libSingular.get_ring_ref(x.ptr) - return Any[ mapping_types_reversed[:RING_CMD], new_ptr ], x + return Any[mapping_types_reversed[:RING_CMD], new_ptr], x end function prepare_argument(x::spoly) rng = parent(x) - return Any[ mapping_types_reversed[:POLY_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng.ptr) ], rng + return Any[mapping_types_reversed[:POLY_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng.ptr)], rng end function prepare_argument(x::svector) rng = parent(x).base_ring - return Any[ mapping_types_reversed[:VECTOR_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng.ptr) ], rng + return Any[mapping_types_reversed[:VECTOR_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng.ptr)], rng end function prepare_argument(x::sideal) rng = parent(x).base_ring - return Any[ mapping_types_reversed[:IDEAL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng.ptr)], rng + return Any[mapping_types_reversed[:IDEAL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng.ptr)], rng end function prepare_argument(x::smodule) rng = parent(x).base_ring - return Any[ mapping_types_reversed[:MODUL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng.ptr)], rng + return Any[mapping_types_reversed[:MODUL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng.ptr)], rng end function prepare_argument(x::sresolution) rng = base_ring(x) - res = Any[ mapping_types_reversed[:RESOLUTION_CMD], libSingular.create_syStrategy_data(x.ptr, rng.ptr) ] + res = Any[mapping_types_reversed[:RESOLUTION_CMD], libSingular.create_syStrategy_data(x.ptr, rng.ptr)] return res, rng end @@ -148,16 +150,16 @@ function prepare_argument(x::Any) ptr = x.ptr rng = parent(x) new_ptr = libSingular.n_Copy(ptr, rng.ptr) - return Any[ mapping_types_reversed[:NUMBER_CMD], new_ptr.cpp_object ], nothing + return Any[mapping_types_reversed[:NUMBER_CMD], new_ptr.cpp_object], nothing elseif x.ptr isa libSingular.ip_smatrix rng = parent(x) - return Any[ mapping_types_reversed[:MATRIX_CMD], libSingular.mpCopy(x.ptr, rng.ptr).cpp_object ], rng + return Any[mapping_types_reversed[:MATRIX_CMD], libSingular.mpCopy(x.ptr, rng.ptr).cpp_object ], rng elseif x.ptr isa libSingular.__mpz_struct - return Any[ mapping_types_reversed[:BIGINT_CMD], x.ptr.cpp_object ], nothing + return Any[mapping_types_reversed[:BIGINT_CMD], x.ptr.cpp_object], nothing elseif x.ptr isa libSingular.sip_smap - return Any[ mapping_types_reversed[:MAP_CMD], x.ptr.cpp_object ], nothing + return Any[mapping_types_reversed[:MAP_CMD], x.ptr.cpp_object], nothing elseif x.ptr isa libSingular.bigintmat - return Any[ mapping_types_reversed[:BIGINTMAT_CMD], x.ptr.cpp_object ], nothing + return Any[mapping_types_reversed[:BIGINTMAT_CMD], x.ptr.cpp_object], nothing end end @@ -165,7 +167,7 @@ end function low_level_caller_rng(lib::String, name::String, ring, args...) libSingular.load_library(lib) arguments = [prepare_argument(i) for i in args] - arguments = Any[ i for (i, j) in arguments ] + arguments = Any[i for (i, j) in arguments] return_value = libSingular.call_singular_library_procedure(name, ring.ptr, arguments) return convert_return_list(return_value, ring) end @@ -179,7 +181,7 @@ function low_level_caller(lib::String, name::String, args...) rng = j end end - arguments = Any[ i for (i, j) in arguments ] + arguments = Any[i for (i, j) in arguments] return_values = nothing rng = (rng == nothing) ? C_NULL : rng.ptr return_value = libSingular.call_singular_library_procedure(name, rng, arguments) From 7d12206df0e096e6280df3cfe15ed6c83158b797 Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 16:31:20 +0200 Subject: [PATCH 10/16] Minor textual formatting. --- src/module/ModuleTypes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/ModuleTypes.jl b/src/module/ModuleTypes.jl index d6fb2b0ca..27ed66537 100644 --- a/src/module/ModuleTypes.jl +++ b/src/module/ModuleTypes.jl @@ -41,7 +41,7 @@ This needs to be indicated due to the fact that Singulars vectors and polys are both stored in the poly data structure. """ function (R::PolyRing{T})(m::libSingular.poly,::Val{:vector}) where T - return svector{T}(R,1,m) + return svector{T}(R, 1, m) end function _svector_clear_fn(p::svector) From 3f9f66221e2a2f26e34707df99409b6cfdafbddc Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 16:32:45 +0200 Subject: [PATCH 11/16] Typo. --- src/module/ModuleTypes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/ModuleTypes.jl b/src/module/ModuleTypes.jl index 27ed66537..d854d7be1 100644 --- a/src/module/ModuleTypes.jl +++ b/src/module/ModuleTypes.jl @@ -105,7 +105,7 @@ end If R is called with a low-level ideal pointer, along with Val(:module), it will interpret the ideal pointer as a module. -This needs to be indicated due to the fact that Singulars +This needs to be indicated due to the fact that Singular's modules and ideals are both stored in the ideal data structure. """ function (R::PolyRing{T})(m::libSingular.ideal,::Val{:module}) where T From a57219126efe8b5d5d02e6c86b79662c01afd2ee Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 16:34:11 +0200 Subject: [PATCH 12/16] Minor textual fixes. --- src/resolution/resolution.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resolution/resolution.jl b/src/resolution/resolution.jl index 819ad1d91..986d43e65 100644 --- a/src/resolution/resolution.jl +++ b/src/resolution/resolution.jl @@ -27,7 +27,7 @@ end function getindex(r::sresolution, i::Int) checkbounds(r, i) R = base_ring(r) - ptr = libSingular.getindex_internal(r.ptr, i-1, r.minimal ) + ptr = libSingular.getindex_internal(r.ptr, i - 1, r.minimal ) if ptr.cpp_object != C_NULL ptr = libSingular.id_Copy(ptr, R.ptr) end @@ -113,7 +113,7 @@ function show(io::IO, r::sresolution) end end for i = 1:len - 1 - ptr = libSingular.getindex_internal(r.ptr,i-1,r.minimal) + ptr = libSingular.getindex_internal(r.ptr, i - 1, r.minimal) if ptr.cpp_object == C_NULL break end From 055033c615f935e1750d762a89b56cf8e7f52db5 Mon Sep 17 00:00:00 2001 From: wbhart Date: Thu, 19 Sep 2019 17:11:08 +0200 Subject: [PATCH 13/16] Typo. --- src/Meta.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Meta.jl b/src/Meta.jl index f12b43559..20f990062 100644 --- a/src/Meta.jl +++ b/src/Meta.jl @@ -4,7 +4,7 @@ to avoid confusion between the LIBRARYNAME modules and other types, for example "Ideal" or "Poly". =# -This script calls singulars parse_libs and creates a dictionary +# This script calls singulars parse_libs and creates a dictionary # containing Singulars libraries and the functions contained in those libraries. include("libraryfuncdictionary.jl") From 1e3ac2ea8ad919b321e23e406bbdcf305433fdd7 Mon Sep 17 00:00:00 2001 From: Sebastian Gutsche Date: Thu, 19 Sep 2019 18:17:43 +0200 Subject: [PATCH 14/16] Added Ring for test --- test/caller-test.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/caller-test.jl b/test/caller-test.jl index 752d72b3a..ed9e2925a 100644 --- a/test/caller-test.jl +++ b/test/caller-test.jl @@ -40,7 +40,7 @@ function test_caller() @test Singular.LibPrimdec.primdecGTZ(R,i1) isa Array i1 = Ideal(R, x*z, y*z, x^3-y^3) - @test Singular.LibNormal.normal(i1, "withDelta", "prim") isa Array + @test Singular.LibNormal.normal(R, i1, "withDelta", "prim") isa Array println("PASS") end From 3d2b89efc7c56688004c14779a65dd586947f34f Mon Sep 17 00:00:00 2001 From: Sebastian Gutsche Date: Thu, 19 Sep 2019 18:32:08 +0200 Subject: [PATCH 15/16] Fixed bug in the low_level_caller without specific ring argument --- src/caller.jl | 4 ++-- test/caller-test.jl | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/caller.jl b/src/caller.jl index 0d067a4c0..2a6cae296 100644 --- a/src/caller.jl +++ b/src/caller.jl @@ -183,7 +183,7 @@ function low_level_caller(lib::String, name::String, args...) end arguments = Any[i for (i, j) in arguments] return_values = nothing - rng = (rng == nothing) ? C_NULL : rng.ptr - return_value = libSingular.call_singular_library_procedure(name, rng, arguments) + rng_ptr = (rng == nothing) ? C_NULL : rng.ptr + return_value = libSingular.call_singular_library_procedure(name, rng_ptr, arguments) return convert_return_list(return_value, rng) end diff --git a/test/caller-test.jl b/test/caller-test.jl index ed9e2925a..0f28068fd 100644 --- a/test/caller-test.jl +++ b/test/caller-test.jl @@ -42,5 +42,7 @@ function test_caller() i1 = Ideal(R, x*z, y*z, x^3-y^3) @test Singular.LibNormal.normal(R, i1, "withDelta", "prim") isa Array + @test Singular.LibNormal.normal(i1, "withDelta", "prim") isa Array + println("PASS") end From c1f13fcef34384b59dd33e72b892be1f7ee2baf9 Mon Sep 17 00:00:00 2001 From: wbhart Date: Mon, 23 Sep 2019 19:26:24 +0200 Subject: [PATCH 16/16] Update resolution.jl --- src/resolution/resolution.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/resolution/resolution.jl b/src/resolution/resolution.jl index 986d43e65..99f8014e7 100644 --- a/src/resolution/resolution.jl +++ b/src/resolution/resolution.jl @@ -21,7 +21,8 @@ elem_type(::ResolutionSet{T}) where T <: AbstractAlgebra.RingElem = sresolution{ parent_type(::Type{sresolution{T}}) where T <: AbstractAlgebra.RingElem = ResolutionSet{T} function checkbounds(r::sresolution, i::Int) - (i < 1 || i > length(r)) && throw(BoundsError(r, i)) + # structure has 1 more item than the mathematical length + (i < 1 || i > length(r) + 1) && throw(BoundsError(r, i)) end function getindex(r::sresolution, i::Int)