| 1 | This patch backports part of Julia upstream commit:
|
| 2 |
|
| 3 | 1e5fdb29f8858f3244f6aff116ee12e4c8247f3a
|
| 4 | Author: Simon Byrne <[email protected]>
|
| 5 | AuthorDate: Tue Jan 10 14:52:36 2023 -0800
|
| 6 | Commit: GitHub <[email protected]>
|
| 7 | CommitDate: Tue Jan 10 17:52:36 2023 -0500
|
| 8 |
|
| 9 | update MPFR to 4.2.0 (#48165)
|
| 10 |
|
| 11 | Co-authored-by: Mosè Giordano <[email protected]>
|
| 12 |
|
| 13 | 6 files changed, 112 insertions(+), 79 deletions(-)
|
| 14 | base/mpfr.jl | 34 ++++++++++++++--
|
| 15 | deps/checksums/mpfr | 68 ++++++++++++++++----------------
|
| 16 | deps/mpfr.version | 2 +-
|
| 17 | stdlib/MPFR_jll/Project.toml | 2 +-
|
| 18 | stdlib/MPFR_jll/test/runtests.jl | 2 +-
|
| 19 | test/math.jl | 83 +++++++++++++++++++++-------------------
|
| 20 |
|
| 21 |
|
| 22 | diff -ur julia-1.8.3-orig/base/mpfr.jl julia-1.8.3-patch/base/mpfr.jl
|
| 23 | |
| 24 | |
| 25 | @@ -16,7 +16,8 @@
|
| 26 | cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh, lerpi,
|
| 27 | cbrt, typemax, typemin, unsafe_trunc, floatmin, floatmax, rounding,
|
| 28 | setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero,
|
| 29 | - isone, big, _string_n, decompose
|
| 30 | + isone, big, _string_n, decompose, minmax,
|
| 31 | + sinpi, cospi, sincospi, sind, cosd, tand, asind, acosd, atand
|
| 32 |
|
| 33 | import ..Rounding: rounding_raw, setrounding_raw
|
| 34 |
|
| 35 | @@ -745,7 +746,7 @@
|
| 36 | end
|
| 37 |
|
| 38 | # Functions for which NaN results are converted to DomainError, following Base
|
| 39 | -for f in (:sin, :cos, :tan, :sec, :csc, :acos, :asin, :atan, :acosh, :asinh, :atanh)
|
| 40 | +for f in (:sin, :cos, :tan, :sec, :csc, :acos, :asin, :atan, :acosh, :asinh, :atanh, :sinpi, :cospi)
|
| 41 | @eval begin
|
| 42 | function ($f)(x::BigFloat)
|
| 43 | isnan(x) && return x
|
| 44 | @@ -756,6 +757,7 @@
|
| 45 | end
|
| 46 | end
|
| 47 | end
|
| 48 | +sincospi(x::BigFloat) = (sinpi(x), cospi(x))
|
| 49 |
|
| 50 | function atan(y::BigFloat, x::BigFloat)
|
| 51 | z = BigFloat()
|
| 52 | @@ -763,6 +765,32 @@
|
| 53 | return z
|
| 54 | end
|
| 55 |
|
| 56 | +# degree functions
|
| 57 | +for f in (:sin, :cos, :tan)
|
| 58 | + @eval begin
|
| 59 | + function ($(Symbol(f,:d)))(x::BigFloat)
|
| 60 | + isnan(x) && return x
|
| 61 | + z = BigFloat()
|
| 62 | + ccall(($(string(:mpfr_,f,:u)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, 360, ROUNDING_MODE[])
|
| 63 | + isnan(z) && throw(DomainError(x, "NaN result for non-NaN input."))
|
| 64 | + return z
|
| 65 | + end
|
| 66 | + function ($(Symbol(:a,f,:d)))(x::BigFloat)
|
| 67 | + isnan(x) && return x
|
| 68 | + z = BigFloat()
|
| 69 | + ccall(($(string(:mpfr_a,f,:u)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, 360, ROUNDING_MODE[])
|
| 70 | + isnan(z) && throw(DomainError(x, "NaN result for non-NaN input."))
|
| 71 | + return z
|
| 72 | + end
|
| 73 | + end
|
| 74 | +end
|
| 75 | +function atand(y::BigFloat, x::BigFloat)
|
| 76 | + z = BigFloat()
|
| 77 | + ccall((:mpfr_atan2u, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, y, x, 360, ROUNDING_MODE[])
|
| 78 | + return z
|
| 79 | +end
|
| 80 | +
|
| 81 | +
|
| 82 | # Utility functions
|
| 83 | ==(x::BigFloat, y::BigFloat) = ccall((:mpfr_equal_p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0
|
| 84 | <=(x::BigFloat, y::BigFloat) = ccall((:mpfr_lessequal_p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0
|
| 85 | @@ -1018,7 +1046,7 @@
|
| 86 | isfinite(x) || return string(Float64(x))
|
| 87 | _prettify_bigfloat(string_mpfr(x, fmt))
|
| 88 | end
|
| 89 | -_string(x::BigFloat) = _string(x, "%.Re")
|
| 90 | +_string(x::BigFloat) = _string(x, "%Re")
|
| 91 | _string(x::BigFloat, k::Integer) = _string(x, "%.$(k)Re")
|
| 92 |
|
| 93 | string(b::BigFloat) = _string(b)
|
| 94 | diff -ur julia-1.8.3-orig/test/math.jl julia-1.8.3-patch/test/math.jl
|
| 95 | |
| 96 | |
| 97 | @@ -411,47 +411,51 @@
|
| 98 | @test rad2deg(pi + (pi/3)*im) ≈ 180 + 60im
|
| 99 | end
|
| 100 |
|
| 101 | +# ensure zeros are signed the same
|
| 102 | +⩲(x,y) = typeof(x) == typeof(y) && x == y && signbit(x) == signbit(y)
|
| 103 | +⩲(x::Tuple, y::Tuple) = length(x) == length(y) && all(map(⩲,x,y))
|
| 104 | +
|
| 105 | @testset "degree-based trig functions" begin
|
| 106 | - @testset "$T" for T = (Float32,Float64,Rational{Int})
|
| 107 | + @testset "$T" for T = (Float32,Float64,Rational{Int},BigFloat)
|
| 108 | fT = typeof(float(one(T)))
|
| 109 | fTsc = typeof( (float(one(T)), float(one(T))) )
|
| 110 | for x = -400:40:400
|
| 111 | - @test sind(convert(T,x))::fT ≈ convert(fT,sin(pi/180*x)) atol=eps(deg2rad(convert(fT,x)))
|
| 112 | - @test cosd(convert(T,x))::fT ≈ convert(fT,cos(pi/180*x)) atol=eps(deg2rad(convert(fT,x)))
|
| 113 | + @test sind(convert(T,x))::fT ≈ sin(pi*convert(fT,x)/180) atol=eps(deg2rad(convert(fT,x)))
|
| 114 | + @test cosd(convert(T,x))::fT ≈ cos(pi*convert(fT,x)/180) atol=eps(deg2rad(convert(fT,x)))
|
| 115 |
|
| 116 | s,c = sincosd(convert(T,x))
|
| 117 | - @test s::fT ≈ convert(fT,sin(pi/180*x)) atol=eps(deg2rad(convert(fT,x)))
|
| 118 | - @test c::fT ≈ convert(fT,cos(pi/180*x)) atol=eps(deg2rad(convert(fT,x)))
|
| 119 | + @test s::fT ≈ sin(pi*convert(fT,x)/180) atol=eps(deg2rad(convert(fT,x)))
|
| 120 | + @test c::fT ≈ cos(pi*convert(fT,x)/180) atol=eps(deg2rad(convert(fT,x)))
|
| 121 | end
|
| 122 | @testset "sind" begin
|
| 123 | - @test sind(convert(T,0.0))::fT === zero(fT)
|
| 124 | - @test sind(convert(T,180.0))::fT === zero(fT)
|
| 125 | - @test sind(convert(T,360.0))::fT === zero(fT)
|
| 126 | - T != Rational{Int} && @test sind(convert(T,-0.0))::fT === -zero(fT)
|
| 127 | - @test sind(convert(T,-180.0))::fT === -zero(fT)
|
| 128 | - @test sind(convert(T,-360.0))::fT === -zero(fT)
|
| 129 | + @test sind(convert(T,0.0))::fT ⩲ zero(fT)
|
| 130 | + @test sind(convert(T,180.0))::fT ⩲ zero(fT)
|
| 131 | + @test sind(convert(T,360.0))::fT ⩲ zero(fT)
|
| 132 | + T != Rational{Int} && @test sind(convert(T,-0.0))::fT ⩲ -zero(fT)
|
| 133 | + @test sind(convert(T,-180.0))::fT ⩲ -zero(fT)
|
| 134 | + @test sind(convert(T,-360.0))::fT ⩲ -zero(fT)
|
| 135 | if T <: AbstractFloat
|
| 136 | @test isnan(sind(T(NaN)))
|
| 137 | end
|
| 138 | end
|
| 139 | @testset "cosd" begin
|
| 140 | - @test cosd(convert(T,90))::fT === zero(fT)
|
| 141 | - @test cosd(convert(T,270))::fT === zero(fT)
|
| 142 | - @test cosd(convert(T,-90))::fT === zero(fT)
|
| 143 | - @test cosd(convert(T,-270))::fT === zero(fT)
|
| 144 | + @test cosd(convert(T,90))::fT ⩲ zero(fT)
|
| 145 | + @test cosd(convert(T,270))::fT ⩲ zero(fT)
|
| 146 | + @test cosd(convert(T,-90))::fT ⩲ zero(fT)
|
| 147 | + @test cosd(convert(T,-270))::fT ⩲ zero(fT)
|
| 148 | if T <: AbstractFloat
|
| 149 | @test isnan(cosd(T(NaN)))
|
| 150 | end
|
| 151 | end
|
| 152 | @testset "sincosd" begin
|
| 153 | - @test sincosd(convert(T,-360))::fTsc === ( -zero(fT), one(fT) )
|
| 154 | - @test sincosd(convert(T,-270))::fTsc === ( one(fT), zero(fT) )
|
| 155 | - @test sincosd(convert(T,-180))::fTsc === ( -zero(fT), -one(fT) )
|
| 156 | - @test sincosd(convert(T, -90))::fTsc === ( -one(fT), zero(fT) )
|
| 157 | - @test sincosd(convert(T, 0))::fTsc === ( zero(fT), one(fT) )
|
| 158 | - @test sincosd(convert(T, 90))::fTsc === ( one(fT), zero(fT) )
|
| 159 | - @test sincosd(convert(T, 180))::fTsc === ( zero(fT), -one(fT) )
|
| 160 | - @test sincosd(convert(T, 270))::fTsc === ( -one(fT), zero(fT) )
|
| 161 | + @test sincosd(convert(T,-360))::fTsc ⩲ ( -zero(fT), one(fT) )
|
| 162 | + @test sincosd(convert(T,-270))::fTsc ⩲ ( one(fT), zero(fT) )
|
| 163 | + @test sincosd(convert(T,-180))::fTsc ⩲ ( -zero(fT), -one(fT) )
|
| 164 | + @test sincosd(convert(T, -90))::fTsc ⩲ ( -one(fT), zero(fT) )
|
| 165 | + @test sincosd(convert(T, 0))::fTsc ⩲ ( zero(fT), one(fT) )
|
| 166 | + @test sincosd(convert(T, 90))::fTsc ⩲ ( one(fT), zero(fT) )
|
| 167 | + @test sincosd(convert(T, 180))::fTsc ⩲ ( zero(fT), -one(fT) )
|
| 168 | + @test sincosd(convert(T, 270))::fTsc ⩲ ( -one(fT), zero(fT) )
|
| 169 | if T <: AbstractFloat
|
| 170 | @test_throws DomainError sincosd(T(Inf))
|
| 171 | @test all(isnan.(sincosd(T(NaN))))
|
| 172 | @@ -463,22 +467,22 @@
|
| 173 | "sincospi" => (x->sincospi(x)[1], x->sincospi(x)[2])
|
| 174 | )
|
| 175 | @testset "pi * $x" for x = -3:0.3:3
|
| 176 | - @test sinpi(convert(T,x))::fT ≈ convert(fT,sin(pi*x)) atol=eps(pi*convert(fT,x))
|
| 177 | - @test cospi(convert(T,x))::fT ≈ convert(fT,cos(pi*x)) atol=eps(pi*convert(fT,x))
|
| 178 | + @test sinpi(convert(T,x))::fT ≈ sin(pi*convert(fT,x)) atol=eps(pi*convert(fT,x))
|
| 179 | + @test cospi(convert(T,x))::fT ≈ cos(pi*convert(fT,x)) atol=eps(pi*convert(fT,x))
|
| 180 | end
|
| 181 |
|
| 182 | - @test sinpi(convert(T,0.0))::fT === zero(fT)
|
| 183 | - @test sinpi(convert(T,1.0))::fT === zero(fT)
|
| 184 | - @test sinpi(convert(T,2.0))::fT === zero(fT)
|
| 185 | - T != Rational{Int} && @test sinpi(convert(T,-0.0))::fT === -zero(fT)
|
| 186 | - @test sinpi(convert(T,-1.0))::fT === -zero(fT)
|
| 187 | - @test sinpi(convert(T,-2.0))::fT === -zero(fT)
|
| 188 | + @test sinpi(convert(T,0.0))::fT ⩲ zero(fT)
|
| 189 | + @test sinpi(convert(T,1.0))::fT ⩲ zero(fT)
|
| 190 | + @test sinpi(convert(T,2.0))::fT ⩲ zero(fT)
|
| 191 | + T != Rational{Int} && @test sinpi(convert(T,-0.0))::fT ⩲ -zero(fT)
|
| 192 | + @test sinpi(convert(T,-1.0))::fT ⩲ -zero(fT)
|
| 193 | + @test sinpi(convert(T,-2.0))::fT ⩲ -zero(fT)
|
| 194 | @test_throws DomainError sinpi(convert(T,Inf))
|
| 195 |
|
| 196 | - @test cospi(convert(T,0.5))::fT === zero(fT)
|
| 197 | - @test cospi(convert(T,1.5))::fT === zero(fT)
|
| 198 | - @test cospi(convert(T,-0.5))::fT === zero(fT)
|
| 199 | - @test cospi(convert(T,-1.5))::fT === zero(fT)
|
| 200 | + @test cospi(convert(T,0.5))::fT ⩲ zero(fT)
|
| 201 | + @test cospi(convert(T,1.5))::fT ⩲ zero(fT)
|
| 202 | + @test cospi(convert(T,-0.5))::fT ⩲ zero(fT)
|
| 203 | + @test cospi(convert(T,-1.5))::fT ⩲ zero(fT)
|
| 204 | @test_throws DomainError cospi(convert(T,Inf))
|
| 205 | end
|
| 206 | @testset "Check exact values" begin
|
| 207 | @@ -489,8 +493,8 @@
|
| 208 | @test sincospi(one(T)/convert(T,6))[1] == 0.5
|
| 209 | @test_throws DomainError sind(convert(T,Inf))
|
| 210 | @test_throws DomainError cosd(convert(T,Inf))
|
| 211 | - T != Float32 && @test cospi(one(T)/convert(T,3)) == 0.5
|
| 212 | - T != Float32 && @test sincospi(one(T)/convert(T,3))[2] == 0.5
|
| 213 | + fT == Float64 && @test isapprox(cospi(one(T)/convert(T,3)), 0.5)
|
| 214 | + fT == Float64 && @test isapprox(sincospi(one(T)/convert(T,3))[2], 0.5)
|
| 215 | T == Rational{Int} && @test sinpi(5//6) == 0.5
|
| 216 | T == Rational{Int} && @test sincospi(5//6)[1] == 0.5
|
| 217 | end
|
| 218 | @@ -538,8 +542,8 @@
|
| 219 | end
|
| 220 | end
|
| 221 | end
|
| 222 | - @test @inferred(sinc(0//1)) === 1.0
|
| 223 | - @test @inferred(cosc(0//1)) === -0.0
|
| 224 | + @test @inferred(sinc(0//1)) ⩲ 1.0
|
| 225 | + @test @inferred(cosc(0//1)) ⩲ -0.0
|
| 226 |
|
| 227 | # test right before/after thresholds of Taylor series
|
| 228 | @test sinc(0.001) ≈ 0.999998355066745 rtol=1e-15
|