Skip to content

Commit

Permalink
Julia interface (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
amontoison authored Feb 14, 2024
1 parent 12cabad commit 79cfa46
Show file tree
Hide file tree
Showing 127 changed files with 10,268 additions and 6,765 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/meson.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,18 @@ jobs:
shell: bash
run: |
echo "GALAHAD=$GITHUB_WORKSPACE" >> $GITHUB_ENV
echo "JULIA_GALAHAD_LIBRARY_PATH=$GITHUB_WORKSPACE/galahad/lib" >> $GITHUB_ENV
echo "DEPS=$GITHUB_WORKSPACE/.." >> $GITHUB_ENV
if [[ "${{matrix.os}}" == "ubuntu-latest" ]]; then
echo "LIBDIR=lib" >> $GITHUB_ENV
echo "JULIA_GALAHAD_LIBRARY_PATH=$GITHUB_WORKSPACE/galahad/lib" >> $GITHUB_ENV
fi
if [[ "${{matrix.os}}" == "macos-latest" ]]; then
echo "LIBDIR=lib" >> $GITHUB_ENV
echo "JULIA_GALAHAD_LIBRARY_PATH=$GITHUB_WORKSPACE/galahad/lib" >> $GITHUB_ENV
fi
if [[ "${{matrix.os}}" == "windows-latest" ]]; then
echo "LIBDIR=bin" >> $GITHUB_ENV
echo "JULIA_GALAHAD_LIBRARY_PATH=$GITHUB_WORKSPACE/galahad/bin" >> $GITHUB_ENV
fi
- name: Install dependencies
Expand Down
5 changes: 4 additions & 1 deletion GALAHAD.jl/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ version = "0.1.0"
[deps]
GALAHAD_jll = "1621ace8-c1f0-5e32-a05d-ca786afa56c2"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
OpenBLAS32_jll = "656ef2d0-ae68-5445-9ca0-591084a874a2"

[compat]
julia = "1.9"

[extras]
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "Printf"]
test = ["Test", "Printf", "Accessors"]
4 changes: 1 addition & 3 deletions GALAHAD.jl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,5 @@ permanently in the shell's startup file, or in

## Documentation

Documentation is available online from

