diff --git a/Project.toml b/Project.toml index abae127..9e45ee7 100644 --- a/Project.toml +++ b/Project.toml @@ -9,6 +9,7 @@ Format = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8" Preferences = "21216c6a-2e73-6563-6e65-726566657250" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +ThreadSafeDicts = "4239201d-c60e-5e0a-9702-85d713665ba7" [compat] DelimitedFiles = "1" @@ -16,4 +17,5 @@ Format = "1.3.7" Preferences = "1.5.0" Printf = "1" SparseArrays = "1" +ThreadSafeDicts = "0.1.6" julia = "1.10" diff --git a/src/DiagHamInterface.jl b/src/DiagHamInterface.jl index a7e83e1..6398097 100644 --- a/src/DiagHamInterface.jl +++ b/src/DiagHamInterface.jl @@ -4,6 +4,7 @@ Interface to the DiagHam library. module DiagHamInterface export execute_diagham_script +export diagham_command export install_diagham export read_matrix_from_txt @@ -11,13 +12,14 @@ export write_to_txt export write_matrix_elements using DelimitedFiles -using Format: cfmt +using Format using SparseArrays using Preferences +using ThreadSafeDicts include("utility/backup.jl") include("utility/diagham_path.jl") -include("utility/execute_script.jl") +include("utility/diagham_script.jl") include("utility/diagham_install.jl") include("utility/fileending.jl") include("utility/numbers.jl") diff --git a/src/utility/execute_script.jl b/src/utility/diagham_script.jl similarity index 69% rename from src/utility/execute_script.jl rename to src/utility/diagham_script.jl index ce166d2..609a55f 100644 --- a/src/utility/execute_script.jl +++ b/src/utility/diagham_script.jl @@ -1,28 +1,16 @@ """ - execute_diagham_script(execute; kwargs...) - -Run a DiagHam executable. Kwargs are converted to CLI flags (`_` → `-`). -Single-char keys use `-k`, multi-char use `--key`. Boolean `true` adds flag, `false` omits. - -The kwargs of `Cmd()` are supported. + diagham_command(execute; kwargs...) +Construct a command string for running a DiagHam executable with specified kwargs as CLI flags. """ -function execute_diagham_script(execute::AbstractString; kwargs...) - return execute_diagham_script([execute]; kwargs...) +function diagham_command(execute::AbstractString; kwargs...) + return diagham_command([execute]; kwargs...) end - -function execute_diagham_script( +function diagham_command( execute::AbstractVector{<:AbstractString}; diagham_path::AbstractString = get_diagham_path(), - ignorestatus::Bool = false, - detach::Bool = false, - windows_verbatim::Bool = false, - windows_hide::Bool = false, - env = nothing, - dir = "", kwargs... ) warn_about_diagham_path() - ex_file = first(execute) execute[1] = joinpath(diagham_path, ex_file) execute = prod(execute) @@ -31,10 +19,7 @@ function execute_diagham_script( for (k, v) in kwargs execute *= diagham_kwarg(k, v) end - - execute = Cmd(split(execute, " ")) - cmd = Cmd(execute; ignorestatus = ignorestatus, detach = detach, windows_verbatim = windows_verbatim, windows_hide = windows_hide, env = env, dir = dir) - return run(cmd) + return execute end function diagham_kwarg(key, value) @@ -49,3 +34,33 @@ function diagham_kwarg(key, value) end return "" end + +""" + execute_diagham_script(execute; kwargs...) + +Run a DiagHam executable. Kwargs are converted to CLI flags (`_` → `-`). +Single-char keys use `-k`, multi-char use `--key`. Boolean `true` adds flag, `false` omits. + +The kwargs of `Cmd()` and `run()` are supported. +""" +function execute_diagham_script(execute::AbstractString; kwargs...) + return execute_diagham_script([execute]; kwargs...) +end +function execute_diagham_script( + execute::AbstractVector{<:AbstractString}; + diagham_path::AbstractString = get_diagham_path(), + ignorestatus::Bool = false, + detach::Bool = false, + windows_verbatim::Bool = false, + windows_hide::Bool = false, + env = nothing, + dir = "", + wait::Bool = true, + cleanup::Bool = false, + kwargs... + ) + execute = diagham_command(execute; diagham_path, kwargs...) + execute = Cmd(split(execute, " ")) + cmd = Cmd(execute; ignorestatus = ignorestatus, detach = detach, windows_verbatim = windows_verbatim, windows_hide = windows_hide, env = env, dir = dir) + return run(cmd; wait = wait) +end diff --git a/src/utility/numbers.jl b/src/utility/numbers.jl index dbff702..1de0b90 100644 --- a/src/utility/numbers.jl +++ b/src/utility/numbers.jl @@ -1,3 +1,6 @@ +# Maps the format string (e.g. "%.5f") to the compiled formatter Function. +const LOCAL_FORMAT_CACHE = ThreadSafeDict{String, Function}() + """ format_with_precision(x; atol=eps(float(T)), mode=:auto, maxdigits=20) @@ -5,7 +8,7 @@ Format number `x` as a string with absolute precision `atol`. Mode `:auto` uses `%f` for `[1e-3, 1e6)`, else `%e`. Use `:f` or `:e` to force format. """ function format_with_precision(x::T; atol = eps(float(T)), mode::Symbol = :auto, maxdigits::Int = 20) where {T <: Real} - x == 0 && return "0.0" + iszero(x) && return "0.0" absx = abs(x) abs_atol = abs(atol) @@ -16,11 +19,21 @@ function format_with_precision(x::T; atol = eps(float(T)), mode::Symbol = :auto, log10_atol = log10(abs_atol) p = ceil(Int, exp10 - log10_atol) p = clamp(p, 0, maxdigits) - return cfmt("%.$(p)e", x) + + formatter = get_threadsafe_formatter("%.$(p)e") + return formatter(x) else p = ceil(Int, -log10(abs_atol)) p = clamp(p, 0, maxdigits) - return cfmt("%.$(p)f", x) + + formatter = get_threadsafe_formatter("%.$(p)f") + return formatter(x) + end +end + +function get_threadsafe_formatter(fmtstr::String) + return get!(LOCAL_FORMAT_CACHE, fmtstr) do + Format.generate_formatter(fmtstr) end end