1717 cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh,
1818 cbrt, typemax, typemin, unsafe_trunc, realmin, realmax, rounding,
1919 setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero,
20- isone, big, RefValue
20+ isone, big, _string_n
2121
2222import . Base. Rounding: rounding_raw, setrounding_raw
2323
@@ -39,8 +39,8 @@ function __init__()
3939 nothing
4040end
4141
42- const ROUNDING_MODE = RefValue {Cint} (0 )
43- const DEFAULT_PRECISION = RefValue (256 )
42+ const ROUNDING_MODE = Ref {Cint} (0 ) # actually an Enum, defined by `to_mpfr`
43+ const DEFAULT_PRECISION = Ref {Int} (256 )
4444
4545# Basic type and initialization definitions
4646
@@ -54,21 +54,44 @@ mutable struct BigFloat <: AbstractFloat
5454 sign:: Cint
5555 exp:: Clong
5656 d:: Ptr{Limb}
57+ # _d::Buffer{Limb} # Julia gc handle for memory @ d
58+ _d:: String # Julia gc handle for memory @ d (optimized)
59+
60+ # Not recommended for general use:
61+ # used internally by, e.g. deepcopy
62+ global function _BigFloat (prec:: Clong , sign:: Cint , exp:: Clong , d:: String )
63+ # ccall-based version, inlined below
64+ # z = new(zero(Clong), zero(Cint), zero(Clong), C_NULL, d)
65+ # ccall((:mpfr_custom_init,:libmpfr), Cvoid, (Ptr{Limb}, Clong), d, prec) # currently seems to be a no-op in mpfr
66+ # NAN_KIND = Cint(0)
67+ # ccall((:mpfr_custom_init_set,:libmpfr), Cvoid, (Ref{BigFloat}, Cint, Clong, Ptr{Limb}), z, NAN_KIND, prec, d)
68+ # return z
69+ return new (prec, sign, exp, pointer (d), d)
70+ end
5771
5872 function BigFloat ()
59- prec = precision (BigFloat)
60- z = new (zero (Clong), zero (Cint), zero (Clong), C_NULL )
61- ccall ((:mpfr_init2 ,:libmpfr ), Cvoid, (Ref{BigFloat}, Clong), z, prec)
62- finalizer (cglobal ((:mpfr_clear , :libmpfr )), z)
63- return z
73+ prec:: Clong = precision (BigFloat)
74+ nb = ccall ((:mpfr_custom_get_size ,:libmpfr ), Csize_t, (Clong,), prec)
75+ nb = (nb + Core. sizeof (Limb) - 1 ) ÷ Core. sizeof (Limb) # align to number of Limb allocations required for this
76+ # d = Vector{Limb}(undef, nb)
77+ d = _string_n (nb * Core. sizeof (Limb))
78+ EXP_NAN = Clong (1 ) - Clong (typemax (Culong) >> 1 )
79+ return _BigFloat (prec, one (Cint), EXP_NAN, d) # +NAN
6480 end
81+ end
6582
66- # Not recommended for general use:
67- function BigFloat (prec:: Clong , sign:: Cint , exp:: Clong , d:: Ptr{Cvoid} )
68- new (prec, sign, exp, d)
83+ # overload the definition of unsafe_convert to ensure that `x.d` is assigned
84+ # it may have been dropped in the event that the BigFloat was serialized
85+ Base. unsafe_convert (:: Type{Ref{BigFloat}} , x:: Ptr{BigFloat} ) = x
86+ @inline function Base. unsafe_convert (:: Type{Ref{BigFloat}} , x:: Ref{BigFloat} )
87+ x = x[]
88+ if x. d == C_NULL
89+ x. d = pointer (x. _d)
6990 end
91+ return convert (Ptr{BigFloat}, Base. pointer_from_objref (x))
7092end
7193
94+
7295"""
7396 BigFloat(x)
7497
@@ -739,6 +762,7 @@ function setprecision(::Type{BigFloat}, precision::Int)
739762 throw (DomainError (precision, " `precision` cannot be less than 2." ))
740763 end
741764 DEFAULT_PRECISION[] = precision
765+ return precision
742766end
743767
744768setprecision (precision:: Int ) = setprecision (BigFloat, precision)
@@ -957,11 +981,11 @@ set_emin!(x) = ccall((:mpfr_set_emin, :libmpfr), Cvoid, (Clong,), x)
957981
958982function Base. deepcopy_internal (x:: BigFloat , stackdict:: IdDict )
959983 haskey (stackdict, x) && return stackdict[x]
960- prec = precision (x )
961- y = BigFloat ( zero (Clong), zero (Cint), zero (Clong), C_NULL )
962- ccall (( :mpfr_init2 , :libmpfr ), Cvoid, (Ref{BigFloat}, Clong), y, prec)
963- finalizer ( cglobal (( :mpfr_clear , :libmpfr )), y )
964- ccall ((:mpfr_set , :libmpfr ), Int32 , (Ref{BigFloat}, Ref{BigFloat}, Int32 ), y, x, ROUNDING_MODE[])
984+ # d = copy(x._d )
985+ d = x . _d
986+ d′ = GC . @preserve d unsafe_string ( pointer (d ), sizeof (d)) # creates a definitely-new String
987+ y = _BigFloat (x . prec, x . sign, x . exp, d′ )
988+ # ccall((:mpfr_custom_move, :libmpfr), Cvoid , (Ref{BigFloat}, Ptr{Limb} ), y, d) # unnecessary
965989 stackdict[x] = y
966990 return y
967991end
0 commit comments