https://ralna.github.io/galahad_docs/html/Julia
Documentation is available online from [https://ralna.github.io/galahad_docs/html/Julia](https://ralna.github.io/galahad_docs/html/Julia).

26 changes: 26 additions & 0 deletions GALAHAD.jl/gen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,29 @@ include("wrappers/abcd.jl")

Now, the Julia wrappers for the `abcd` package are accessible upon
loading the Julia interface with `using GALAHAD`.

# Tests

The file `examples.jl` aids in generating Julia tests based on the
C tests within a GALAHAD package. To facilitate the translation of a C
test `GALAHAD/src/abcd/C/abcdtf.c` into a Julia test, follow these steps:

Add the following entry to `examples.jl`:

```julia
(name == "abcd") && examples("abcd", "tf")
```

Replace `"tf"` with `"t"` if translating a test from `abcdt.c`, or use `""` if no corresponding C test exists.

After including `examples.jl`, invoking `main("abcd")` will generate the file `test_abcd.jl` in the
directory `GALAHAD.jl/test`, along with a symbolic link pointing to this file in `GALAHAD/src/abcd/Julia`.

After manual modifications to ensure the Julia test works correctly, you can utilize `clean_example("abcd")`
to format the file.

To test the new package named `abcd` alongside other packages, insert the following line in `GALAHAD.jl/test/runtests.jl`:

```julia
include("test_abcd.jl")
```
204 changes: 123 additions & 81 deletions GALAHAD.jl/gen/examples.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
using JuliaFormatter

function examples(package::String, example::String)
if example == ""
text = "# test_" * package * ".jl\n# Simple code to test the Julia interface to " * uppercase(package) * "\n"
text = "# test_" * package * ".jl\n# Simple code to test the Julia interface to " * uppercase(package) * "\n\n"
text = text * "using GALAHAD\nusing Test\n\nfunction test_$package()\n"
text = text * " data = Ref{Ptr{Cvoid}}()\n"
text = text * " control = Ref{$(package)_control_type{Float64}}()\n"
text = text * " inform = Ref{$(package)_inform_type{Float64}}()\n\n"
text = text * " status = Ref{Cint}()\n"
text = text * " $(package)_initialize(data, control, status)\n"
text = text * " $(package)_information(data, inform, status)\n"
text = text * " $(package)_terminate(data, control, inform)\n\n"
text = text * " return 0\n"
else
src = "../../src/$package/C/" * package * example * ".c"
text = read(src, String)
end
dst = "../test/test_" * package * ".jl"
text = replace(text, " " => "")
text = replace(text, "int main(void) {\n\n" => "# test_$package.jl\n# Simple code to test the Julia interface to " * uppercase(package) * "\n\nusing GALAHAD\nusing Printf\n\n")
text = replace(text, "int main(void) {\n\n" => "# test_$package.jl\n# Simple code to test the Julia interface to " * uppercase(package) * "\n\nusing GALAHAD\nusing Test\nusing Printf\nusing Accessors\n\nfunction test_$package()\n")
text = replace(text, "\" i_ipc_ \"" => "i")
text = replace(text, "\" d_ipc_ \"" => "d")
text = replace(text, "ipc_" => "int")
text = replace(text, "rpc_" => "real_wp_")
text = replace(text, "//" => "#")
text = replace(text, ";" => "")
text = replace(text, "&" => "")
Expand All @@ -16,35 +31,47 @@ function examples(package::String, example::String)
text = replace(text, "printf" => "@printf")
text = replace(text, "else if" => "elseif")
text = replace(text, "}else{" => "else")
text = replace(text, "}elseif" => "elseif")
text = replace(text, "} else {" => "else")
text = replace(text, "void *data" => "data = [Ptr{Ptr{Cvoid}}()]")
text = replace(text, "struct $(package)_control_type control" => "control = $(package)_control_type{Float64}()")
text = replace(text, "struct $(package)_inform_type inform" => "inform = $(package)_inform_type{Float64}()")
text = replace(text, "void *data" => "data = Ref{Ptr{Cvoid}}()")
text = replace(text, "struct $(package)_control_type control" => "control = Ref{$(package)_control_type{Float64}}()")
text = replace(text, "struct $(package)_inform_type inform" => "inform = Ref{$(package)_inform_type{Float64}}()")
text = replace(text, "control." => "control[].")
text = replace(text, "inform." => "inform[].")
text = replace(text, "} #" => "] #")
text = replace(text, "} #" => "] #")
text = replace(text, "} #" => "] #")
for var in ("f", "power", "weight", "shift", "radius", "half_radius")
text = replace(text, "real_wp_ $var =" => "$var =")
end
for var in ("A_val", "A_dense", "b", "c", "c_l", "c_u", "x_l", "x_u", "y_l", "y_u", "z_l", "z_u", "g", "x_0",
"w", "x", "y", "z", "val", "dense", "rhs", "rhst", "sol", "H_val", "H_dense")
"w", "x", "y", "z", "val", "dense", "rhs", "rhst", "sol", "H_val", "H_dense", "C_val",
"C_dense", "H_diag", "C_diag", "H_scid", "C_scid", "Ao_val", "r", "M_val", "M_dense",
"M_diag", "y", "W", "Ao_dense")
text = replace(text, "real_wp_ $var[] = {" => "$var = Float64[")
end
for var in ("n", "ne", "m", "A_ne", "A_dense_ne", "H_ne", "H_dense_ne")
for var in ("f", "power", "weight", "shift", "radius", "half_radius", "x_l", "x_u", "sigma", "rho_g", "rho_b")
text = replace(text, "real_wp_ $var =" => "$var =")
end
for var in ("n", "ne", "m", "A_ne", "A_dense_ne", "H_ne", "H_dense_ne", "C_dense_ne",
"C_ne", "dense_ne", "o", "Ao_ne", "Ao_ptr_ne", "A_ptr_ne", "m_equal",
"M_ne", "M_dense_ne", "j_ne", "h_ne", "p_ne", "Ao_dense_ne")
text = replace(text, "int $var =" => "$var =")
end
for var in ("A_row", "A_col", "A_ptr", "row", "col", "ptr", "c_stat", "x_stat", "H_row", "H_col", "H_ptr")
for var in ("A_row", "A_col", "A_ptr", "row", "col", "ptr", "c_stat", "x_stat", "H_row", "H_col", "H_ptr",
"C_row", "C_col", "C_ptr", "Ao_col", "Ao_ptr", "Ao_row", "M_row",
"M_col", "M_ptr", "J_row", "J_col", "J_ptr", "P_row", "P_ptr")
text = replace(text, "int $var[] = {" => "$var = Cint[")
end
for val in ("3", "5", "6", "n")
for val in ("1", "3", "5", "6", "7", "n", "n+m")
text = replace(text, "for( int d=1 d <= $val d++){" => "for d = 1:$val")
text = replace(text, "for(int d=1 d <= $val d++){" => "for d = 1:$val")
end
for index in ("unit_m", "new_radius")
for index in ("unit_m", "new_radius", "a_is", "m_is")
text = replace(text, "for( int $index=0 $index <= 1 $index++){" => "for $index = 0:1")
text = replace(text, "for(int $index=0 $index <= 1 $index++){" => "for $index = 0:1")
end
for val in ("c", "g", "u", "v", "x", "r", "vector", "h_vector")
for val in ("c", "g", "u", "v", "x", "w", "z", "x_l", "x_u", "r", "vector", "h_vector", "error")
text = replace(text, "real_wp_ $val[n]" => "$val = zeros(Float64, n)")
text = replace(text, "real_wp_ $val[m]" => "$val = zeros(Float64, m)")
text = replace(text, "real_wp_ $val[o]" => "$val = zeros(Float64, o)")
end
for val in ("x_stat", "c_stat", "index_nz_u", "index_nz_v", "depen")
text = replace(text, "int $val[n]" => "$val = zeros(Cint, n)")
Expand All @@ -57,7 +84,7 @@ function examples(package::String, example::String)
text = replace(text, ")\n}" => ")\n")
text = replace(text, "\n\n\n" => "\n")
text = replace(text, "}\n" => "]\n")
text = replace(text, "NULL" => "Cint[]")
text = replace(text, "NULL" => "C_NULL")
text = replace(text, "char st" => "st = ' '")
text = replace(text, "int status" => "status = Ref{Cint}()")
text = replace(text, "int n_depen" => "n_depen = Ref{Cint}()")
Expand All @@ -80,82 +107,97 @@ function examples(package::String, example::String)
text = replace(text, "while(true)" => "while true")
text = replace(text, "for( int i = 0 i < n i++)" => "for i = 1:n")
text = replace(text, "for( int i = 0 i < m i++)" => "for i = 1:m")
text = replace(text, "for( int i = 1 i < n i++)" => "for i = 2:n")
text = replace(text, "for( int i = 1 i < m i++)" => "for i = 2:m")
text = replace(text, "for( int i = 2 i < n i++)" => "for i = 3:n")
text = replace(text, "for( int i = 2 i < m i++)" => "for i = 3:m")
text = replace(text, "constrastatus = Ref{Cint}()" => "constraint status")
text = replace(text, "}#" => "] #")
text = replace(text, "#for" => "# for")
text = replace(text, "#@" => "# @")
text = replace(text, "# for i = 1:n @" => "# for i = 1:n\n# @")
text = replace(text, "( " => "(")
text = replace(text, " )" => ")")
text = replace(text, "switch(d)\n" => "")
text = replace(text, "for(i=0 i<n i++)" => "for i = 1:n\n")
text = replace(text, "}\n" => "end\n")
for var in ("x", "u", "v", "hval", "g")
text = replace(text, "const real_wp_ $var[]" => "var::Vector{Float64}")
text = replace(text, "real_wp_ $var[]" => "$var::Vector{Float64}")
end
text = text * "end\n\n@testset \"" * uppercase(package) * "\" begin\n @test test_$package() == 0\nend\n"
write(dst, text)
(example == "") && clean_example(package)

