diff --git a/src/implementations/BigFloat.jl b/src/implementations/BigFloat.jl index ba8d414..b604e3b 100644 --- a/src/implementations/BigFloat.jl +++ b/src/implementations/BigFloat.jl @@ -26,165 +26,391 @@ else end const _MPFRRoundingMode = Base.MPFR.MPFRRoundingMode +const _MPFRMachineSigned = Base.GMP.ClongMax +const _MPFRMachineUnsigned = Base.GMP.CulongMax +const _MPFRMachineInteger = Union{_MPFRMachineSigned,_MPFRMachineUnsigned} +const _MPFRMachineFloat = Base.GMP.CdoubleMax + +make_mpfr_error() = error("Invalid use of @make_mpfr") +function make_mpfr_impl( + fn::Expr, + mod::Module, + rounding_mode::Bool, + rest::Expr..., +) + pre = :() + post = :() + for restᵢ in rest + restᵢ isa Expr && restᵢ.head === :(=) && length(restᵢ.args) == 2 || + make_mpfr_error() + if restᵢ.args[1] === :pre + pre = restᵢ.args[2] + elseif restᵢ.args[1] === :post + post = restᵢ.args[2] + else + make_mpfr_error() + end + end + fn.head === :(->) || make_mpfr_error() + if fn.args[2] isa Expr + # Julia likes to insert a line number node + (fn.args[2].head === :block && fn.args[2].args[1] isa LineNumberNode) || + make_mpfr_error() + fn_name = fn.args[2].args[end] + else + fn_name = fn.args[2] + end + if fn_name isa Expr + fn_name.head === :tuple + surplus_args = fn_name.args[2:end] + fn_name = fn_name.args[1] + else + surplus_args = [] + end + fn_name isa Symbol || make_mpfr_error() + fn = fn.args[1]::Expr + if fn.head === :(::) + return_type = mod.eval(fn.args[2]) + return_type <: Tuple{Vararg{BigFloat}} || make_mpfr_error() + fn = fn.args[1]::Expr + else + return_type = BigFloat + end + fn.head === :call || make_mpfr_error() + ju_name = fn.args[1] + try + mod.eval(ju_name) isa Base.Callable || make_mpfr_error() + catch + return :() # some functions may not be known in all Julia versions - this is not an error + end + args = sizehint!(Any[], length(fn.args) - 1) + argnames = sizehint!(Symbol[], length(fn.args) - 1) + types = sizehint!( + Any[], + length(fn.args) + + (return_type === BigFloat ? 0 : fieldcount(return_type) - 1), + ) + if return_type === BigFloat + push!(types, Ref{BigFloat}) + else + append!( + types, + Iterators.repeated(Ref{BigFloat}, fieldcount(return_type)), + ) + end + for (i, argᵢ) in enumerate(Iterators.drop(fn.args, 1)) + argᵢ isa Expr && argᵢ.head === :(::) || make_mpfr_error() + argtype = mod.eval(argᵢ.args[end]) + # singleton types may be used for method disambiguation - we only need them on the Julia side + if Base.issingletontype(argtype) + push!(args, Expr(:(::), argtype)) + continue + end + argname = + length(argᵢ.args) == 2 ? argᵢ.args[1]::Symbol : Symbol(:arg, i) + push!(args, Expr(:(::), argname, argtype)) + push!(argnames, argname) + if isbitstype(argtype) + push!(types, argtype) + elseif argtype isa Union + push!(types, promote_type(Base.uniontypes(argtype)...)) + else + push!(types, Ref{argtype}) + end + end + return quote + function promote_operation( + ::typeof($ju_name), + $((:(::Type{<:$(arg.args[end])}) for arg in args)...), + ) + return $return_type + end -# copy + function operate_to!(out::$return_type, ::typeof($ju_name), $(args...)) + $pre + ccall( + ($(QuoteNode(fn_name)), :libmpfr), + Int32, + ( + $(types...), + $((typeof(s) for s in surplus_args)...), + $((rounding_mode ? (:($_MPFRRoundingMode),) : ())...), + ), + $( + ( + return_type <: Tuple ? + (:(out[$i]) for i in 1:fieldcount(return_type)) : + (:out,) + )... + ), + $(argnames...), + $(surplus_args...), + $( + ( + rounding_mode ? + (:($(Base.Rounding.rounding_raw)($BigFloat)),) : () + )... + ), + ) + $post + return out + end + end +end -promote_operation(::typeof(copy), ::Type{BigFloat}) = BigFloat +macro make_mpfr(fn::Expr, rest::Expr...) + return esc(make_mpfr_impl(fn, __module__, true, rest...)) +end -function operate_to!(out::BigFloat, ::typeof(copy), in::BigFloat) - ccall( - (:mpfr_set, :libmpfr), - Int32, - (Ref{BigFloat}, Ref{BigFloat}, _MPFRRoundingMode), - out, - in, - Base.MPFR.ROUNDING_MODE[], - ) - return out +macro make_mpfr_noround(fn::Expr, rest::Expr...) + return esc(make_mpfr_impl(fn, __module__, false, rest...)) end +# copy + +@make_mpfr copy(::BigFloat) -> mpfr_set +@make_mpfr copy(::_MPFRMachineSigned) -> mpfr_set_si +@make_mpfr copy(::_MPFRMachineUnsigned) -> mpfr_set_ui +# the Julia MPFR library does not come with the set_sj/set_uj functions +@make_mpfr copy(::Float32) -> mpfr_set_flt +@make_mpfr copy(::Float64) -> mpfr_set_d +@make_mpfr copy(x::Float16) -> mpfr_set_flt pre=(x = Float32(x)) + operate!(::typeof(copy), x::BigFloat) = x # zero promote_operation(::typeof(zero), ::Type{BigFloat}) = BigFloat -function _set_si!(x::BigFloat, value) - ccall( - (:mpfr_set_si, :libmpfr), - Int32, - (Ref{BigFloat}, Clong, _MPFRRoundingMode), - x, - value, - Base.MPFR.ROUNDING_MODE[], - ) - return x -end -operate!(::typeof(zero), x::BigFloat) = _set_si!(x, 0) +operate!(::typeof(zero), x::BigFloat) = operate_to!(x, copy, 0) # one promote_operation(::typeof(one), ::Type{BigFloat}) = BigFloat -operate!(::typeof(one), x::BigFloat) = _set_si!(x, 1) +operate!(::typeof(one), x::BigFloat) = operate_to!(x, copy, 1) -# + +# ldexp -function promote_operation(::typeof(+), ::Type{BigFloat}, ::Type{BigFloat}) - return BigFloat -end +@make_mpfr ldexp(::_MPFRMachineSigned, ::_MPFRMachineSigned) -> mpfr_set_si_2exp +@make_mpfr ldexp(::_MPFRMachineUnsigned, ::_MPFRMachineSigned) -> + mpfr_set_ui_2exp +@make_mpfr ldexp(::BigFloat, ::_MPFRMachineSigned) -> mpfr_mul_2si +@make_mpfr ldexp(::BigFloat, ::_MPFRMachineUnsigned) -> mpfr_mul_2ui -function operate_to!(output::BigFloat, ::typeof(+), a::BigFloat, b::BigFloat) - ccall( - (:mpfr_add, :libmpfr), - Int32, - (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, _MPFRRoundingMode), - output, - a, - b, - Base.MPFR.ROUNDING_MODE[], - ) - return output -end +# + -operate_to!(out::BigFloat, ::typeof(+), a::BigFloat) = operate_to!(out, copy, a) +@make_mpfr +(::BigFloat, ::BigFloat) -> mpfr_add +@make_mpfr +(::BigFloat, ::_MPFRMachineSigned) -> mpfr_add_si +@make_mpfr +(::BigFloat, ::_MPFRMachineUnsigned) -> mpfr_add_ui +@make_mpfr +(::BigFloat, ::_MPFRMachineFloat) -> mpfr_add_d + +operate_to!(out::BigFloat, ::typeof(+), a::Real) = operate_to!(out, copy, a) operate!(::typeof(+), a::BigFloat) = a # - -promote_operation(::typeof(-), ::Vararg{Type{BigFloat},N}) where {N} = BigFloat +@make_mpfr -(::BigFloat, ::BigFloat) -> mpfr_sub +@make_mpfr -(::BigFloat, ::_MPFRMachineSigned) -> mpfr_sub_si +@make_mpfr -(::BigFloat, ::_MPFRMachineUnsigned) -> mpfr_sub_ui +@make_mpfr -(::BigFloat, ::_MPFRMachineFloat) -> mpfr_sub_d +@make_mpfr -(::_MPFRMachineSigned, ::BigFloat) -> mpfr_si_sub +@make_mpfr -(::_MPFRMachineUnsigned, ::BigFloat) -> mpfr_ui_sub +@make_mpfr -(::_MPFRMachineFloat, ::BigFloat) -> mpfr_d_sub -function operate_to!(output::BigFloat, ::typeof(-), a::BigFloat, b::BigFloat) - ccall( - (:mpfr_sub, :libmpfr), - Int32, - (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, _MPFRRoundingMode), - output, - a, - b, - Base.MPFR.ROUNDING_MODE[], - ) - return output -end +promote_operation(::typeof(-), ::Type{BigFloat}) = BigFloat function operate!(::typeof(-), x::BigFloat) x.sign = -x.sign return x end -function operate_to!(o::BigFloat, ::typeof(-), x::BigFloat) +function operate_to!(o::BigFloat, ::typeof(-), x::Real) operate_to!(o, copy, x) return operate!(-, o) end -# Base.abs +# abs -function operate!(::typeof(Base.abs), x::BigFloat) +function operate!(::typeof(abs), x::BigFloat) x.sign = abs(x.sign) return x end -function operate_to!(o::BigFloat, ::typeof(abs), x::BigFloat) +function operate_to!(o::BigFloat, ::typeof(abs), x::Real) operate_to!(o, copy, x) return operate!(abs, o) end # * -promote_operation(::typeof(*), ::Type{BigFloat}, ::Type{BigFloat}) = BigFloat +@make_mpfr *(::BigFloat, ::BigFloat) -> mpfr_mul +@make_mpfr *(::BigFloat, ::_MPFRMachineSigned) -> mpfr_mul_si +@make_mpfr *(::BigFloat, ::_MPFRMachineUnsigned) -> mpfr_mul_ui +@make_mpfr *(::BigFloat, ::_MPFRMachineFloat) -> mpfr_mul_d -function operate_to!(output::BigFloat, ::typeof(*), a::BigFloat, b::BigFloat) - ccall( - (:mpfr_mul, :libmpfr), - Int32, - (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, _MPFRRoundingMode), - output, - a, - b, - Base.MPFR.ROUNDING_MODE[], - ) - return output +operate_to!(out::BigFloat, ::typeof(*), a::Real) = operate_to!(out, copy, a) + +operate!(::typeof(*), a::BigFloat) = a + +# / + +@make_mpfr /(::BigFloat, ::BigFloat) -> mpfr_div +@make_mpfr /(::BigFloat, ::_MPFRMachineSigned) -> mpfr_div_si +@make_mpfr /(::BigFloat, ::_MPFRMachineUnsigned) -> mpfr_div_ui +@make_mpfr /(::BigFloat, ::_MPFRMachineFloat) -> mpfr_div_d +@make_mpfr /(::_MPFRMachineSigned, ::BigFloat) -> mpfr_si_div +@make_mpfr /(::_MPFRMachineUnsigned, ::BigFloat) -> mpfr_ui_div +@make_mpfr /(::_MPFRMachineFloat, ::BigFloat) -> mpfr_d_div + +# roots +@make_mpfr sqrt(x::BigFloat) -> mpfr_sqrt pre=begin + isnan(x) && return operate_to!(out, copy, x) +end post=begin + isnan(out) && throw(DomainError(x, "NaN result for non-NaN input")) end +@make_mpfr sqrt(::_MPFRMachineUnsigned) -> mpfr_sqrt_ui +@make_mpfr cbrt(::BigFloat) -> mpfr_cbrt +@make_mpfr fourthroot(::BigFloat) -> (mpfr_rootn_ui, 0x00000004) -operate_to!(out::BigFloat, ::typeof(*), a::BigFloat) = operate_to!(out, copy, a) +# factorial -operate!(::typeof(*), a::BigFloat) = a +@make_mpfr factorial(::_MPFRMachineUnsigned) -> mpfr_fac_ui # Base.fma -function promote_operation( - ::typeof(Base.fma), - ::Type{F}, - ::Type{F}, - ::Type{F}, -) where {F<:BigFloat} - return F +@make_mpfr fma(::BigFloat, ::BigFloat, ::BigFloat) -> mpfr_fma + +function operate!(::typeof(fma), x::F, y::F, z::F) where {F<:BigFloat} + return operate_to!(x, fma, x, y, z) end -function operate_to!( - output::F, - ::typeof(Base.fma), - x::F, - y::F, - z::F, -) where {F<:BigFloat} - ccall( - (:mpfr_fma, :libmpfr), - Int32, - (Ref{F}, Ref{F}, Ref{F}, Ref{F}, _MPFRRoundingMode), - output, - x, - y, - z, - Base.MPFR.ROUNDING_MODE[], - ) - return output +# hypot + +@make_mpfr hypot(::BigFloat, ::BigFloat) -> mpfr_hypot + +# log + +@make_mpfr log(::_MPFRMachineUnsigned) -> mpfr_log_ui +for f in (:log, :log2, :log10) + @eval @make_mpfr $f(x::BigFloat) -> $(Symbol(:mpfr_, f)) pre=begin + if x < 0 + throw( + DomainError( + x, + string( + $f, + " was called with a negative real argument but ", + "will only return a complex result if called ", + "with a complex argument. Try ", + $f, + "(complex(x)).", + ), + ), + ) + end + end end +@make_mpfr log1p(x::BigFloat) -> mpfr_log1p pre=begin + if x < -1 + throw( + DomainError( + x, + string( + "log1p was called with a real argument < -1 but ", + "will only return a complex result if called ", + "with a complex argument. Try log1p(complex(x)).", + ), + ), + ) + end +end + +# exp + +@make_mpfr exp(::BigFloat) -> mpfr_exp +@make_mpfr exp2(::BigFloat) -> mpfr_exp2 +@make_mpfr exp10(::BigFloat) -> mpfr_exp10 +@make_mpfr expm1(::BigFloat) -> mpfr_expm1 + +# ^ +@make_mpfr ^(::BigFloat, ::BigFloat) -> mpfr_pow +@make_mpfr ^(::BigFloat, ::_MPFRMachineSigned) -> mpfr_pow_si +@make_mpfr ^(::BigFloat, ::_MPFRMachineUnsigned) -> mpfr_pow_ui + +# trigonometric +# Functions for which NaN results are converted to DomainError, following Base +for f in ( + :sin, + :cos, + :tan, + :cot, + :sec, + :csc, + :acos, + :asin, + :atan, + :acosh, + :asinh, + :atanh, + (VERSION ≥ v"1.10" ? (:sinpi, :cospi, :tanpi) : ())..., +) + @eval @make_mpfr $f(x::BigFloat) -> $(Symbol(:mpfr_, f)) pre=begin + isnan(x) && return operate_to!(out, copy, x) + end post=begin + isnan(out) && throw(DomainError(x, "NaN result for non-NaN input.")) + end +end +@make_mpfr sincos(::BigFloat)::Tuple{BigFloat,BigFloat} -> mpfr_sin_cos +VERSION ≥ v"1.10" && for f in (:sin, :cos, :tan) + @eval begin + @make_mpfr $(Symbol(f, :d))(x::BigFloat) -> + ($(Symbol(:mpfr_, f, :u)), 0x00000168) pre=begin + isnan(x) && return operate_to!(out, copy, x) + end post=begin + isnan(out) && throw(DomainError(x, "NaN result for non-NaN input.")) + end -function operate!(::typeof(Base.fma), x::F, y::F, z::F) where {F<:BigFloat} - return operate_to!(x, Base.fma, x, y, z) + @make_mpfr $(Symbol(:a, f, :d))(x::BigFloat) -> + ($(Symbol(:mpfr_a, f, :u)), 0x00000168) pre=begin + isnan(x) && return operate_to!(out, copy, x) + end post=begin + isnan(out) && throw(DomainError(x, "NaN result for non-NaN input.")) + end + end end +@make_mpfr atan(::BigFloat, ::BigFloat) -> mpfr_atan2 +VERSION ≥ v"1.10" && + @make_mpfr atand(::BigFloat, ::BigFloat) -> (mpfr_atan2u, 0x00000168) + +# hyperbolic +@make_mpfr cosh(::BigFloat) -> mpfr_cosh +@make_mpfr sinh(::BigFloat) -> mpfr_sinh +@make_mpfr tanh(::BigFloat) -> mpfr_tanh +@make_mpfr sech(::BigFloat) -> mpfr_sech +@make_mpfr csch(::BigFloat) -> mpfr_csch +@make_mpfr coth(::BigFloat) -> mpfr_coth + +# integer/remainder +@make_mpfr_noround round(::BigFloat, ::RoundingMode{:Nearest}) -> mpfr_roundeven +@make_mpfr_noround round(::BigFloat, ::RoundingMode{:Up}) -> mpfr_ceil +@make_mpfr_noround round(::BigFloat, ::RoundingMode{:Down}) -> mpfr_floor +@make_mpfr_noround round(::BigFloat, ::RoundingMode{:ToZero}) -> mpfr_trunc +@make_mpfr_noround round(::BigFloat, ::RoundingMode{:NearestTiesAway}) -> + mpfr_round + +@make_mpfr modf(::BigFloat)::Tuple{BigFloat,BigFloat} -> mpfr_modf pre=( + out = reverse(out) +) post=(out = reverse(out)) +@make_mpfr rem(::BigFloat, ::BigFloat) -> mpfr_fmod +@make_mpfr rem(::BigFloat, ::BigFloat, ::RoundingMode{:Nearest}) -> + mpfr_remainder + +# miscellaneous +@make_mpfr min(::BigFloat, ::BigFloat) -> mpfr_min +@make_mpfr max(::BigFloat, ::BigFloat) -> mpfr_max +@make_mpfr copysign(::BigFloat, ::BigFloat) -> mpfr_copysign # Base.muladd @@ -215,8 +441,8 @@ function operate_to!( output::BigFloat, op::Union{typeof(+),typeof(-),typeof(*)}, a::BigFloat, - b::BigFloat, - c::Vararg{BigFloat,N}, + b::Real, + c::Vararg{Real,N}, ) where {N} operate_to!(output, op, a, b) return operate!(op, output, c...) diff --git a/test/bigfloat_wrappers.jl b/test/bigfloat_wrappers.jl new file mode 100644 index 0000000..725b6d0 --- /dev/null +++ b/test/bigfloat_wrappers.jl @@ -0,0 +1,184 @@ +@testset "MPFR wrappers" begin + # call MA.operate_to!(out, op, args...) and compare with expected. If Base throws for + # the inputs, assert MA throws the same kind of error. + function check_op_matches_expected( + op, + args...; + out = BigFloat(), + expected = missing, + ) + # preserve originals for mutation checks + old_args = MA.copy_if_mutable.(args) + + # Test operate_to! into an output + local result + success = try + result = MA.operate_to!(out, op, args...) + true + catch e + @test_throws typeof(e) op(args...) + false + end + if success + @test result === out # check return value + if ismissing(expected) + success = try + expected = op(args...) + true + catch e + @test false + false + end + end + if success + if out isa Real + @test out ≈ expected atol=1e-13 + else + @test length(out) == length(expected) + for (outᵢ, expectedᵢ) in zip(out, expected) + @test outᵢ ≈ expectedᵢ atol=1e-13 + end + end + end + end + + # Ensure operate_to! didn't mutate the input arguments + @test old_args == args + end + + setprecision(BigFloat, 64) do + check_op_matches_expected(copy, big"12.") + check_op_matches_expected(copy, -12) + check_op_matches_expected(copy, UInt(12)) + check_op_matches_expected(copy, 12.0f0) + check_op_matches_expected(copy, 12.0) + + check_op_matches_expected(ldexp, -5, 3; expected = ldexp(-5.0, 3)) + check_op_matches_expected(ldexp, UInt(5), 3; expected = ldexp(5.0, 3)) + check_op_matches_expected(ldexp, big"5.", -3) + check_op_matches_expected(ldexp, big"5.", UInt(3)) + + check_op_matches_expected(+, big"1.5", big"2.5") + check_op_matches_expected(+, big"1.5", 10) + check_op_matches_expected(+, big"1.5", 0x23) + check_op_matches_expected(+, big"1.5", 2.5) + check_op_matches_expected(+, big"1.5", 2.5f0) + + check_op_matches_expected(-, big"1.5", big"2.5") + check_op_matches_expected(-, big"1.5", Int32(-42)) + check_op_matches_expected(-, big"1.5", 0x6525) + check_op_matches_expected(-, big"1.5", 17.0) + check_op_matches_expected(-, Int16(-62), big"1.5") + check_op_matches_expected(-, 0x73764fa, big"1.5") + check_op_matches_expected(-, 24.0, big"1.5") + + check_op_matches_expected(*, big"63.6", big"91.") + check_op_matches_expected(*, big"63.6", Int32(-52)) + check_op_matches_expected(*, big"63.6", 0x53d2a) + check_op_matches_expected(*, big"63.6", 8.0f3) + + for dividend in (58, 0) + check_op_matches_expected(/, big"5352.5", BigFloat(dividend)) + check_op_matches_expected(/, big"5352.5", Int(dividend)) + check_op_matches_expected(/, big"5352.5", UInt(dividend)) + check_op_matches_expected(/, big"5352.5", Float64(dividend)) + check_op_matches_expected(/, 5352, BigFloat(dividend)) + check_op_matches_expected(/, 0x452, BigFloat(dividend)) + check_op_matches_expected(/, 5352.5, BigFloat(dividend)) + end + + check_op_matches_expected(sqrt, big"646.4") + check_op_matches_expected(sqrt, 0x12) + check_op_matches_expected(cbrt, big"652.6") + VERSION ≥ v"1.10" && check_op_matches_expected(fourthroot, big"746.3") + + check_op_matches_expected(factorial, 0xc) + + check_op_matches_expected(fma, big"1.2", big"2.3", big"0.7") + + check_op_matches_expected(hypot, big"3.", big"4.") + + check_op_matches_expected(log, big"2.5") + check_op_matches_expected(log, big"-53.") + check_op_matches_expected(log, 0x623) + check_op_matches_expected(log, 0x0) + check_op_matches_expected(log2, big"8.0") + check_op_matches_expected(log2, big"0.") + check_op_matches_expected(log10, big"100.0") + check_op_matches_expected(log10, big"-17.") + check_op_matches_expected(log1p, big"0.001") + check_op_matches_expected(log1p, big"-13.") + + check_op_matches_expected(exp, big"1.2") + check_op_matches_expected(exp2, big"3.0") + check_op_matches_expected(exp10, big"2.0") + check_op_matches_expected(expm1, big"0.001") + + check_op_matches_expected(^, big"17.", big"13.") + check_op_matches_expected(^, big"17.", 13) + check_op_matches_expected(^, big"17.", 0x13) + + check_op_matches_expected(cos, big"0.5") + check_op_matches_expected(sin, big"0.5") + check_op_matches_expected(tan, big"0.5") + if VERSION ≥ v"1.10" + check_op_matches_expected(cospi, big"0.5") + check_op_matches_expected(sinpi, big"0.5") + check_op_matches_expected(tanpi, big"0.125") + check_op_matches_expected(tanpi, big"0.5") + check_op_matches_expected(cosd, big"60.0") + check_op_matches_expected(sind, big"30.0") + check_op_matches_expected(tand, big"30.0") + check_op_matches_expected(tand, big"90.") + end + check_op_matches_expected( + sincos, + big"0.5"; + out = (BigFloat(), BigFloat()), + ) + check_op_matches_expected(sec, big"0.7") + check_op_matches_expected(csc, big"0.7") + check_op_matches_expected(cot, big"0.7") + check_op_matches_expected(acos, big"0.5") + check_op_matches_expected(asin, big"0.5") + check_op_matches_expected(atan, big"0.5") + check_op_matches_expected(atan, big"0.5", big"0.9") + if VERSION ≥ v"1.10" + check_op_matches_expected(acosd, big"0.5") + check_op_matches_expected(asind, big"0.5") + check_op_matches_expected(atand, big"0.5") + check_op_matches_expected(atand, big"0.5", big"0.9") + end + + check_op_matches_expected(cosh, big"0.5") + check_op_matches_expected(sinh, big"0.5") + check_op_matches_expected(tanh, big"0.5") + check_op_matches_expected(sech, big"0.5") + check_op_matches_expected(csch, big"0.5") + check_op_matches_expected(coth, big"0.5") + check_op_matches_expected(acosh, big"2.0") + check_op_matches_expected(asinh, big"0.5") + check_op_matches_expected(atanh, big"0.3") + + for rm in ( + RoundNearest, + RoundUp, + RoundDown, + RoundToZero, + RoundNearestTiesAway, + ) + check_op_matches_expected(round, big"24.", rm) + end + + check_op_matches_expected( + modf, + big"3.1415"; + out = (BigFloat(), BigFloat()), + ) + check_op_matches_expected(rem, big"7.5", big"2.3") + check_op_matches_expected(rem, big"7.5", big"2.3", RoundNearest) + check_op_matches_expected(min, big"1.2", big"2.3") + check_op_matches_expected(max, big"1.2", big"2.3") + return check_op_matches_expected(copysign, big"-1.2", big"2.0") + end +end diff --git a/test/runtests.jl b/test/runtests.jl index 9a9bb53..4f485bb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -30,6 +30,9 @@ end @testset "BigFloat dot" begin include("bigfloat_dot.jl") end +@testset "BigFloat all wrappers" begin + include("bigfloat_wrappers.jl") +end @testset "evalpoly" begin include("evalpoly.jl") end