diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2007-07-09 09:46:49 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2007-07-09 09:46:49 +0000 |
commit | f45f3cda75310b0cb32c165c10b856795c09a5ad (patch) | |
tree | 6bf6ece8f2ba9d03459ddf5bc72f610e3077c7ed | |
parent | 15db3bbdb1cd9f0178a3abf1f4d96ddb4e18dd4a (diff) | |
download | mpfr-f45f3cda75310b0cb32c165c10b856795c09a5ad.tar.gz |
Merges changesets 4629 and 4630 from the trunk (bug fixes, updated
algorithms.tex).
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/2.3@4631 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | algorithms.tex | 42 | ||||
-rw-r--r-- | cos.c | 9 | ||||
-rw-r--r-- | tan.c | 5 |
3 files changed, 23 insertions, 33 deletions
diff --git a/algorithms.tex b/algorithms.tex index ce14d412a..bf0f702d4 100644 --- a/algorithms.tex +++ b/algorithms.tex @@ -870,7 +870,9 @@ above reasoning. At step (1c) we have $r=y/2$, thus $r-y$ simplifies to $-r$. \subsection{The cosine function} To evaluate $\cos x$ with a target precision of $n$ bits, we use the following -algorithm with working precision $m$: +algorithm with working precision $m$, after an additive argument reduction +which reduces $x$ in the interval $[-\pi, \pi]$, using the +\texttt{mpfr\_remainder} function: \begin{quote} $k \leftarrow \lfloor \sqrt{n/2} \rfloor$ \\ $r \leftarrow x^2$ rounded up \\ % err <= ulp(r) @@ -907,7 +909,7 @@ giving $\epsilon_k \le (2 l_0+1/3) 2^{2k-m}$. \subsection{The sine function} The sine function is computed from the cosine, with a working precision of -$m$ bits: +$m$ bits, after an additive argument reduction in $[-\pi, \pi]$: \begin{quote} $c \leftarrow \cos x$ rounded away \\ $t \leftarrow c^2$ rounded away \\ @@ -993,34 +995,20 @@ bound of $2^{-p+7}$. \subsection{The tangent function} -The tangent function is computed from the cosine, -using $\tan x = {\rm sign}(x) \sqrt{\frac{1}{\cos^2 x} - 1}$, +The tangent function is computed from the \texttt{mpfr\_sin\_cos} function, +which computes simultaneously $\sin x$ and $\cos x$ with a working precision of $m$ bits: \begin{quote} -$c \leftarrow \cos x$ rounded down \\ % c <= cos(x) <= 1 -$t \leftarrow c^2$ rounded down \\ % t <= cos(x)^2 <= 1 -$v \leftarrow 1/t$ rounded up \\ % v >= 1/cos(x)^2 >= 1 -$u \leftarrow v - 1$ rounded up \\ % u >= 1/cos(x)^2 - 1 -$s \leftarrow {\rm sign}(x) \sqrt{u}$ rounded away from $0$ \\ +$s, c \leftarrow \circ(\sin x), \circ(\cos x)$ \quad [to nearest] \\ +$t \leftarrow \circ(s/c)$ \quad [to nearest] \\ \end{quote} -The absolute error on $c$ is at most $\ulp(c)$. -Hence the error on -$t$ is at most $\ulp(t) + 2 c \ulp(c) \le 5 \ulp(t)$, -% err(t) <= ulp(t) + |c^2-c'^2| <= ulp(t) + |c-c'|*|c+c'| -% <= ulp(t) + 2*ulp(c)*c <= 5*ulp(t) -that on $v$ is at most $\ulp(v) + 5 \ulp(t)/t^2 - \le \ulp(v) + 10 \ulp(1/t) \le 11 \ulp(v)$, -% err(v) <= ulp(v) + |1/t-1/t'| <= ulp(v) + |t-t'|/t/t' -% <= ulp(v) + 5*ulp(t)/t^2 <= ulp(v) + 10*ulp(1/t) <= 11*ulp(v) -that on $u$ is at most $\ulp(u) + 11 \ulp(v) \le (1 + 11 \cdot 2^e) \ulp(u)$ -where $e$ is the exponent difference between $v$ and $u$. -% err(u) <= ulp(u) + err(v) <= ulp(v) + 11*ulp(v) <= (1+11*2^e)*ulp(u) -The final error on $s$ is $\le \ulp(s) + (1+11 \cdot 2^e) \ulp(u)/2/\sqrt{u} - \le \ulp(s) + (1+11 \cdot 2^e) \ulp(u/\sqrt{u}) - \le (2 + 11 \cdot 2^e) \ulp(s)$. -% err(s) <= ulp(s) + |u-u'|/2/sqrt(u) <= ulp(s) + (1+11*2^e)*ulp(u)/2/sqrt(u) -% <= ulp(s) + (1+11*2^e)*ulp(u/sqrt(u)) -% <= (2+11*2^e)*ulp(s) +We have $s = \sin(x) (1 + \theta_1)$ and $c = \cos(x) (1 + \theta_2)$ +with $|\theta_1|, |\theta_2| \leq 2^{-m}$, thus +$t = (\tan x) (1 + \theta)^3$ with $|\theta| \leq 2^{-m}$. +For $m \geq 2$, $|\theta| \leq 1/4$, +$|(1 + \theta)^3 - 1| \leq 4 |\theta|$, thus we can write +$t = (\tan x) (1 + 4 \theta)$, thus +$|t - \tan x| \leq 4 \ulp(t)$. \subsection{The exponential function} @@ -231,10 +231,11 @@ mpfr_cos (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) { if (m > k && (m - k >= precy + (rnd_mode == GMP_RNDN))) { - /* if round to nearest or away, result is s, - otherwise it is round(nexttoward (s, 0)) */ - if (MPFR_IS_LIKE_RNDZ (rnd_mode, MPFR_IS_NEG (s))) - mpfr_nexttozero (s); + /* If round to nearest or away, result is s = 1 or -1, + otherwise it is round(nexttoward (s, 0)). However in order to + have the inexact flag correctly set below, we set |s| to + 1 - 2^(-m) in all cases. */ + mpfr_nexttozero (s); break; } } @@ -62,6 +62,7 @@ mpfr_tan (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) /* Compute initial precision */ precy = MPFR_PREC (y); m = precy + MPFR_INT_CEIL_LOG2 (precy) + 13; + MPFR_ASSERTD (m >= 2); /* needed for the error analysis in algorithms.tex */ MPFR_GROUP_INIT_2 (group, m, s, c); MPFR_ZIV_INIT (loop, m); @@ -70,9 +71,9 @@ mpfr_tan (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) /* The only way to get an overflow is to get ~ Pi/2 But the result will be ~ 2^Prec(y). */ mpfr_sin_cos (s, c, x, GMP_RNDN); /* err <= 1/2 ulp on s and c */ - mpfr_div (c, s, c, GMP_RNDN); /* err <= 2 ulps */ + mpfr_div (c, s, c, GMP_RNDN); /* err <= 4 ulps */ MPFR_ASSERTD (!MPFR_IS_SINGULAR (c)); - if (MPFR_LIKELY (MPFR_CAN_ROUND (c, m-1, precy, rnd_mode))) + if (MPFR_LIKELY (MPFR_CAN_ROUND (c, m - 2, precy, rnd_mode))) break; MPFR_ZIV_NEXT (loop, m); MPFR_GROUP_REPREC_2 (group, m, s, c); |