-
Notifications
You must be signed in to change notification settings - Fork 20
Accessing Singular from Julia
malex984 edited this page Dec 8, 2014
·
26 revisions
using Cxx
const singdir = joinpath( ENV["HOME"], "singular-4/T/home/wbhart/singular-4/") # const singdir = joinpath( ENV["HOME"], "S" )
addHeaderDir(joinpath(singdir, "include"), kind = C_System)
addHeaderDir(joinpath(singdir, "include", "singular"), kind = C_System)
cxxinclude("Singular/libsingular.h", isAngled=false)
libSingular = dlopen(joinpath(singdir, "lib", "libSingular.so"), RTLD_GLOBAL)
@cxx siInit(pointer(joinpath(singdir, "bin", "Singular")))
@cxx StringSetS(pointer("Hello World!"))
@cxx feStringAppendResources(0)
s = @cxx StringEndS()
# @cxx PrintS(s) # BUG: PrintS is a C function
# icxx" PrintS($s); " # quick and dirty shortcut
PrintS(m) = ccall( dlsym (libSingular, :PrintS), Void, (Ptr{Uint8},), m) # another workaround
PrintS(s)
icxx" char* n [] = { (char*)\"t\"}; ring r = rDefault( 13, 1, n); rWrite(r); PrintLn(); rDelete(r); "
function jlInit(cf::Ptr{Void}, ::Ptr{Void})
println("jlInit: new coeffs: $cf"); return convert( Cint, 1);
end
const cjlInit = cfunction(jlInit, Cint, (Ptr{Void},Ptr{Void}))
new_typ = icxx" return nRegister( n_unknown, (cfInitCharProc)$cjlInit); " # CppEnum{:n_coeffType}(14)
new_coeff = icxx" return nInitChar( $new_typ, 0 ); "
Here is my idea for Julia wrappers for Singular "pointer" types (all of low level element types: number
, poly
, ideal
) which are to be treated in conjunction with corresponding management objects (coeffs
, ring
):
abstract SingularCoeffs
# possible concrete coeff types:
type SingularQQ <: SingularCoeffs end
immutable SingularZZ <: SingularCoeffs end
bitstype WORD_SIZE GenericSingularCoeffs <: SingularCoeffs
abstract SingularNumber <: Number
bitstype WORD_SIZE GenericSingularNumber{Coeffs <: SingularCoeffs} <: SingularNumber
immutable RRSingularNumber <: SingularNumber end
InitSingularNumber{Coeffs <: SingularCoeffs}( ::Type{Coeffs}, i) = reinterpret(GenericSingularNumber{Coeffs}, i)
InitSingularNumber( SingularQQ, 2 ) # GenericSingularNumber{SingularQQ}(0x0000000000000002)
isbits(ans) # true
function myop{C}( a::GenericSingularNumber{C}, b::GenericSingularNumber{C} )
println( "myop ($a, $b) over $C")
end
myop( InitSingularNumber( SingularQQ, 22 ), InitSingularNumber( SingularQQ, 66 ) )
myop (GenericSingularNumber{SingularQQ}(0x0000000000000016), GenericSingularNumber{SingularQQ}(0x0000000000000042)) over SingularQQ
myop( InitSingularNumber( SingularZZ, 22 ), InitSingularNumber( SingularZZ, 66 ) )
myop (GenericSingularNumber{SingularZZ}(0x0000000000000016), GenericSingularNumber{SingularZZ}(0x0000000000000042)) over SingularZZ
myop( InitSingularNumber( SingularQQ, 22 ), InitSingularNumber( SingularZZ, 66 ) )
# ERROR: `myop` has no method matching myop(::GenericSingularNumber{SingularQQ}, ::GenericSingularNumber{SingularZZ})
myop( InitSingularNumber( SingularZZ, 22 ), InitSingularNumber( SingularQQ, 66 ) )
# ERROR: `myop` has no method matching myop(::GenericSingularNumber{SingularZZ}, ::GenericSingularNumber{SingularQQ})
Pros:
- we avoid one extra level of indirection (types in Julia are pointers to heap allocated things)
- we can specialize conversions to/from Julia Number types to specific Singular Numbers
Cons:
- we need to do "proper" construction/destruction for all such handles "by hand"
Proof of concept:
using Cxx
cxx"""
typedef void* SingularCoeffs;
typedef void* SingularNumber;
SingularNumber InitSingularNumber( SingularCoeffs cf, unsigned long i )
{ i += (unsigned long)(cf); return (SingularNumber)(i); }
"""
@cxx InitSingularNumber( Ptr{Void}(1), 2) # Ptr{Void} @0x0000000000000003