Skip to content

Commit

Permalink
Merge branch 'master' into lg/module
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoettgens authored Sep 23, 2024
2 parents 3c699ee + e60382d commit fcceba2
Show file tree
Hide file tree
Showing 13 changed files with 44 additions and 229 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:
- 'release-*'
tags: '*'
pull_request:
schedule:
# Every day at 3:08 AM UTC
- cron: '8 3 * * *'

concurrency:
# group by workflow and ref; the last slightly strange component ensures that for pull
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/oscar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:
push:
branches:
- master
schedule:
# Every day at 3:08 AM UTC (Tutorial tests initiated at 2:00AM)
- cron: '8 3 * * *'
workflow_dispatch:

concurrency:
Expand Down
2 changes: 1 addition & 1 deletion pkg/JuliaExperimental/ipynb/GAPJulia_Singular_car.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@
}
],
"source": [
"i:= JuliaFunction( \"Matrix\", \"Singular\" )( I );"
"i:= Julia.Singular.Matrix( I );"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion pkg/JuliaExperimental/tst/singular_blog.tst
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ gap> M:= Julia.Singular.syz( I );
x*gen(3)-2*x*gen(2)+y*gen(3)-y*gen(2)-z*gen(2)
y^2*gen(3)-y^2*gen(2)-y*z*gen(2)-y*gen(1)+z*gen(1)-gen(3)+2*gen(2)
x*y*gen(2)-x*gen(1)-y*gen(1)+gen(2)>
gap> JuliaFunction( "Matrix", "Singular" )( M );
gap> Julia.Singular.Matrix( M );
<Julia: [0, -y+z, -x-y
-2*x-y-z, -y^2-y*z+2, x*y+1
x+y, y^2-1, 0]>
Expand Down
23 changes: 4 additions & 19 deletions pkg/JuliaInterface/example/function_perform.gi
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,17 @@ dirs:= DirectoriesPackageLibrary( "JuliaInterface", "example" );

JuliaIncludeFile( Filename( dirs, "function_perform.jl" ) );

typed_func := JuliaFunction("typed_func", "GapFunctionPerform");
typed_funcNoConv := _JuliaFunctionByModule("typed_func", "GapFunctionPerform");

untyped_func := JuliaFunction("untyped_func");
untyped_funcNoConv := _JuliaFunction("untyped_func");
return_first := Julia.GapFunctionPerform.return_first;

GASMAN("collect"); ListX([1..10^5], [1..10], {i,j} -> i);; time;
GASMAN("collect"); ListX([1..10^5], [1..10], ReturnFirst);; time;
GASMAN("collect"); ListX([1..10^5], [1..10], typed_func);; time;
GASMAN("collect"); ListX([1..10^5], [1..10], untyped_func);; time;
GASMAN("collect"); ListX([1..10^5], [1..10], typed_funcNoConv);; time;
GASMAN("collect"); ListX([1..10^5], [1..10], untyped_funcNoConv);; time;

GASMAN("collect"); ListX([1..10^5], [1..10], return_first);; time;

GASMAN("collect"); ListX("0123456789", [1..10^5], {i,j} -> i);; time;
GASMAN("collect"); ListX("0123456789", [1..10^5], ReturnFirst);; time;
GASMAN("collect"); ListX("0123456789", [1..10^5], typed_func);; time;
GASMAN("collect"); ListX("0123456789", [1..10^5], untyped_func);; time;
GASMAN("collect"); ListX("0123456789", [1..10^5], typed_funcNoConv);; time;
GASMAN("collect"); ListX("0123456789", [1..10^5], untyped_funcNoConv);; time;

GASMAN("collect"); ListX("0123456789", [1..10^5], return_first);; time;

input:=ListWithIdenticalEntries(10^5,fail);;
GASMAN("collect"); ListX("0123456789", input, {i,j} -> i);; time;
GASMAN("collect"); ListX("0123456789", input, ReturnFirst);; time;
GASMAN("collect"); ListX("0123456789", input, typed_func);; time;
GASMAN("collect"); ListX("0123456789", input, untyped_func);; time;
GASMAN("collect"); ListX("0123456789", input, typed_funcNoConv);; time;
GASMAN("collect"); ListX("0123456789", input, untyped_funcNoConv);; time;
GASMAN("collect"); ListX("0123456789", input, return_first);; time;
22 changes: 2 additions & 20 deletions pkg/JuliaInterface/example/function_perform.jl
Original file line number Diff line number Diff line change
@@ -1,25 +1,7 @@
module GapFunctionPerform

import GAP: GapObj

function typed_func(a::GapObj, b::GapObj)
return a
end

function typed_func(a::GapObj, b::Int64)
return a
end

function typed_func(a::Int64, b::GapObj)
function return_first(a, b)
return a
end

function typed_func(a::Int64, b::Int64)
return a
end

end

function untyped_func(a, b)
return a
end
end
4 changes: 1 addition & 3 deletions pkg/JuliaInterface/example/orbits.gi
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ end;
example_dirs := DirectoriesPackageLibrary( "JuliaInterface", "example" );
JuliaIncludeFile( Filename( example_dirs, "orbits.jl" ) );

bahn_jl := JuliaFunction( "bahn" );

grp := SymmetricGroup( 10000 );
gens := GeneratorsOfGroup( grp );;

bahn(1, gens, OnPoints);;time;
bahn_jl(1, gens, OnPoints);;time;
Julia.bahn(1, gens, OnPoints);;time;
46 changes: 1 addition & 45 deletions pkg/JuliaInterface/gap/JuliaInterface.gd
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,6 @@ DeclareAttribute( "JuliaPointer", IsJuliaWrapper );
#! true
#! gap> Julia.GAP.julia_to_gap;
#! <Julia: julia_to_gap>
#! gap> JuliaFunction( "julia_to_gap", "GAP" ); # the same function
#! <Julia: julia_to_gap>
#! @EndExampleSession
DeclareCategory( "IsJuliaModule", IsJuliaWrapper and IsRecord );

Expand Down Expand Up @@ -246,47 +244,6 @@ DeclareGlobalFunction( "JuliaImportPackage" );

#! @Section Access to &Julia; objects

#! @Arguments function_name[, module_name]
#! @Returns a function
#! @Description
#! Returns a &GAP; function that wraps the &Julia; function with identifier
#! <A>function_name</A> from the module <A>module_name</A>.
#! Both arguments must be strings.
#! If <A>module_name</A> is not given,
#! the function is taken from &Julia;'s <C>Main</C> module.
#!
#! @BeginExampleSession
#! gap> fun:= JuliaFunction( "sqrt" );
#! <Julia: sqrt>
#! gap> Print( fun );
#! function ( arg... )
#! <<kernel code>> from Julia:sqrt
#! end
#! gap> IsFunction( fun );
#! true
#! gap> IsJuliaObject( fun );
#! false
#! @EndExampleSession
#!
#! Alternatively, one can access &Julia; functions also via the global object
#! <Ref Var="Julia"/>, as follows.
#!
#! @BeginExampleSession
#! gap> Julia.sqrt;
#! <Julia: sqrt>
#! @EndExampleSession
#!
#! Note that each call to <Ref Func="JuliaFunction"/> and each component
#! access to <Ref Var="Julia"/> create a <E>new</E> &GAP; object.
#!
#! @BeginExampleSession
#! gap> IsIdenticalObj( JuliaFunction( "sqrt" ), JuliaFunction( "sqrt" ) );
#! false
#! gap> IsIdenticalObj( Julia.sqrt, Julia.sqrt );
#! false
#! @EndExampleSession
DeclareGlobalFunction( "JuliaFunction" );

#! @Description
#! This global variable represents the &Julia; module <C>Main</C>,
#! see <Ref Filt="IsJuliaModule" Label="for IsJuliaWrapper and IsRecord"/>.
Expand Down Expand Up @@ -411,8 +368,7 @@ DeclareGlobalFunction( "CallJuliaFunctionWithKeywordArguments" );
#! <Julia: 1.4142135623730951>
#! @EndExampleSession
#! In fact, there are slightly different kinds of function calls.
#! A &Julia; function such as <C>Julia.sqrt</C>
#! (or equivalently <C>JuliaFunction( "sqrt" )</C>) is represented by
#! A &Julia; function such as <C>Julia.sqrt</C> is represented by
#! a &GAP; function object,
#! and calls to it are executed on the C level,
#! using &Julia;'s <C>jl_call</C>.
Expand Down
34 changes: 12 additions & 22 deletions pkg/JuliaInterface/gap/JuliaInterface.gi
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,9 @@
# Implementations
#

InstallGlobalFunction( JuliaFunction,
function( arglist... )
if Length( arglist ) = 1 and IsString( arglist[ 1 ] ) then
return _JuliaFunction( arglist[ 1 ] );
elif Length( arglist ) = 2 and ForAll( arglist, IsString ) then
return _JuliaFunctionByModule( arglist[1], arglist[2] );
fi;
Error( "arguments must be strings function_name[,module_name]" );
end );

BindGlobal( "_JULIA_MODULE_TYPE", _JuliaGetGlobalVariable( "Module" ) );
BindGlobal( "_JULIA_FUNCTION_TYPE", _JuliaGetGlobalVariable( "Function" ) );
BindGlobal( "_JULIA_ISA", JuliaFunction( "isa" ) );
BindGlobal( "_JULIA_MODULE_TYPE", _JuliaGetGlobalVariableByModule( "Module", "Core" ) );
BindGlobal( "_JULIA_FUNCTION_TYPE", _JuliaGetGlobalVariableByModule( "Function", "Core" ) );
BindGlobal( "_JULIA_ISA", _WrapJuliaFunction( _JuliaGetGlobalVariableByModule( "isa", "Core" ) ) );

BindGlobal( "_WrapJuliaModule",
function( name, julia_pointer )
Expand Down Expand Up @@ -44,26 +34,26 @@ InstallMethod( ViewString,
InstallMethod( \.,
[ "IsJuliaModule", "IsPosInt" ],
function( module, rnum )
local rnam, global_variable;
local rnam, var;

if IsBound\.( module!.storage, rnum ) then
return \.(module!.storage, rnum );
fi;

rnam := NameRNam( rnum );

global_variable := _JuliaGetGlobalVariableByModule( rnam, JuliaPointer( module ) );
if global_variable = fail then
var := _JuliaGetGlobalVariableByModule( rnam, JuliaPointer( module ) );
if var = fail then
Error( rnam, " is not bound in Julia" );
fi;

if _JULIA_ISA( global_variable, _JULIA_FUNCTION_TYPE ) then
global_variable := _JuliaFunction( global_variable );
elif _JULIA_ISA( global_variable, _JULIA_MODULE_TYPE ) then
global_variable := _WrapJuliaModule( rnam, global_variable );
if _JULIA_ISA( var, _JULIA_FUNCTION_TYPE ) then
var := _WrapJuliaFunction( var );
elif _JULIA_ISA( var, _JULIA_MODULE_TYPE ) then
var := _WrapJuliaModule( rnam, var );
fi;

return global_variable;
return var;
end );

InstallMethod( \.\:\=,
Expand Down Expand Up @@ -92,7 +82,7 @@ function( obj )
return JuliaToGAP( IsList, Julia.GAP.get_symbols_in_module( JuliaPointer( obj ) ), true );
end);

InstallValue( Julia, _WrapJuliaModule( "Main", _JuliaGetGlobalVariable( "Main" ) ) );
InstallValue( Julia, _WrapJuliaModule( "Main", _JuliaGetGlobalVariableByModule( "Main", "Main" ) ) );

InstallGlobalFunction( "JuliaIncludeFile",
function( filename, module_name... )
Expand Down
72 changes: 6 additions & 66 deletions pkg/JuliaInterface/src/JuliaInterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,63 +129,21 @@ Obj NewJuliaObj(jl_value_t * v)
}


jl_function_t * get_function_from_obj_or_string(Obj func)
{
jl_function_t * f = NULL;
BEGIN_GAP_SYNC();
if (IS_JULIA_OBJ(func)) {
f = (jl_function_t *)GET_JULIA_OBJ(func);
}
else if (IsStringConv(func)) {
// jl_get_function is a thin wrapper for jl_get_global and never
// throws an exception
f = jl_get_function(jl_main_module, CONST_CSTR_STRING(func));
if (f == 0) {
ErrorMayQuit("Function is not defined in julia", 0, 0);
}
}
else
ErrorMayQuit("argument is not a julia object or string", 0, 0);
END_GAP_SYNC();
return f;
}


void ResetUserHasQUIT(void)
{
STATE(UserHasQUIT) = 0;
}


/*
* Returns the function from the Object <func>
* or the function with name <func> from
* the Julia main module.
* Wrap Julia object <func> into a GAP function.
*/
static Obj Func_JuliaFunction(Obj self, Obj func)
static Obj Func_WrapJuliaFunction(Obj self, Obj func)
{
jl_function_t * f = get_function_from_obj_or_string(func);
return WrapJuliaFunc(f);
}
if (!IS_JULIA_OBJ(func))
ErrorMayQuit("argument is not a julia object", 0, 0);

/*
* Returns the function with name <funcName> from the Julia module with
* name <moduleName>.
*/
static Obj Func_JuliaFunctionByModule(Obj self, Obj funcName, Obj moduleName)
{
BEGIN_GAP_SYNC();
RequireStringRep("_JuliaFunctionByModule", funcName);
RequireStringRep("_JuliaFunctionByModule", moduleName);

jl_module_t * m = get_module(CONST_CSTR_STRING(moduleName));
// jl_get_function is a thin wrapper for jl_get_global and never throws
// an exception
jl_function_t * f = jl_get_function(m, CONST_CSTR_STRING(funcName));
if (f == 0)
ErrorMayQuit("Function %g.%g is not defined in julia",
(Int)moduleName, (Int)funcName);
END_GAP_SYNC();
jl_function_t * f = (jl_function_t *)GET_JULIA_OBJ(func);
return WrapJuliaFunc(f);
}

Expand Down Expand Up @@ -233,22 +191,6 @@ static int gap_jl_boundp(jl_module_t * m, jl_sym_t * var)
#endif
}

// Returns the julia object GAP object that holds a pointer to the value
// currently bound to the julia identifier <name>.
static Obj Func_JuliaGetGlobalVariable(Obj self, Obj name)
{
BEGIN_GAP_SYNC();
RequireStringRep("_JuliaGetGlobalVariable", name);

jl_sym_t * symbol = jl_symbol(CONST_CSTR_STRING(name));
END_GAP_SYNC();
if (!gap_jl_boundp(jl_main_module, symbol)) {
return Fail;
}
jl_value_t * value = jl_get_global(jl_main_module, symbol);
return gap_julia(value);
}

// Returns the julia object GAP object that holds a pointer to the value
// currently bound to the julia identifier <moduleName>.<name>.
static Obj Func_JuliaGetGlobalVariableByModule(Obj self, Obj name, Obj module)
Expand Down Expand Up @@ -309,11 +251,9 @@ static void MarkJuliaObject(Bag bag)

// Table of functions to export
static StructGVarFunc GVarFuncs[] = {
GVAR_FUNC(_JuliaFunction, 1, "string"),
GVAR_FUNC(_JuliaFunctionByModule, 2, "funcName, moduleName"),
GVAR_FUNC(_WrapJuliaFunction, 1, "juliafunc"),
GVAR_FUNC(IS_JULIA_FUNC, 1, "obj"),
GVAR_FUNC(JuliaEvalString, 1, "string"),
GVAR_FUNC(_JuliaGetGlobalVariable, 1, "name"),
GVAR_FUNC(_JuliaGetGlobalVariableByModule, 2, "name, module"),
GVAR_FUNC(JuliaSymbol, 1, "name"),
GVAR_FUNC(_JuliaGetGapModule, 0, ""),
Expand Down
Loading

0 comments on commit fcceba2

Please sign in to comment.