From ec3f42baea8ed04fccd196390733c98d6a176b92 Mon Sep 17 00:00:00 2001 From: odow Date: Fri, 11 Oct 2024 10:57:33 +1300 Subject: [PATCH] Simplify test/bigfloat_dot.jl --- src/implementations/BigFloat.jl | 3 +- test/bigfloat_dot.jl | 80 +++++++-------------------------- 2 files changed, 16 insertions(+), 67 deletions(-) diff --git a/src/implementations/BigFloat.jl b/src/implementations/BigFloat.jl index 97b9782b..6856f47d 100644 --- a/src/implementations/BigFloat.jl +++ b/src/implementations/BigFloat.jl @@ -14,8 +14,7 @@ mutability(::Type{BigFloat}) = IsMutable() # which costs some extra allocations. We don't need the IdDict case because we # never call `mutable_copy` recursively. @static if VERSION >= v"1.12.0-DEV.1343" - # mutable_copy(x::BigFloat) = Base.MPFR._BigFloat(copy(getfield(x, :d))) - mutable_copy(x::BigFloat) = deepcopy(x) + mutable_copy(x::BigFloat) = Base.MPFR._BigFloat(copy(getfield(x, :d))) else function mutable_copy(x::BigFloat) d = x._d diff --git a/test/bigfloat_dot.jl b/test/bigfloat_dot.jl index 37de53a8..295e0e36 100644 --- a/test/bigfloat_dot.jl +++ b/test/bigfloat_dot.jl @@ -4,69 +4,18 @@ # v.2.0. If a copy of the MPL was not distributed with this file, You can obtain # one at http://mozilla.org/MPL/2.0/. -backup_bigfloats(v::AbstractVector{BigFloat}) = map(MA.copy_if_mutable, v) - -absolute_error(accurate::Real, approximate::Real) = abs(accurate - approximate) - -function relative_error(accurate::Real, approximate::Real) - return absolute_error(accurate, approximate) / abs(accurate) -end - -function dotter(x::V, y::V) where {V<:AbstractVector{<:Real}} - let x = x, y = y - () -> LinearAlgebra.dot(x, y) - end -end - -function reference_dot(x::V, y::V) where {F<:Real,V<:AbstractVector{F}} - return setprecision(dotter(x, y), F, 8 * precision(F)) -end - -function dot_test_relative_error(x::V, y::V) where {V<:AbstractVector{BigFloat}} - buf = MA.buffer_for(LinearAlgebra.dot, V, V) - - input = (x, y) - backup = map(backup_bigfloats, input) - - output = BigFloat() - - MA.buffered_operate_to!!(buf, output, LinearAlgebra.dot, input...) - - @test input == backup - - return relative_error(reference_dot(input...), output) -end - -subtracter(s::Real) = - let s = s - x -> x - s - end - -our_rand(n::Int, bias::Real) = map(subtracter(bias), rand(BigFloat, n)) - function rand_dot_rel_err(size::Int, bias::Real) - x = our_rand(size, bias) - y = our_rand(size, bias) - return dot_test_relative_error(x, y) -end - -function max_rand_dot_rel_err(size::Int, bias::Real, iter_cnt::Int) - max_rel_err = zero(BigFloat) - for i in 1:iter_cnt - rel_err = rand_dot_rel_err(size, bias) - <(max_rel_err, rel_err) && (max_rel_err = rel_err) - end - return max_rel_err -end - -function max_rand_dot_ulps(size::Int, bias::Real, iter_cnt::Int) - return max_rand_dot_rel_err(size, bias, iter_cnt) / eps(BigFloat) -end - -function ulper(size::Int, bias::Real, iter_cnt::Int) - let s = size, b = bias, c = iter_cnt - () -> max_rand_dot_ulps(s, b, c) + x = rand(BigFloat, size) .- bias + y = rand(BigFloat, size) .- bias + backup = (MA.copy_if_mutable(x), MA.copy_if_mutable(y)) + buf = MA.buffer_for(LinearAlgebra.dot, Vector{BigFloat}, Vector{BigFloat}) + output = BigFloat() + MA.buffered_operate_to!!(buf, output, LinearAlgebra.dot, x, y) + @test (x, y) == backup + accurate = setprecision(BigFloat, 8 * precision(BigFloat)) do + return LinearAlgebra.dot(x, y) end + return abs(accurate - output) / abs(accurate) end @testset "prec:$prec size:$size bias:$bias" for (prec, size, bias) in @@ -78,11 +27,9 @@ end # precision (except when vector lengths are really huge with # respect to the precision). (32, 64), - # Compensated summation should be accurate even for very large # input vectors, so test that. (10000,), - # The zero "bias" signifies that the input will be entirely # nonnegative (drawn from the interval [0, 1]), while a positive # bias shifts that interval towards negative infinity. We want to @@ -91,8 +38,11 @@ end # no guarantee on the relative error in that case. (0.0, 2^-2, 2^-2 + 2^-3 + 2^-4), ) - iter_cnt = 10 - err = setprecision(ulper(size, bias, iter_cnt), BigFloat, prec) + err = setprecision(BigFloat, prec) do + return mapreduce(max, 1:10) do _ + return rand_dot_rel_err(size, bias) / eps(BigFloat) + end + end @test 0 <= err < 1 end