1/* mpfr_sin_cos -- sine and cosine of a floating-point number
2
3Copyright 2002-2023 Free Software Foundation, Inc.
4Contributed by the AriC and Caramba projects, INRIA.
5
6This file is part of the GNU MPFR Library.
7
8The GNU MPFR Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MPFR Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23#define MPFR_NEED_LONGLONG_H
24#include "mpfr-impl.h"
25
26/* (y, z) <- (sin(x), cos(x)), return value is 0 iff both results are exact
27   ie, iff x = 0 */
28int
29mpfr_sin_cos (mpfr_ptr y, mpfr_ptr z, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
30{
31  mpfr_prec_t prec, m;
32  int neg, reduce;
33  mpfr_t c, xr;
34  mpfr_srcptr xx;
35  mpfr_exp_t err, expx;
36  int inexy, inexz;
37  MPFR_ZIV_DECL (loop);
38  MPFR_SAVE_EXPO_DECL (expo);
39
40  MPFR_ASSERTN (y != z);
41
42  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
43    {
44      if (MPFR_IS_NAN(x) || MPFR_IS_INF(x))
45        {
46          MPFR_SET_NAN (y);
47          MPFR_SET_NAN (z);
48          MPFR_RET_NAN;
49        }
50      else /* x is zero */
51        {
52          MPFR_ASSERTD (MPFR_IS_ZERO (x));
53          MPFR_SET_ZERO (y);
54          MPFR_SET_SAME_SIGN (y, x);
55          /* y = 0, thus exact, but z is inexact in case of underflow
56             or overflow */
57          inexy = 0; /* y is exact */
58          inexz = mpfr_set_ui (z, 1, rnd_mode);
59          return INEX(inexy,inexz);
60        }
61    }
62
63  MPFR_LOG_FUNC
64    (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode),
65     ("sin[%Pu]=%.*Rg cos[%Pu]=%.*Rg", mpfr_get_prec(y), mpfr_log_prec, y,
66      mpfr_get_prec (z), mpfr_log_prec, z));
67
68  MPFR_SAVE_EXPO_MARK (expo);
69
70  prec = MAX (MPFR_PREC (y), MPFR_PREC (z));
71  m = prec + MPFR_INT_CEIL_LOG2 (prec) + 13;
72  expx = MPFR_GET_EXP (x);
73
74  /* When x is close to 0, say 2^(-k), then there is a cancellation of about
75     2k bits in 1-cos(x)^2. FIXME: in that case, it would be more efficient
76     to compute sin(x) directly. VL: This is partly done by using
77     MPFR_FAST_COMPUTE_IF_SMALL_INPUT from the mpfr_sin and mpfr_cos
78     functions. Moreover, any overflow on m is avoided. */
79  if (expx < 0)
80    {
81      /* Warning: in case y = x, and the first call to
82         MPFR_FAST_COMPUTE_IF_SMALL_INPUT succeeds but the second fails,
83         we will have clobbered the original value of x.
84         The workaround is to first compute z = cos(x) in that case, since
85         y and z are different. */
86      if (y != x)
87        /* y and x differ, thus we can safely try to compute y first */
88        {
89          MPFR_FAST_COMPUTE_IF_SMALL_INPUT (
90            y, x, -2 * expx, 2, 0, rnd_mode,
91            { inexy = _inexact;
92              goto small_input; });
93          if (0)
94            {
95            small_input:
96              /* we can go here only if we can round sin(x) */
97              MPFR_FAST_COMPUTE_IF_SMALL_INPUT (
98                z, __gmpfr_one, -2 * expx, 1, 0, rnd_mode,
99                { inexz = _inexact;
100                  MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
101                  goto end; });
102            }
103
104          /* if we go here, one of the two MPFR_FAST_COMPUTE_IF_SMALL_INPUT
105             calls failed */
106        }
107      else /* y and x are the same variable: try to compute z first, which
108              necessarily differs */
109        {
110          MPFR_FAST_COMPUTE_IF_SMALL_INPUT (
111            z, __gmpfr_one, -2 * expx, 1, 0, rnd_mode,
112            { inexz = _inexact;
113              goto small_input2; });
114          if (0)
115            {
116            small_input2:
117              /* we can go here only if we can round cos(x) */
118              MPFR_FAST_COMPUTE_IF_SMALL_INPUT (
119                y, x, -2 * expx, 2, 0, rnd_mode,
120                { inexy = _inexact;
121                  MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
122                  goto end; });
123            }
124        }
125      m += 2 * (-expx);
126    }
127
128  if (prec >= MPFR_SINCOS_THRESHOLD)
129    {
130      MPFR_SAVE_EXPO_FREE (expo);
131      return mpfr_sincos_fast (y, z, x, rnd_mode);
132    }
133
134  mpfr_init2 (c, m);
135  mpfr_init2 (xr, m);
136
137  MPFR_ZIV_INIT (loop, m);
138  for (;;)
139    {
140      /* the following is copied from sin.c */
141      if (expx >= 2) /* reduce the argument */
142        {
143          reduce = 1;
144          MPFR_ASSERTN (expx + m - 1 <= MPFR_PREC_MAX);
145          mpfr_set_prec (c, expx + m - 1);
146          mpfr_set_prec (xr, m);
147          mpfr_const_pi (c, MPFR_RNDN);
148          mpfr_mul_2ui (c, c, 1, MPFR_RNDN);
149          mpfr_remainder (xr, x, c, MPFR_RNDN);
150          mpfr_div_2ui (c, c, 1, MPFR_RNDN);
151          if (MPFR_IS_POS (xr))
152            mpfr_sub (c, c, xr, MPFR_RNDZ);
153          else
154            mpfr_add (c, c, xr, MPFR_RNDZ);
155          if (MPFR_IS_ZERO(xr)
156              || MPFR_EXP(xr) < (mpfr_exp_t) 3 - (mpfr_exp_t) m
157              || MPFR_EXP(c) < (mpfr_exp_t) 3 - (mpfr_exp_t) m)
158            goto next_step;
159          xx = xr;
160        }
161      else /* the input argument is already reduced */
162        {
163          reduce = 0;
164          xx = x;
165        }
166
167      neg = MPFR_IS_NEG (xx); /* gives sign of sin(x) */
168      mpfr_set_prec (c, m);
169      mpfr_cos (c, xx, MPFR_RNDZ);
170      /* If no argument reduction was performed, the error is at most ulp(c),
171         otherwise it is at most ulp(c) + 2^(2-m). Since |c| < 1, we have
172         ulp(c) <= 2^(-m), thus the error is bounded by 2^(3-m) in that later
173         case. */
174      if (reduce == 0)
175        err = m;
176      else
177        err = MPFR_GET_EXP (c) + (mpfr_exp_t) (m - 3);
178      if (!MPFR_CAN_ROUND (c, err, MPFR_PREC (z), rnd_mode))
179        goto next_step;
180
181      /* We can't set z now, because in case z = x, and the MPFR_CAN_ROUND()
182         call below fails, we will have clobbered the input.
183         Note: m below is the precision of c; see above. */
184      mpfr_set_prec (xr, m);
185      mpfr_swap (xr, c); /* save the approximation of the cosine in xr */
186      mpfr_sqr (c, xr, MPFR_RNDU); /* the absolute error is bounded by
187                                      2^(5-m) if reduce=1, and by 2^(2-m)
188                                      otherwise */
189      mpfr_ui_sub (c, 1, c, MPFR_RNDN); /* error bounded by 2^(6-m) if reduce
190                                           is 1, and 2^(3-m) otherwise */
191      mpfr_sqrt (c, c, MPFR_RNDN); /* the absolute error is bounded by
192                                      2^(6-m-Exp(c)) if reduce=1, and
193                                      2^(3-m-Exp(c)) otherwise */
194      err = 3 + 3 * reduce - MPFR_GET_EXP (c);
195      if (neg)
196        MPFR_CHANGE_SIGN (c);
197
198      /* the absolute error on c is at most 2^(err-m), which we must put
199         in the form 2^(EXP(c)-err). */
200      err = MPFR_GET_EXP (c) + (mpfr_exp_t) m - err;
201      if (MPFR_CAN_ROUND (c, err, MPFR_PREC (y), rnd_mode))
202        break;
203      /* check for huge cancellation */
204      if (err < (mpfr_exp_t) MPFR_PREC (y))
205        m += MPFR_PREC (y) - err;
206      /* Check if near 1 */
207      if (MPFR_GET_EXP (c) == 1
208          && MPFR_MANT (c)[MPFR_LIMB_SIZE (c)-1] == MPFR_LIMB_HIGHBIT)
209        m += m;
210
211    next_step:
212      MPFR_ZIV_NEXT (loop, m);
213      mpfr_set_prec (c, m);
214    }
215  MPFR_ZIV_FREE (loop);
216
217  inexy = mpfr_set (y, c, rnd_mode);
218  inexz = mpfr_set (z, xr, rnd_mode);
219
220  mpfr_clear (c);
221  mpfr_clear (xr);
222
223 end:
224  MPFR_SAVE_EXPO_FREE (expo);
225  /* FIXME: add a test for bug before revision 7355 */
226  inexy = mpfr_check_range (y, inexy, rnd_mode);
227  inexz = mpfr_check_range (z, inexz, rnd_mode);
228  MPFR_RET (INEX(inexy,inexz));
229}
230
231/*************** asymptotically fast implementation below ********************/
232
233/* truncate Q from R to at most prec bits.
234   Return the number of truncated bits.
235 */
236static mpfr_prec_t
237reduce (mpz_t Q, mpz_srcptr R, mpfr_prec_t prec)
238{
239  mpfr_prec_t l;
240
241  MPFR_MPZ_SIZEINBASE2(l, R);
242  l = (l > prec) ? l - prec : 0;
243  mpz_fdiv_q_2exp (Q, R, l);
244  return l;
245}
246
247/* truncate S and C so that the smaller has prec bits.
248   Return the number of truncated bits.
249 */
250static unsigned long
251reduce2 (mpz_t S, mpz_t C, mpfr_prec_t prec)
252{
253  unsigned long ls;
254  unsigned long lc;
255  unsigned long l;
256
257  MPFR_MPZ_SIZEINBASE2(ls, S);
258  MPFR_MPZ_SIZEINBASE2(lc, C);
259
260  l = (ls < lc) ? ls : lc; /* smaller length */
261  l = (l > prec) ? l - prec : 0;
262  mpz_fdiv_q_2exp (S, S, l);
263  mpz_fdiv_q_2exp (C, C, l);
264  return l;
265}
266
267/* return in S0/Q0 a rational approximation of sin(X) with absolute error
268                     bounded by 9*2^(-prec), where 0 <= X=p/2^r <= 1/2,
269   and in    C0/Q0 a rational approximation of cos(X), with relative error
270                     bounded by 9*2^(-prec) (and also absolute error, since
271                     |cos(X)| <= 1).
272   We have sin(X)/X = sum((-1)^i*(p/2^r)^i/(2i+1)!, i=0..infinity).
273   We use the following binary splitting formula:
274   P(a,b) = (-p)^(b-a)
275   Q(a,b) = (2a)*(2a+1)*2^r if a+1=b [except Q(0,1)=1], Q(a,c)*Q(c,b) otherwise
276   T(a,b) = 1 if a+1=b, Q(c,b)*T(a,c)+P(a,c)*T(c,b) otherwise.
277
278   Since we use P(a,b) for b-a=2^k only, we compute only p^(2^k).
279   We do not store the factor 2^r in Q().
280
281   Then sin(X)/X ~ T(0,i)/Q(0,i) for i so that (p/2^r)^i/i! is small enough.
282
283   Return l such that Q0 has to be multiplied by 2^l.
284
285   Assumes prec >= 10.
286*/
287
288#define KMAX 64
289static unsigned long
290sin_bs_aux (mpz_t Q0, mpz_t S0, mpz_t C0, mpz_srcptr p, mpfr_prec_t r,
291            mpfr_prec_t prec)
292{
293  mpz_t T[KMAX], Q[KMAX], ptoj[KMAX], pp;
294  mpfr_prec_t log2_nb_terms[KMAX], mult[KMAX];
295  mpfr_prec_t accu[KMAX], size_ptoj[KMAX];
296  mpfr_prec_t prec_i_have, h, r0 = r, pp_s, p_s;
297  unsigned long i, j, m;
298  int alloc, k, l;
299
300  if (MPFR_UNLIKELY(mpz_cmp_ui (p, 0) == 0)) /* sin(x)/x -> 1 */
301    {
302      mpz_set_ui (Q0, 1);
303      mpz_set_ui (S0, 1);
304      mpz_set_ui (C0, 1);
305      return 0;
306    }
307
308  /* check that X=p/2^r <= 1/2 */
309  MPFR_ASSERTN(mpz_sizeinbase (p, 2) - (mpfr_exp_t) r <= -1);
310
311  mpz_init (pp);
312
313  /* normalize p (non-zero here) */
314  h = mpz_scan1 (p, 0);
315  mpz_fdiv_q_2exp (pp, p, h); /* p = pp * 2^h */
316  mpz_mul (pp, pp, pp);
317  r = 2 * (r - h);            /* x^2 = (p/2^r0)^2 = pp / 2^r */
318
319  /* now p is odd */
320  alloc = 2;
321  mpz_init_set_ui (T[0], 6);
322  mpz_init_set_ui (Q[0], 6);
323  mpz_init_set (ptoj[0], pp); /* ptoj[i] = pp^(2^i) */
324  mpz_init (T[1]);
325  mpz_init (Q[1]);
326  mpz_init (ptoj[1]);
327  mpz_mul (ptoj[1], pp, pp);  /* ptoj[1] = pp^2 */
328  MPFR_MPZ_SIZEINBASE2(size_ptoj[1], ptoj[1]);
329
330  mpz_mul_2exp (T[0], T[0], r);
331  mpz_sub (T[0], T[0], pp);      /* 6*2^r - pp = 6*2^r*(1 - x^2/6) */
332  log2_nb_terms[0] = 1;
333
334  /* already take into account the factor x=p/2^r in sin(x) = x * (...) */
335  MPFR_MPZ_SIZEINBASE2(pp_s, pp);
336  MPFR_MPZ_SIZEINBASE2(p_s, p);
337  mult[0] = r - pp_s + r0 - p_s;
338  /* we have x^3 < 1/2^mult[0] */
339
340  for (i = 2, k = 0, prec_i_have = mult[0]; prec_i_have < prec; i += 2)
341    {
342      /* i is even here */
343      /* invariant: Q[0]*Q[1]*...*Q[k] equals (2i-1)!,
344         we have already summed terms of index < i
345         in S[0]/Q[0], ..., S[k]/Q[k] */
346      k ++;
347      if (k + 1 >= alloc) /* necessarily k + 1 = alloc */
348        {
349          MPFR_ASSERTD (k + 1 == alloc);
350          alloc ++;
351          MPFR_ASSERTN (k + 1 < KMAX);
352          mpz_init (T[k+1]);
353          mpz_init (Q[k+1]);
354          mpz_init (ptoj[k+1]);
355          mpz_mul (ptoj[k+1], ptoj[k], ptoj[k]); /* pp^(2^(k+1)) */
356          MPFR_MPZ_SIZEINBASE2(size_ptoj[k+1], ptoj[k+1]);
357        }
358      /* for i even, we have Q[k] = (2*i)*(2*i+1), T[k] = 1,
359         then                Q[k+1] = (2*i+2)*(2*i+3), T[k+1] = 1,
360         which reduces to T[k] = (2*i+2)*(2*i+3)*2^r-pp,
361         Q[k] = (2*i)*(2*i+1)*(2*i+2)*(2*i+3). */
362      MPFR_ASSERTN (k < KMAX);
363      log2_nb_terms[k] = 1;
364      mpz_set_ui (Q[k], 2 * i + 2);
365      mpz_mul_ui (Q[k], Q[k], 2 * i + 3);
366      mpz_mul_2exp (T[k], Q[k], r);
367      mpz_sub (T[k], T[k], pp);
368      mpz_mul_ui (Q[k], Q[k], 2 * i);
369      mpz_mul_ui (Q[k], Q[k], 2 * i + 1);
370      /* the next term of the series is divided by Q[k] and multiplied
371         by pp^2/2^(2r), thus the mult. factor < 1/2^mult[k] */
372      MPFR_MPZ_SIZEINBASE2(mult[k], Q[k]);
373      mult[k] += 2 * r - size_ptoj[1] - 1;
374      /* the absolute contribution of the next term is 1/2^accu[k] */
375      accu[k] = (k == 0) ? mult[k] : mult[k] + accu[k-1];
376      prec_i_have = accu[k]; /* the current term is < 1/2^accu[k] */
377      j = (i + 2) / 2;
378      l = 1;
379      while ((j & 1) == 0) /* combine and reduce */
380        {
381          MPFR_ASSERTN (k >= 1);
382          mpz_mul (T[k], T[k], ptoj[l]);
383          mpz_mul (T[k-1], T[k-1], Q[k]);
384          mpz_mul_2exp (T[k-1], T[k-1], r << l);
385          mpz_add (T[k-1], T[k-1], T[k]);
386          mpz_mul (Q[k-1], Q[k-1], Q[k]);
387          log2_nb_terms[k-1] ++; /* number of terms in S[k-1]
388                                    is a power of 2 by construction */
389          MPFR_MPZ_SIZEINBASE2(prec_i_have, Q[k]);
390          mult[k-1] += prec_i_have + (r << l) - size_ptoj[l] - 1;
391          accu[k-1] = (k == 1) ? mult[k-1] : mult[k-1] + accu[k-2];
392          prec_i_have = accu[k-1];
393          l ++;
394          j >>= 1;
395          k --;
396        }
397    }
398
399  /* accumulate all products in T[0] and Q[0]. Warning: contrary to above,
400     here we do not have log2_nb_terms[k-1] = log2_nb_terms[k]+1. */
401  h = 0; /* number of accumulated terms in the right part T[k]/Q[k] */
402  while (k > 0)
403    {
404      mpz_mul (T[k], T[k], ptoj[log2_nb_terms[k-1]]);
405      mpz_mul (T[k-1], T[k-1], Q[k]);
406      h += (mpfr_prec_t) 1 << log2_nb_terms[k];
407      mpz_mul_2exp (T[k-1], T[k-1], r * h);
408      mpz_add (T[k-1], T[k-1], T[k]);
409      mpz_mul (Q[k-1], Q[k-1], Q[k]);
410      k--;
411    }
412
413  m = r0 + r * (i - 1); /* implicit multiplier 2^r for Q0 */
414  /* at this point T[0]/(2^m*Q[0]) is an approximation of sin(x) where the 1st
415     neglected term has contribution < 1/2^prec, thus since the series has
416     alternate signs, the error is < 1/2^prec */
417
418  /* we truncate Q0 to prec bits: the relative error is at most 2^(1-prec),
419     which means that Q0 = Q[0] * (1+theta) with |theta| <= 2^(1-prec)
420     [up to a power of two] */
421  m += reduce (Q0, Q[0], prec);
422  m -= reduce (T[0], T[0], prec);
423  /* multiply by x = p/2^m */
424  mpz_mul (S0, T[0], p);
425  m -= reduce (S0, S0, prec); /* S0 = T[0] * (1 + theta)^2 up to power of 2 */
426  /* sin(X) ~ S0/Q0*(1 + theta)^3 + err with |theta| <= 2^(1-prec) and
427              |err| <= 2^(-prec), thus since |S0/Q0| <= 1:
428     |sin(X) - S0/Q0| <= 4*|theta*S0/Q0| + |err| <= 9*2^(-prec) */
429
430  mpz_clear (pp);
431  for (k = 0; k < alloc; k ++)
432    {
433      mpz_clear (T[k]);
434      mpz_clear (Q[k]);
435      mpz_clear (ptoj[k]);
436    }
437
438  /* compute cos(X) from sin(X): sqrt(1-(S/Q)^2) = sqrt(Q^2-S^2)/Q
439     = sqrt(Q0^2*2^(2m)-S0^2)/Q0.
440     Write S/Q = sin(X) + eps with |eps| <= 9*2^(-prec),
441     then sqrt(Q^2-S^2) = sqrt(Q^2-Q^2*(sin(X)+eps)^2)
442                        = sqrt(Q^2*cos(X)^2-Q^2*(2*sin(X)*eps+eps^2))
443                        = sqrt(Q^2*cos(X)^2-Q^2*eps1) with |eps1|<=9*2^(-prec)
444                          [using X<=1/2 and eps<=9*2^(-prec) and prec>=10]
445
446                        Since we truncate the square root, we get:
447                          sqrt(Q^2*cos(X)^2-Q^2*eps1)+eps2 with |eps2|<1
448                        = Q*sqrt(cos(X)^2-eps1)+eps2
449                        = Q*cos(X)*(1+eps3)+eps2 with |eps3| <= 6*2^(-prec)
450                        = Q*cos(X)*(1+eps3+eps2/(Q*cos(X)))
451                        = Q*cos(X)*(1+eps4) with |eps4| <= 9*2^(-prec)
452                          since |Q| >= 2^(prec-1) */
453  /* we assume that Q0*2^m >= 2^(prec-1) */
454  MPFR_ASSERTN(m + mpz_sizeinbase (Q0, 2) >= prec);
455  mpz_mul (C0, Q0, Q0);
456  mpz_mul_2exp (C0, C0, 2 * m);
457  mpz_submul (C0, S0, S0);
458  mpz_sqrt (C0, C0);
459
460  return m;
461}
462
463/* Put in s and c approximations of sin(x) and cos(x) respectively.
464   Assumes 0 < x < Pi/4 and PREC(s) = PREC(c) >= 10.
465   Return err such that the relative error is bounded by 2^err ulps.
466*/
467static int
468sincos_aux (mpfr_ptr s, mpfr_ptr c, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
469{
470  mpfr_prec_t prec_s, sh;
471  mpz_t Q, S, C, Q2, S2, C2, y;
472  mpfr_t x2;
473  unsigned long l, l2, j, err;
474
475  MPFR_ASSERTD(MPFR_PREC(s) == MPFR_PREC(c));
476
477  prec_s = MPFR_PREC(s);
478
479  mpfr_init2 (x2, MPFR_PREC(x));
480  mpz_init (Q);
481  mpz_init (S);
482  mpz_init (C);
483  mpz_init (Q2);
484  mpz_init (S2);
485  mpz_init (C2);
486  mpz_init (y);
487
488  mpfr_set (x2, x, MPFR_RNDN); /* exact */
489  mpz_set_ui (Q, 1);
490  l = 0;
491  mpz_set_ui (S, 0); /* sin(0) = S/(2^l*Q), exact */
492  mpz_set_ui (C, 1); /* cos(0) = C/(2^l*Q), exact */
493
494  /* Invariant: x = X + x2/2^(sh-1), where the part X was already treated,
495     S/(2^l*Q) ~ sin(X), C/(2^l*Q) ~ cos(X), and x2/2^(sh-1) < Pi/4.
496     'sh-1' is the number of already shifted bits in x2.
497  */
498
499  for (sh = 1, j = 0; mpfr_cmp_ui (x2, 0) != 0 && sh <= prec_s; sh <<= 1, j++)
500    {
501      if (sh > prec_s / 2) /* sin(x) = x + O(x^3), cos(x) = 1 + O(x^2) */
502        {
503          l2 = -mpfr_get_z_2exp (S2, x2); /* S2/2^l2 = x2 */
504          l2 += sh - 1;
505          mpz_set_ui (Q2, 1);
506          mpz_set_ui (C2, 1);
507          mpz_mul_2exp (C2, C2, l2);
508          mpfr_set_ui (x2, 0, MPFR_RNDN);
509        }
510      else
511        {
512          /* y <- trunc(x2 * 2^sh) = trunc(x * 2^(2*sh-1)) */
513          mpfr_mul_2ui (x2, x2, sh, MPFR_RNDN); /* exact */
514          mpfr_get_z (y, x2, MPFR_RNDZ); /* round toward zero: now
515                                           0 <= x2 < 2^sh, thus
516                                           0 <= x2/2^(sh-1) < 2^(1-sh) */
517          if (mpz_cmp_ui (y, 0) == 0)
518            continue;
519          mpfr_sub_z (x2, x2, y, MPFR_RNDN); /* should be exact */
520          l2 = sin_bs_aux (Q2, S2, C2, y, 2 * sh - 1, prec_s);
521          /* we now have |S2/Q2/2^l2 - sin(X)| <= 9*2^(prec_s)
522             and |C2/Q2/2^l2 - cos(X)| <= 6*2^(prec_s), with X=y/2^(2sh-1) */
523        }
524      if (sh == 1) /* S=0, C=1 */
525        {
526          l = l2;
527          mpz_swap (Q, Q2);
528          mpz_swap (S, S2);
529          mpz_swap (C, C2);
530        }
531      else
532        {
533          /* s <- s*c2+c*s2, c <- c*c2-s*s2, using Karatsuba:
534             a = s+c, b = s2+c2, t = a*b, d = s*s2, e = c*c2,
535             s <- t - d - e, c <- e - d */
536          mpz_add (y, S, C); /* a */
537          mpz_mul (C, C, C2); /* e */
538          mpz_add (C2, C2, S2); /* b */
539          mpz_mul (S2, S, S2); /* d */
540          mpz_mul (y, y, C2); /* a*b */
541          mpz_sub (S, y, S2); /* t - d */
542          mpz_sub (S, S, C); /* t - d - e */
543          mpz_sub (C, C, S2); /* e - d */
544          mpz_mul (Q, Q, Q2);
545          /* after j loops, the error is <= (11j-2)*2^(prec_s) */
546          l += l2;
547          /* reduce Q to prec_s bits */
548          l += reduce (Q, Q, prec_s);
549          /* reduce S,C to prec_s bits, error <= 11*j*2^(prec_s) */
550          l -= reduce2 (S, C, prec_s);
551        }
552    }
553
554  j = 11 * j;
555  for (err = 0; j > 1; j = (j + 1) / 2, err ++);
556
557  mpfr_set_z (s, S, MPFR_RNDN);
558  mpfr_div_z (s, s, Q, MPFR_RNDN);
559  mpfr_div_2ui (s, s, l, MPFR_RNDN);
560
561  mpfr_set_z (c, C, MPFR_RNDN);
562  mpfr_div_z (c, c, Q, MPFR_RNDN);
563  mpfr_div_2ui (c, c, l, MPFR_RNDN);
564
565  mpz_clear (Q);
566  mpz_clear (S);
567  mpz_clear (C);
568  mpz_clear (Q2);
569  mpz_clear (S2);
570  mpz_clear (C2);
571  mpz_clear (y);
572  mpfr_clear (x2);
573  return err;
574}
575
576/* Assumes x is neither NaN, +/-Inf, nor +/- 0.
577   One of s and c might be NULL, in which case the corresponding value is
578   not computed.
579   Assumes s differs from c.
580 */
581int
582mpfr_sincos_fast (mpfr_ptr s, mpfr_ptr c, mpfr_srcptr x, mpfr_rnd_t rnd)
583{
584  int inexs, inexc;
585  mpfr_t x_red, ts, tc;
586  mpfr_prec_t w;
587  mpfr_exp_t err, errs, errc;
588  MPFR_GROUP_DECL (group);
589  MPFR_ZIV_DECL (loop);
590
591  MPFR_ASSERTN(s != c);
592  if (s == NULL)
593    w = MPFR_PREC(c);
594  else if (c == NULL)
595    w = MPFR_PREC(s);
596  else
597    w = MPFR_PREC(s) >= MPFR_PREC(c) ? MPFR_PREC(s) : MPFR_PREC(c);
598  w += MPFR_INT_CEIL_LOG2(w) + 9; /* ensures w >= 10 (needed by sincos_aux) */
599
600  MPFR_GROUP_INIT_2(group, w, ts, tc);
601
602  MPFR_ZIV_INIT (loop, w);
603  for (;;)
604    {
605      /* if 0 < x <= Pi/4, we can call sincos_aux directly */
606      if (MPFR_IS_POS(x) && mpfr_cmp_ui_2exp (x, 1686629713, -31) <= 0)
607        {
608          err = sincos_aux (ts, tc, x, MPFR_RNDN);
609        }
610      /* if -Pi/4 <= x < 0, use sin(-x)=-sin(x) */
611      else if (MPFR_IS_NEG(x) && mpfr_cmp_si_2exp (x, -1686629713, -31) >= 0)
612        {
613          MPFR_ALIAS(x_red, x, MPFR_SIGN_POS, MPFR_GET_EXP(x));
614          err = sincos_aux (ts, tc, x_red, MPFR_RNDN);
615          MPFR_CHANGE_SIGN(ts);
616        }
617      else /* argument reduction is needed */
618        {
619          long q;
620          mpfr_t pi;
621          int neg = 0;
622
623          mpfr_init2 (x_red, w);
624          mpfr_init2 (pi, (MPFR_EXP(x) > 0) ? w + MPFR_EXP(x) : w);
625          mpfr_const_pi (pi, MPFR_RNDN);
626          mpfr_div_2ui (pi, pi, 1, MPFR_RNDN); /* Pi/2 */
627          mpfr_remquo (x_red, &q, x, pi, MPFR_RNDN);
628          /* x = q * (Pi/2 + eps1) + x_red + eps2,
629             where |eps1| <= 1/2*ulp(Pi/2) = 2^(-w-MAX(0,EXP(x))),
630             and eps2 <= 1/2*ulp(x_red) <= 1/2*ulp(Pi/2) = 2^(-w)
631             Since |q| <= x/(Pi/2) <= |x|, we have
632             q*|eps1| <= 2^(-w), thus
633             |x - q * Pi/2 - x_red| <= 2^(1-w) */
634          /* now -Pi/4 <= x_red <= Pi/4: if x_red < 0, consider -x_red */
635          if (MPFR_IS_NEG(x_red))
636            {
637              mpfr_neg (x_red, x_red, MPFR_RNDN);
638              neg = 1;
639            }
640          err = sincos_aux (ts, tc, x_red, MPFR_RNDN);
641          err ++; /* to take into account the argument reduction */
642          if (neg) /* sin(-x) = -sin(x), cos(-x) = cos(x) */
643            mpfr_neg (ts, ts, MPFR_RNDN);
644          if (q & 2) /* sin(x+Pi) = -sin(x), cos(x+Pi) = -cos(x) */
645            {
646              mpfr_neg (ts, ts, MPFR_RNDN);
647              mpfr_neg (tc, tc, MPFR_RNDN);
648            }
649          if (q & 1) /* sin(x+Pi/2) = cos(x), cos(x+Pi/2) = -sin(x) */
650            {
651              mpfr_neg (ts, ts, MPFR_RNDN);
652              mpfr_swap (ts, tc);
653            }
654          mpfr_clear (x_red);
655          mpfr_clear (pi);
656        }
657      /* adjust errors with respect to absolute values */
658      errs = err - MPFR_EXP(ts);
659      errc = err - MPFR_EXP(tc);
660      if ((s == NULL || MPFR_CAN_ROUND (ts, w - errs, MPFR_PREC(s), rnd)) &&
661          (c == NULL || MPFR_CAN_ROUND (tc, w - errc, MPFR_PREC(c), rnd)))
662        break;
663      MPFR_ZIV_NEXT (loop, w);
664      MPFR_GROUP_REPREC_2(group, w, ts, tc);
665    }
666  MPFR_ZIV_FREE (loop);
667
668  inexs = (s == NULL) ? 0 : mpfr_set (s, ts, rnd);
669  inexc = (c == NULL) ? 0 : mpfr_set (c, tc, rnd);
670
671  MPFR_GROUP_CLEAR (group);
672  return INEX(inexs,inexc);
673}
674