\name{mpfr-utils}
\title{Rmpfr -- Utilities for Precision Setting, etc}
\alias{getPrec}
\alias{.getPrec}
\alias{getD}
\alias{mpfr_default_prec}
\alias{mpfr2array}
\alias{mpfrImport}
\alias{mpfrXport}
%\alias{.mpfr1tolist}% not exported
% \alias{print.mpfr}    ==> ./formatMpfr.Rd
\alias{toNum}
\alias{.mpfr2d}
\alias{.mpfr2i}
\alias{.mpfr2list}
%-
\alias{.mpfr_formatinfo}
\alias{.mpfr2exp}
%-
\alias{.mpfr_erange}
\alias{.mpfr_erange_set}
\alias{.mpfr_erange_kinds}
\alias{.mpfr_erange_is_int}
\alias{.mpfr_maxPrec}
\alias{.mpfr_minPrec}
\alias{.mpfr_gmp_numbbits}
\alias{.mpfrSizeof}
\alias{.mpfrVersion}
%- really internal
\alias{..bigq2mpfr}
\alias{..bigz2mpfr}
\alias{.getSign}
\alias{.mpfr_negative}
\alias{.mpfr_sign}
\alias{.mpfr}
\alias{.mpfr.}
\description{
  This page documents utilities from package \pkg{Rmpfr} which are
  typically not called by the user, but may come handy in some
  situations.

  Notably, the (base-2) maximal (and minimal) precision and the
  \dQuote{erange}, the range of possible (base-2) exponents of
  \code{\link{mpfr}}-numbers can be queried and partly extended.
}
\usage{
getPrec(x, base = 10, doNumeric = TRUE, is.mpfr = NA, bigq. = 128L)
.getPrec(x)
getD(x)
mpfr_default_prec(prec)
toNum(from, rnd.mode = c('N','D','U','Z','A'))
.mpfr2d(from)
.mpfr2i(from)

mpfr2array(x, dim, dimnames = NULL, check = FALSE)

.mpfr2list(x, names = FALSE)

mpfrXport(x, names = FALSE)
mpfrImport(mxp)

.mpfr_formatinfo(x)
.mpfr2exp(x)

.mpfr_erange(kind = c("Emin", "Emax"), names = TRUE)
.mpfr_erange_set(kind = c("Emin", "Emax"), value)
.mpfr_erange_kinds
.mpfr_erange_is_int()
.mpfr_maxPrec()
.mpfr_minPrec()

.mpfr_gmp_numbbits()
.mpfrSizeof()
.mpfrVersion()

## Really Internal and low level, no error checking (for when you know ..)
.mpfr (x, precBits)
.mpfr.(x, precBits, rnd.mode)
.getSign(x)

.mpfr_negative(x)
.mpfr_sign(x)

..bigq2mpfr(x, precB = NULL, rnd.mode = c("N", "D", "U", "Z", "A"))
..bigz2mpfr(x, precB = NULL, rnd.mode = c("N", "D", "U", "Z", "A"))
}
\arguments{
  \item{x, from}{typically, an \R object of class \code{"\linkS4class{mpfr}"}, or
    \code{"\linkS4class{mpfrArray}"}, respectively.  For
    \code{getPrec()}, any number-like \R object, or \code{\link{NULL}}.}
  \item{base}{(only when \code{x} is \code{\link{character}}) the base
    with respect to which \code{x[i]} represent numbers; \code{base}
    \eqn{b} must fulfill \eqn{2 \le b \le 62}{2 <= b <= 62}.}
  \item{doNumeric}{logical indicating \code{\link{integer}} or
    \code{\link{double}} typed \code{x} should be accepted and a default
    precision be returned.  Should typically be kept at default \code{TRUE}.}
  \item{is.mpfr}{logical indicating if \code{\link{class}(x)} is already
    known to be \code{"mpfr"}; typically should be kept at default, \code{NA}.}
  \item{bigq.}{for \code{getPrec()}, the precision to use for a big
    rational (class \code{"bigq"}); if not specified gives warning when used.}
  \item{prec, precB, precBits}{a positive integer, not larger than
    \code{\link{.Machine}$ integer.max}, or missing.}
  \item{rnd.mode}{a 1-letter string specifying how \emph{rounding}
    should happen at C-level conversion to MPFR, see details of
    \code{\link{mpfr}}.}
  \item{dim, dimnames}{for \code{"\linkS4class{mpfrArray}"}
    construction.}
  \item{check}{logical indicating if the mpfrArray construction should
    happen with internal safety check.  Previously, the implicit default
    used to be true.}
  \item{names}{(for \code{.mpfr2list()}) \code{\link{logical}} or
    \code{\link{character}} vector, indicating if the list returned
    should have \code{\link{names}}.  If character, it specifies the
    names; if true, the names are set to \code{format(x)}.}
  \item{mxp}{an \code{"mpfrXport"} object, as resulting from
    \code{mpfrXport()}.}
  \item{kind}{a \code{\link{character}} string or vector, specifying the
    kind of \dQuote{erange} value; must be an element of
    \code{.mpfr_erange_kinds}, i.e., one of \code{"Emin"}, \code{"Emax"},
    \code{"min.emin"}, \code{"max.emin"}, \code{"min.emax"}, \code{"max.emax"}.}
  \item{value}{\code{\link{numeric}}, for \code{.mpfr_erange_set()} one
    number per \code{kind}.  Must be in range specified by the
    \code{*."emin"} and \code{*."emax"} erange values.}
}
\details{
  The \code{.mpfr_erange*} functions (and variable) allow to query and set
  the allowed range of values for the base-2 \emph{exponents} of
  \code{"mpfr"} numbers.
  See the examples below and GNU MPFR library documentation on the C functions
  \code{mpfr_get_emin()}, \code{mpfr_set_emin(.)},
  \code{mpfr_get_emin_min()}, and \code{mpfr_get_emin_max()},
  (and those four with \sQuote{_emin} replaced by \sQuote{_emax} above).
}
\value{
  \code{getPrec(x)} returns a \code{\link{integer}} vector of length one or
  the same length as \code{x} when that is positive, whereas
  \code{getPrec(NULL)} returns \code{mpfr_default_prec()}, see below.
  % the current MPFR default precision, see   \code{mpfr_default_prec()}
  If you need to \emph{change} the precision of \code{x}, i.e., need
  something like \dQuote{setPrec}, use \code{\link{roundMpfr}()}.

  \code{.getPrec(x)} is a simplified version of \code{getPrec()} which only
  works for \code{"mpfr"} objects \code{x}.

  \code{getD(x)} is intended to be a fast version of \code{x@.Data},
  and should not be used outside of lower level functions.

  \code{mpfr_default_prec()} returns the current MPFR default precision,
  an \code{\link{integer}}.  This is currently % ??
  not made use of much in package \pkg{Rmpfr}, where functions have
  their own default precision where needed, and otherwise we'd rather not
  be dependent of such a \emph{global} setting.
  \cr
  \code{mpfr_default_prec(prec)} \emph{sets} the current MPFR default
  precision and returns the previous one; see above.

  \code{.mpfr_maxPrec()} and (less interestingly) \code{.mpfr_minPrec()}
  give the maximal and minimal base-2 precision allowed in the current
  version of the MPFR library linked to by \R package \pkg{Rmpfr}.
  The maximal precision is typically \eqn{2^{63}}, i.e.,
  \preformatted{ all.equal(.mpfr_maxPrec(), 2^63) }
  is typically true.

  \code{toNum(m)} returns a numeric \code{\link{array}} or
  \code{\link{matrix}}, when \code{m} is of class
  \code{"\linkS4class{mpfrArray}"} or \code{"\linkS4class{mpfrMatrix}"},
  respectively.  It should be equivalent to \code{as(m, "array")} or
  \code{... "matrix"}.   Note that the slightly more general
  \code{\link[gmp]{asNumeric}()} from \CRANpkg{gmp} is preferred now.
  \code{.mpfr2d()} is similar to but simpler than \code{toNum()}, whereas
  \code{.mpfr2i()} is an analogue low level utility for
  \code{\link{as.integer}(<mpfr>)}.

  \code{mpfr2array()} a slightly more flexible alternative to
  \code{dim(.) <- dd}.

  \code{.mpfr2exp(x)} returns the base-2 (integer valued) exponents of
  \code{x}, i.e., it is the \R interface to MPFR C's \code{mpfr_get_exp()}.
  The result is \code{\link{integer}}  iff \code{.mpfr_erange_is_int()}
  is true, otherwise \code{\link{double}}.  Note that the MPFR (4.0.1)
  manual says about \code{mpfr_get_exp()}: \emph{The behavior for NaN,
    infinity or zero is undefined}.

  \code{.mpfr_erange_is_int()} returns \code{TRUE} iff the
  \code{.mpfr_erange(c("Emin","Emax"))} range lies inside the range of \R's
  \code{\link{integer}} limits, i.e., has absolute values not larger than
  \code{\link{.Machine}$integer.max} (\eqn{ = 2^{31} - 1}).

  \code{.mpfr_erange_set()} \emph{invisibly} (see \code{\link{invisible}()})
  returns \code{TRUE} iff the change was successful.

  \code{.mpfr_gmp_numbbits()} returns the \file{GMP} library \dQuote{numb}
  size, which is either 32 or 64 bit (as \code{\link{integer}}, i.e.,
  \code{64L} or \code{32L}).  If it is \emph{not} 64, you typically
  cannot enlarge the exponential range of mpfr numbers via
  \code{.mpfr_erange()}, see above.

  \code{.mpfrSizeof()} may be more relevant (than \code{.mpfr_gmp_numbbits()}),
  returning a named integer vector of \code{\link{length}(.) == 3} with
  the sizes in bytes of the three \file{MPFR} library types named
  \code{c("mpfr_prec_t", "mpfr_exp_t", "mp_limb_t")}.

  \code{.mpfrVersion()} returns a string, the version of the \file{MPFR}
  library we are linking to.

  \code{.mpfr_formatinfo(x)} returns conceptually a subset of
  \code{\link{.mpfr2str}()}'s result, a list with three components
  \describe{
    \item{exp}{the base-2 exponents of \code{x}, identical to \code{.mpfr2exp(x)}.}
    \item{finite}{\code{\link{logical}} identical to \code{\link{is.finite}(x)}.}
    \item{is.0}{\code{\link{logical}} indicating if the corresponding
      \code{x[i]} is zero; identical to \code{\link{mpfrIs0}(x)}.}}
  (Note that \code{\link{.mpfr2str}(x, .., base)$exp} is wrt \code{base}
  \emph{and} is not undefined but ...)% FIXME

  \code{.mpfr_sign(x)} only works for \code{mpfr} objects, then identical
  to \code{\link{sign}(x)}.  Analogously, \code{.mpfr_negative(x)} is
  \code{-x} in that case.
  \code{.getSign(x)} is a low-level version of \code{\link{sign}(x)}
  returning -1 or +1, but not 0.
  \cr
  Finally, \code{..bigq2mpfr(x, ..)} and \code{..bigz2mpfr(x, ..)} are fast
  ways to coerce \code{bigz} and \code{bigq} number objects (created by
  package \CRANpkg{gmp}'s functionality) to our \code{"mpfr"} class.
}
\note{
  \code{mpfrXport()} and \code{mpfrImport()} are \bold{experimental} and
  used to explore reported platform incompatibilities of
  \code{\link{save}()}d and \code{\link{load}()}ed \code{"mpfr"}
  objects between Windows and non-Windows platforms.

  In other words, the format of the result of \code{mpfrXport()} and
  hence the \code{mxp} argument to \code{mpfrImport()} are considered
  internal, not part of the API and subject to change.
}
\seealso{
  Start using \code{\link{mpfr}(..)}, and compute with these numbers.

  \code{\link{mpfrArray}(x)} is for numeric (\dQuote{non-mpfr})
  \code{x}, whereas \code{mpfr2array(x)} is for \code{"mpfr"} classed
  \code{x}, only.
}
\examples{
getPrec(as(c(1,pi), "mpfr")) # 128 for both

(opr <- mpfr_default_prec()) ## typically  53, the MPFR system default
stopifnot(opr == (oprec <- mpfr_default_prec(70)),
          70  == mpfr_default_prec())
## and reset it:
mpfr_default_prec(opr)

## Explore behavior of rounding modes 'rnd.mode':
x <- mpfr(10,99)^512 # too large for regular (double prec. / numeric):
sapply(c("N", "D", "U", "Z", "A"), function(RM)
       sapply(list(-x,x), function(.) toNum(., RM)))
##    N             D              U              Z    A
## -Inf          -Inf -1.797693e+308 -1.797693e+308 -Inf
##  Inf 1.797693e+308            Inf  1.797693e+308  Inf

## Ranges of (base 2) exponents of MPFR numbers:
.mpfr_erange() # the currently active range of possible base 2 exponents:

## A factory fresh setting fulfills
.mpfr_erange(c("Emin","Emax")) == c(-1,1) * (2^30 - 1)

## There are more 'kind's, the latter 4 showing how you could change the first two :
.mpfr_erange_kinds
.mpfr_erange(.mpfr_erange_kinds)
eLimits <- .mpfr_erange(c("min.emin", "max.emin", "min.emax", "max.emax"))
## Typically true in MPFR versions *iff* long is 64-bit, i.e. *not* on Windows
if(.Machine$sizeof.long == 8L) {
    eLimits == c(-1,1, -1,1) * (2^62 - 1)
} else if(.Machine$sizeof.long == 4L) # on Windows
    eLimits == c(-1,1, -1,1) * (2^30 - 1)


## Looking at internal representation [for power users only!]:

i8 <- mpfr(-2:5, 32)
x4 <- mpfr(c(NA, NaN, -Inf, Inf), 32)
stopifnot(exprs = {
    identical(x4[1], x4[2])
    is.na(x4[1] == x4[2]) # <- was *wrong* in Rmpfr <= 0.9-4
    is.na(x4[1] != x4[2]) #  (ditto)
    identical(x4 < i8[1:4], c(NA,NA, TRUE,FALSE))
    !is.finite(x4)
    identical(is.infinite(x4), c(FALSE,FALSE, TRUE,TRUE))
})
## The output of the following depends on the GMP "numb" size
## (32 bit vs. 64 bit), *and* additionally
## on sizeof.long (mostly non-Windows <-> Windows, see above):
str( .mpfr2list(i8) )
str( .mpfr2list(x4, names = TRUE) )

dput( .mpfrSizeof() ) # on (64-bit) Linux, now typically all '8',
## as 64 bit = 8 bytes --  nowadays probably more relevant than
dput( .mpfr_gmp_numbbits() ) # typically 64

str(xp4 <- mpfrXport(x4, names = TRUE))
stopifnot(identical(x4, mpfrImport(mpfrXport(x4))),
          identical(i8, mpfrImport(mpfrXport(i8))))

B6 <- mpfr2array(Bernoulli(1:6, 60), c(2,3),
                 dimnames = list(LETTERS[1:2], letters[1:3]))
## FIXME, need c(.), as dim(.) & dimnames(.)  "get lost" in export/import:
stopifnot(identical(c(B6), mpfrImport(mpfrXport(B6))))
}
\keyword{utilities}
