Skip to content

Commit

Permalink
Merge branch 'master' into TB_julia_to_gap
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasBreuer committed Sep 23, 2024
2 parents c30e5b8 + e60382d commit 1ab5ec2
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 278 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;
84 changes: 17 additions & 67 deletions pkg/JuliaInterface/gap/JuliaInterface.gd
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@
#! The result is <K>true</K> if and only if <A>obj</A> is a pointer to a
#! &Julia; object.
#!
#! The results of <Ref Func="JuliaModule"/> are always in
#! <Ref Filt="IsJuliaObject" Label="for IsObject"/>.
#! @BeginExampleSession
#! gap> julia_fun:= JuliaEvalString( "sqrt" );
#! <Julia: sqrt>
Expand All @@ -107,12 +105,22 @@
#! <Julia: 1.4142135623730951>
#! gap> IsJuliaObject( julia_val );
#! true
#! gap> julia_x:= JuliaEvalString( "x = 4" );
#! @EndExampleSession
#! However not every object living on the Julia side is in this filter.
#! For example Julia booleans and small <C>Int</C> values are directly
#! translated to GAP booleans and small integers, while for Julia functions
#! and wrappers dedicated wrappers are used for improved efficiency
#! respectively additional features.
#! @BeginExampleSession
#! gap> JuliaEvalString( "x = 4" );;
#! gap> Julia.x;
#! 4
#! gap> IsJuliaObject( julia_x );
#! gap> IsJuliaObject( Julia.x );
#! false
#! gap> IsJuliaObject( Julia.sqrt );
#! false
#! gap> IsJuliaObject( Julia.Main );
#! false
#! gap> IsJuliaObject( JuliaModule( "Main" ) );
#! true
#! @EndExampleSession
DeclareCategory( "IsJuliaObject", IsObject );

Expand All @@ -136,8 +144,8 @@ BindGlobal("TheTypeJuliaObject", NewType( JuliaObjectFamily, IsJuliaObject ));
#! should <E>not</E> be in the filter
#! <Ref Filt="IsJuliaObject" Label="for IsObject"/>.
#!
#! Examples of objects in <Ref Filt="IsJuliaWrapper" Label="for IsObject"/>
#! are the return values of <Ref Func="JuliaModule"/>.
#! For example, any Julia modules such as <C>Julia.Base</C> are
#! in the filter <Ref Filt="IsJuliaWrapper" Label="for IsObject"/>.
DeclareCategory( "IsJuliaWrapper", IsObject );

#! @Arguments obj
Expand Down Expand Up @@ -238,50 +246,6 @@ DeclareGlobalFunction( "JuliaImportPackage" );

#! @Section Access to &Julia; objects

## Internal
BindGlobal( "_JuliaFunctions", rec( ) );

#! @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 All @@ -301,19 +265,6 @@ DeclareGlobalFunction( "JuliaFunction" );
#! @EndExampleSession
DeclareGlobalVariable( "Julia" );

#! @Arguments name
#! @Returns a &Julia; object
#! @Description
#! Returns the &Julia; object that points to the &Julia; module
#! with name <A>name</A>.
#! @BeginExampleSession
#! gap> gapmodule:= JuliaModule( "GAP" );
#! <Julia: GAP>
#! gap> gapmodule = JuliaPointer( Julia.GAP );
#! true
#! @EndExampleSession
DeclareGlobalFunction( "JuliaModule" );

#! @Arguments juliaobj
#! @Returns a string.
#! @Description
Expand Down Expand Up @@ -419,8 +370,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
51 changes: 13 additions & 38 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,27 +34,27 @@ 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 );
\.\:\=( module!.storage, rnum, 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 );
\.\:\=( module!.storage, rnum, var );
fi;

return global_variable;
return var;
end );

InstallMethod( \.\:\=,
Expand Down Expand Up @@ -93,7 +83,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 Expand Up @@ -152,21 +142,6 @@ InstallGlobalFunction( JuliaTypeInfo,
end );


InstallGlobalFunction( JuliaModule,
function( name )
if not IsString( name ) then
Error( "JuliaModule: <name> must be a string" );
fi;
if not IsBound( Julia.(name) ) then
Error( "JuliaModule: Module <name> does not exist, did you import it?" );
fi;
if not IsJuliaModule( Julia.(name) ) then
Error( "JuliaModule: <name> is not a module" );
fi;
return JuliaPointer( Julia.(name) );
end );


InstallGlobalFunction( GetJuliaScratchspace,
function( key )
if not IsString( key ) then
Expand Down
Loading

0 comments on commit 1ab5ec2

Please sign in to comment.