# Generate a symbolic link for the Julia tests
current_folder = pwd()
cd("../../src/$package")
!isdir("Julia") && mkdir("Julia")
cd("Julia")
rm("test_$package.jl", force=true)
symlink("../../../GALAHAD.jl/test/test_$package.jl", "test_$package.jl")
cd(current_folder)
end
current_folder = pwd()
cd("../../src/$package")
!isdir("Julia") && mkdir("Julia")
cd("Julia")
rm("test_$package.jl", force=true)
symlink("../../../GALAHAD.jl/test/test_$package.jl", "test_$package.jl")
cd(current_folder)
end

function main(name::String="all")
(name == "all" || name == "arc") && examples("arc" , "tf")
(name == "all" || name == "bgo") && examples("bgo" , "tf")
(name == "all" || name == "blls") && examples("blls" , "tf")
(name == "all" || name == "bllsb") && examples("bllsb" , "tf")
(name == "all" || name == "bqp") && examples("bqp" , "tf")
(name == "all" || name == "bqpb") && examples("bqpb" , "tf")
(name == "all" || name == "bsc") && examples("bsc" , "" )
(name == "all" || name == "ccqp") && examples("ccqp" , "tf")
(name == "all" || name == "clls") && examples("clls" , "tf")
(name == "all" || name == "convert") && examples("convert" , "" )
(name == "all" || name == "cqp") && examples("cqp" , "tf")
(name == "all" || name == "cro") && examples("cro" , "tf")
(name == "all" || name == "dgo") && examples("dgo" , "tf")
(name == "all" || name == "dps") && examples("dps" , "tf")
(name == "all" || name == "dqp") && examples("dqp" , "tf")
(name == "all" || name == "eqp") && examples("eqp" , "tf")
(name == "all" || name == "fdc") && examples("fdc" , "tf")
(name == "all" || name == "fit") && examples("fit" , "" )
(name == "all" || name == "glrt") && examples("glrt" , "t" )
(name == "all" || name == "gls") && examples("gls" , "" )
(name == "all" || name == "gltr") && examples("gltr" , "t" )
(name == "all" || name == "hash") && examples("hash" , "" )
(name == "all" || name == "ir") && examples("ir" , "" )
(name == "all" || name == "l2rt") && examples("l2rt" , "t" )
(name == "all" || name == "lhs") && examples("lhs" , "t" )
(name == "all" || name == "llsr") && examples("llsr" , "tf")
(name == "all" || name == "llst") && examples("llst" , "tf")
(name == "all" || name == "lms") && examples("lms" , "" )
(name == "all" || name == "lpa") && examples("lpa" , "tf")
(name == "all" || name == "lpb") && examples("lpb" , "tf")
(name == "all" || name == "lsqp") && examples("lsqp" , "tf")
(name == "all" || name == "lsrt") && examples("lsrt" , "t" )
(name == "all" || name == "lstr") && examples("lstr" , "t" )
(name == "all" || name == "nls") && examples("nls" , "tf")
(name == "all" || name == "presolve") && examples("presolve", "tf")
(name == "all" || name == "psls") && examples("psls" , "tf")
(name == "all" || name == "qpa") && examples("qpa" , "tf")
(name == "all" || name == "qpb") && examples("qpb" , "tf")
(name == "all" || name == "roots") && examples("roots" , "" )
(name == "all" || name == "rpd") && examples("rpd" , "tf")
(name == "all" || name == "rqs") && examples("rqs" , "tf")
(name == "all" || name == "sbls") && examples("sbls" , "tf")
(name == "all" || name == "scu") && examples("scu" , "" )
(name == "all" || name == "sec") && examples("sec" , "" )
(name == "all" || name == "sha") && examples("sha" , "" )
(name == "all" || name == "sils") && examples("sils" , "" )
(name == "all" || name == "slls") && examples("slls" , "tf")
(name == "all" || name == "sls") && examples("sls" , "tf")
(name == "all" || name == "trb") && examples("trb" , "tf")
(name == "all" || name == "trs") && examples("trs" , "tf")
(name == "all" || name == "tru") && examples("tru" , "tf")
(name == "all" || name == "ugo") && examples("ugo" , "t" )
(name == "all" || name == "uls") && examples("uls" , "tf")
(name == "all" || name == "wcp") && examples("wcp" , "tf")
function main(name::String)
(name == "arc") && examples("arc" , "tf")
(name == "bgo") && examples("bgo" , "tf")
(name == "blls") && examples("blls" , "tf")
(name == "bllsb") && examples("bllsb" , "tf")
(name == "bqp") && examples("bqp" , "tf")
(name == "bqpb") && examples("bqpb" , "tf")
(name == "bsc") && examples("bsc" , "" )
(name == "ccqp") && examples("ccqp" , "tf")
(name == "clls") && examples("clls" , "tf")
(name == "convert") && examples("convert" , "" )
(name == "cqp") && examples("cqp" , "tf")
(name == "cro") && examples("cro" , "tf")
(name == "dgo") && examples("dgo" , "tf")
(name == "dps") && examples("dps" , "tf")
(name == "dqp") && examples("dqp" , "tf")
(name == "eqp") && examples("eqp" , "tf")
(name == "fdc") && examples("fdc" , "tf")
(name == "fit") && examples("fit" , "" )
(name == "glrt") && examples("glrt" , "t" )
(name == "gls") && examples("gls" , "" )
(name == "gltr") && examples("gltr" , "t" )
(name == "hash") && examples("hash" , "" )
(name == "ir") && examples("ir" , "" )
(name == "l2rt") && examples("l2rt" , "t" )
(name == "lhs") && examples("lhs" , "t" )
(name == "llsr") && examples("llsr" , "tf")
(name == "llst") && examples("llst" , "tf")
(name == "lms") && examples("lms" , "" )
(name == "lpa") && examples("lpa" , "tf")
(name == "lpb") && examples("lpb" , "tf")
(name == "lsqp") && examples("lsqp" , "tf")
(name == "lsrt") && examples("lsrt" , "t" )
(name == "lstr") && examples("lstr" , "t" )
(name == "nls") && examples("nls" , "tf")
(name == "presolve") && examples("presolve", "tf")
(name == "psls") && examples("psls" , "tf")
(name == "qpa") && examples("qpa" , "tf")
(name == "qpb") && examples("qpb" , "tf")
(name == "roots") && examples("roots" , "" )
(name == "rpd") && examples("rpd" , "tf")
(name == "rqs") && examples("rqs" , "tf")
(name == "sbls") && examples("sbls" , "tf")
(name == "scu") && examples("scu" , "" )
(name == "sec") && examples("sec" , "" )
(name == "sha") && examples("sha" , "" )
(name == "sils") && examples("sils" , "" )
(name == "slls") && examples("slls" , "tf")
(name == "sls") && examples("sls" , "tf")
(name == "trb") && examples("trb" , "tf")
(name == "trs") && examples("trs" , "tf")
(name == "tru") && examples("tru" , "tf")
(name == "ugo") && examples("ugo" , "t" )
(name == "uls") && examples("uls" , "tf")
(name == "wcp") && examples("wcp" , "tf")
end

# If we want to use the file as a script with `julia wrapper.jl`
if abspath(PROGRAM_FILE) == @__FILE__
main()
function clean_example(package::String)
path = "../test/test_" * package * ".jl"
isfile(path) || error("The file test_$package.jl doesn't exist.")
format_file(path, YASStyle(), indent=2)
end
Loading

0 comments on commit 79cfa46

Please sign in to comment.