///|
let log2_10 : Double = 3.3219280948873626
///|
/// Convert decimal digits to binary precision using mpmath's formula.
pub fn dps_to_prec(n : Int) -> Int {
let bits = @math.floor((n + 1).to_double() * log2_10 + 0.5).to_int()
if bits > 1 {
bits
} else {
1
}
}
///|
/// Convert binary precision to reliable decimal digits using mpmath's formula.
pub fn prec_to_dps(n : Int) -> Int {
let digits = @math.floor(n.to_double() / log2_10 - 0.5).to_int()
if digits > 1 {
digits
} else {
1
}
}
///|
/// Digits needed to print an `mpf` uniquely for round-tripping.
pub fn repr_dps(n : Int) -> Int {
let dps = prec_to_dps(n)
if dps == 15 {
17
} else {
dps + 3
}
}
///|
/// Create a high-level numeric context from binary precision.
pub fn mp(prec? : Int = 53, rounding? : RoundMode = round_nearest) -> MPContext {
@mp.new(prec, rounding)
}
///|
/// Create a high-level numeric context from decimal digits.
pub fn mp_dps(dps : Int, rounding? : RoundMode = round_nearest) -> MPContext {
mp(prec=dps_to_prec(dps), rounding~)
}
///|
/// Build a temporary context with explicit working precision.
pub fn workprec(prec : Int, rounding? : RoundMode = round_nearest) -> MPContext {
mp(prec~, rounding~)
}
///|
/// Build a temporary context from decimal digits.
pub fn workdps(dps : Int, rounding? : RoundMode = round_nearest) -> MPContext {
mp_dps(dps, rounding~)
}
///|
/// Function-style replacement for mpmath's `local_workprec` context manager.
pub fn[T] local_workprec(
prec : Int,
f : (MPContext) -> T,
rounding? : RoundMode = round_nearest,
) -> T {
f(workprec(prec, rounding~))
}
///|
/// Function-style replacement for mpmath's `local_workdps` context manager.
pub fn[T] local_workdps(
dps : Int,
f : (MPContext) -> T,
rounding? : RoundMode = round_nearest,
) -> T {
f(workdps(dps, rounding~))
}