From 72782d8e2bee46e204e6b52ce7bab454dfd2eea4 Mon Sep 17 00:00:00 2001 From: Simon May Date: Mon, 7 Oct 2024 17:58:48 +0200 Subject: [PATCH] Fix macro hygiene in `@constant`, `@derived_constant` (missing `esc()`) (#36) * Fix macro hygiene in constant definition macros * Avoid hard-coding values of derived constants * Fix argument names in `@derived_constant` docstring --- src/PhysicalConstants.jl | 49 +++++++++++++++++++++------------------- src/codata2014.jl | 3 ++- src/codata2018.jl | 13 +++++++---- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/PhysicalConstants.jl b/src/PhysicalConstants.jl index 8e755ef..f0054ed 100644 --- a/src/PhysicalConstants.jl +++ b/src/PhysicalConstants.jl @@ -29,12 +29,13 @@ _name(::PhysicalConstant{name,T,D,U}) where {name,T,D,U} = name # Functions composing the building blocks of the macros -function _constant_preamble(name, sym, unit, def) +function _constant_preamble(name, sym, unit, val, def) ename = esc(name) qname = esc(Expr(:quote, name)) esym = esc(sym) qsym = esc(Expr(:quote, sym)) eunit = esc(unit) + e_val = esc(val) _bigconvert = isa(def,Symbol) ? quote function _big(::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} c = BigFloat() @@ -45,25 +46,25 @@ function _constant_preamble(name, sym, unit, def) end : quote _big(::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} = $(esc(def)) end - return ename, qname, esym, qsym, eunit, _bigconvert + return ename, qname, esym, qsym, eunit, e_val, _bigconvert end -function _constant_begin(qname, ename, esym, eunit, val, _bigconvert) +function _constant_begin(qname, ename, esym, eunit, e_val, _bigconvert) quote const $ename = PhysicalConstant{gensym($qname),Float64,dimension($eunit),typeof($eunit)}() export $ename const $esym = $ename - Base.float(::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} = $val * $eunit + Base.float(::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} = $e_val * $eunit Base.float(FT::DataType, ::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} = - FT($val) * $eunit + FT($e_val) * $eunit $_bigconvert Base.big(x::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} = _big(x) * $eunit Base.float(::Type{BigFloat}, x::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} = big(x) end end -function _constant_end(qname, ename, qsym, descr, val, reference, eunit) +function _constant_end(qname, ename, qsym, edescr, e_val, ereference, eunit) quote Measurements.measurement(::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} = measurement(Float64, $ename) @@ -73,13 +74,13 @@ function _constant_end(qname, ename, qsym, descr, val, reference, eunit) function Base.show(io::IO, ::MIME"text/plain", x::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} unc = uncertainty(ustrip(measurement($ename))) - println(io, $descr, " (", $qsym, ")") + println(io, $edescr, " (", $qsym, ")") println(io, "Value = ", float($ename)) println(io, "Standard uncertainty = ", iszero(unc) ? "(exact)" : unc * $eunit) println(io, "Relative standard uncertainty = ", - iszero(unc) ? "(exact)" : round(unc / $val, sigdigits=2)) - print(io, "Reference = ", $reference) + iszero(unc) ? "(exact)" : round(unc / $e_val, sigdigits=2)) + print(io, "Reference = ", $ereference) end @assert isa(ustrip(float($ename)), Float64) @@ -141,29 +142,31 @@ Reference = My lab notebook ``` """ macro constant(name, sym, descr, val, def, unit, unc, bigunc, reference) - ename, qname, esym, qsym, eunit, _bigconvert = _constant_preamble(name, sym, unit, def) + ename, qname, esym, qsym, eunit, e_val, _bigconvert = _constant_preamble(name, sym, unit, val, def) + eunc = esc(unc) + ebigunc = esc(bigunc) tag = Threads.atomic_add!(Measurements.tag_counter, UInt64(1)) quote - $(_constant_begin(qname, ename, esym, eunit, val, _bigconvert)) + $(_constant_begin(qname, ename, esym, eunit, e_val, _bigconvert)) function Measurements.measurement(FT::DataType, ::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} - vl = FT($val) + vl = FT($e_val) newder = Measurements.empty_der2(vl) - if iszero($unc) - return Measurement{FT}(vl, FT($unc), UInt64(0), newder) * $eunit + if iszero($eunc) + return Measurement{FT}(vl, FT($eunc), UInt64(0), newder) * $eunit else - return Measurement{FT}(vl, FT($unc), $tag, + return Measurement{FT}(vl, FT($eunc), $tag, Measurements.Derivatives(newder, - (vl, $unc, $tag)=>one(FT))) * $eunit + (vl, $eunc, $tag)=>one(FT))) * $eunit end end function Measurements.measurement(::Type{BigFloat}, x::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} vl = _big(x) - unc = BigFloat($bigunc) + unc = BigFloat($ebigunc) newder = Measurements.empty_der2(vl) - if iszero($unc) + if iszero($eunc) return Measurement{BigFloat}(vl, unc, UInt64(0), newder) * $eunit else return Measurement{BigFloat}(vl, unc, $tag, @@ -172,12 +175,12 @@ macro constant(name, sym, descr, val, def, unit, unc, bigunc, reference) end end - $(_constant_end(qname, ename, qsym, esc(descr), val, reference, eunit)) + $(_constant_end(qname, ename, qsym, esc(descr), e_val, esc(reference), eunit)) end end """ - @derived_constant(name, sym, descr, val, def, unit, unc, bigunc, reference) -> PhysicalConstant + @derived_constant(name, sym, descr, val, def, unit, measure64, measurebig, reference) -> PhysicalConstant Macro to define a new [`PhysicalConstant`](@ref) derived from another existing `PhysicalConstant`. @@ -221,9 +224,9 @@ Reference = My lab notebook ``` """ macro derived_constant(name, sym, descr, val, def, unit, measure64, measurebig, reference) - ename, qname, esym, qsym, eunit, _bigconvert = _constant_preamble(name, sym, unit, def) + ename, qname, esym, qsym, eunit, e_val, _bigconvert = _constant_preamble(name, sym, unit, val, def) quote - $(_constant_begin(qname, ename, esym, eunit, val, _bigconvert)) + $(_constant_begin(qname, ename, esym, eunit, e_val, _bigconvert)) Measurements.measurement(::Type{Float64}, ::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} = @@ -235,7 +238,7 @@ macro derived_constant(name, sym, descr, val, def, unit, measure64, measurebig, x::PhysicalConstant{_name($ename),T,D,U}) where {T,D,U} = convert(Measurement{FT}, ustrip(measurement(x))) * $eunit - $(_constant_end(qname, ename, qsym, esc(descr), val, reference, eunit)) + $(_constant_end(qname, ename, qsym, esc(descr), e_val, esc(reference), eunit)) end end diff --git a/src/codata2014.jl b/src/codata2014.jl index ec42223..2fa09d1 100644 --- a/src/codata2014.jl +++ b/src/codata2014.jl @@ -37,7 +37,8 @@ import PhysicalConstants: @constant, @derived_constant J * s, 8.1e-42, 81/10_000_000_000_000_000_000_000_000_000_000_000_000_000_000, "CODATA 2014") @derived_constant(PlanckConstantOver2pi, ħ, "Planck constant over 2pi", - 1.0545718001391127e-34, ustrip(big(h))/(2 * big(pi)), J * s, + convert(Float64, ustrip(big(h))/(2 * big(pi))), + ustrip(big(h))/(2 * big(pi)), J * s, measurement(h)/2pi, measurement(BigFloat, h)/(2 * big(pi)), "CODATA 2014") @constant(BoltzmannConstant, k_B, "Boltzmann constant", 1.380_648_52e-23, BigFloat(138_064_852)/BigFloat(10_000_000_000_000_000_000_000_000_000_000), J * K^-1, diff --git a/src/codata2018.jl b/src/codata2018.jl index 0cbf6ee..6f409c6 100644 --- a/src/codata2018.jl +++ b/src/codata2018.jl @@ -45,7 +45,8 @@ _νx(T) = find_zero((_νf, _Dνf), T(_νx0), Roots.Newton()) 6_626_070_15/1_000_000_000_000_000_000_000_000_000_000_000_000_000_000, J * s, 0.0, BigFloat(0.0), "CODATA 2018") @derived_constant(ReducedPlanckConstant, ħ, "Reduced Planck constant", - 1.0545718176461565e-34, ustrip(big(h))/(2 * big(pi)), J * s, + convert(Float64, ustrip(big(h))/(2 * big(pi))), + ustrip(big(h))/(2 * big(pi)), J * s, measurement(h)/2pi, measurement(BigFloat, h)/(2 * big(pi)), "CODATA 2018") @constant(BoltzmannConstant, k_B, "Boltzmann constant", 1.380_649e-23, BigFloat(1_380_649)/BigFloat(100_000_000_000_000_000_000_000_000_000), J * K^-1, @@ -77,14 +78,16 @@ _νx(T) = find_zero((_νf, _Dνf), T(_νx0), Roots.Newton()) @constant(AvogadroConstant, N_A, "Avogadro constant", 6.022_140_76e23, BigFloat(602_214_076_000_000_000_000_000), mol^-1, 0.0, BigFloat(0.0), "CODATA 2018") -@derived_constant(MolarGasConstant, R, "Molar gas constant", 8.314_462_618_153_24, +@derived_constant(MolarGasConstant, R, "Molar gas constant", + convert(Float64, ustrip(big(N_A) * big(k_B))), ustrip(big(N_A) * big(k_B)), J * mol^-1 * K^-1, measurement(N_A) * measurement(k_B), measurement(BigFloat, N_A) * measurement(BigFloat, k_B), "CODATA 2018") @constant(RydbergConstant, R_∞, "Rydberg constant", 10_973_731.568_160, BigFloat(10_973_731_568_160)/BigFloat(1_000_000), m^-1, 2.1e-5, BigFloat(21)/BigFloat(1_000_000), "CODATA 2018") -@derived_constant(StefanBoltzmannConstant, σ, "Stefan-Boltzmann constant", 5.670_374_419_184_4294e-8, +@derived_constant(StefanBoltzmannConstant, σ, "Stefan-Boltzmann constant", + convert(Float64, ustrip(2 * big(pi)^5 * big(k_B)^4 / (15 * big(h)^3 * big(c_0)^2))), ustrip(2 * big(pi) ^ 5 * big(k_B) ^ 4 / (15 * big(h) ^ 3 * big(c_0) ^ 2)), W * m^-2 * K^-4, (2 * pi ^ 5 * measurement(k_B) ^ 4) / (15 * measurement(h) ^ 3 * measurement(c_0) ^ 2), (2 * big(pi) ^ 5 * measurement(BigFloat, k_B) ^ 4) / (15 * measurement(BigFloat, h) ^ 3 * measurement(BigFloat, c_0) ^ 2), @@ -95,13 +98,13 @@ _νx(T) = find_zero((_νf, _Dνf), T(_νx0), Roots.Newton()) BigFloat(60)/BigFloat(1000_000_000_000_000_000_000_000_000_000_000_000_000), "CODATA 2018") @derived_constant(WienWavelengthDisplacementLawConstant, b, "Wien wavelength displacement law constant", - 2.897_771_955_185_1727e-3, + convert(Float64, ustrip(big(h) * big(c_0) / (_λx(BigFloat) * big(k_B)))), ustrip(big(h) * big(c_0) / (_λx(BigFloat) * big(k_B))), m * K, measurement(h) * measurement(c_0) / (_λx0 * measurement(k_B)), measurement(BigFloat, h) * measurement(BigFloat, c_0) / (_λx(BigFloat) * measurement(BigFloat, k_B)), "CODATA 2018") @derived_constant(WienFrequencyDisplacementLawConstant, b′, "Wien frequency displacement law constant", - 5.878_925_757_646_825e10, + convert(Float64, ustrip(_νx(BigFloat) * big(k_B) / big(h))), ustrip(_νx(BigFloat) * big(k_B) / big(h)), Hz / K, _νx0 * measurement(k_B) / measurement(h), _νx(BigFloat) * measurement(BigFloat, k_B) / measurement(BigFloat, h), "CODATA 2018")