1 /* mpfr_sinh -- hyperbolic sine
3 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao projects, INRIA.
6 This file is part of the GNU MPFR Library.
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or (at your
11 option) any later version.
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 MA 02110-1301, USA. */
23 #define MPFR_NEED_LONGLONG_H
24 #include "mpfr-impl.h"
26 /* The computation of sinh is done by
27 sinh(x) = 1/2 [e^(x)-e^(-x)] */
30 mpfr_sinh (mpfr_ptr y
, mpfr_srcptr xt
, mp_rnd_t rnd_mode
)
35 MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", xt
, xt
, rnd_mode
),
36 ("y[%#R]=%R inexact=%d", y
, y
, inexact
));
38 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (xt
)))
45 else if (MPFR_IS_INF (xt
))
48 MPFR_SET_SAME_SIGN (y
, xt
);
53 MPFR_ASSERTD (MPFR_IS_ZERO (xt
));
54 MPFR_SET_ZERO (y
); /* sinh(0) = 0 */
55 MPFR_SET_SAME_SIGN (y
, xt
);
60 /* sinh(x) = x + x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */
61 MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y
, xt
, -2 * MPFR_GET_EXP(xt
), 2, 1,
64 MPFR_TMP_INIT_ABS (x
, xt
);
69 mp_prec_t Nt
; /* Precision of the intermediary variable */
70 long int err
; /* Precision of error */
72 MPFR_SAVE_EXPO_DECL (expo
);
73 MPFR_GROUP_DECL (group
);
75 MPFR_SAVE_EXPO_MARK (expo
);
77 /* compute the precision of intermediary variable */
78 Nt
= MAX (MPFR_PREC (x
), MPFR_PREC (y
));
79 /* the optimal number of bits : see algorithms.ps */
80 Nt
= Nt
+ MPFR_INT_CEIL_LOG2 (Nt
) + 4;
81 /* If x is near 0, exp(x) - 1/exp(x) = 2*x+x^3/3+O(x^5) */
82 if (MPFR_GET_EXP (x
) < 0)
83 Nt
-= 2*MPFR_GET_EXP (x
);
85 /* initialise of intermediary variables */
86 MPFR_GROUP_INIT_2 (group
, Nt
, t
, ti
);
88 /* First computation of sinh */
89 MPFR_ZIV_INIT (loop
, Nt
);
92 MPFR_BLOCK_DECL (flags
);
95 MPFR_BLOCK (flags
, mpfr_exp (t
, x
, GMP_RNDD
));
96 if (MPFR_OVERFLOW (flags
))
97 /* exp(x) does overflow */
99 /* sinh(x) = 2 * sinh(x/2) * cosh(x/2) */
100 mpfr_div_2ui (ti
, x
, 1, GMP_RNDD
); /* exact */
102 /* t <- cosh(x/2): error(t) <= 1 ulp(t) */
103 MPFR_BLOCK (flags
, mpfr_cosh (t
, ti
, GMP_RNDD
));
104 if (MPFR_OVERFLOW (flags
))
105 /* when x>1 we have |sinh(x)| >= cosh(x/2), so sinh(x)
108 inexact
= mpfr_overflow (y
, rnd_mode
, MPFR_SIGN (xt
));
109 MPFR_SAVE_EXPO_UPDATE_FLAGS (expo
, MPFR_FLAGS_OVERFLOW
);
113 /* ti <- sinh(x/2): , error(ti) <= 1 ulp(ti)
114 cannot overflow because 0 < sinh(x) < cosh(x) when x > 0 */
115 mpfr_sinh (ti
, ti
, GMP_RNDD
);
117 /* multiplication below, error(t) <= 5 ulp(t) */
118 MPFR_BLOCK (flags
, mpfr_mul (t
, t
, ti
, GMP_RNDD
));
119 if (MPFR_OVERFLOW (flags
))
121 inexact
= mpfr_overflow (y
, rnd_mode
, MPFR_SIGN (xt
));
122 MPFR_SAVE_EXPO_UPDATE_FLAGS (expo
, MPFR_FLAGS_OVERFLOW
);
126 /* doubling below, exact */
127 MPFR_BLOCK (flags
, mpfr_mul_2ui (t
, t
, 1, GMP_RNDN
));
128 if (MPFR_OVERFLOW (flags
))
130 inexact
= mpfr_overflow (y
, rnd_mode
, MPFR_SIGN (xt
));
131 MPFR_SAVE_EXPO_UPDATE_FLAGS (expo
, MPFR_FLAGS_OVERFLOW
);
135 /* we have lost at most 3 bits of precision */
137 if (MPFR_LIKELY (MPFR_CAN_ROUND (t
, err
, MPFR_PREC (y
),
140 inexact
= mpfr_set4 (y
, t
, rnd_mode
, MPFR_SIGN (xt
));
143 err
= Nt
; /* double the precision */
147 d
= MPFR_GET_EXP (t
);
148 mpfr_ui_div (ti
, 1, t
, GMP_RNDU
); /* 1/exp(x) */
149 mpfr_sub (t
, t
, ti
, GMP_RNDN
); /* exp(x) - 1/exp(x) */
150 mpfr_div_2ui (t
, t
, 1, GMP_RNDN
); /* 1/2(exp(x) - 1/exp(x)) */
152 /* it may be that t is zero (in fact, it can only occur when te=1,
153 and thus ti=1 too) */
154 if (MPFR_IS_ZERO (t
))
155 err
= Nt
; /* double the precision */
158 /* calculation of the error */
159 d
= d
- MPFR_GET_EXP (t
) + 2;
160 /* error estimate: err = Nt-(__gmpfr_ceil_log2(1+pow(2,d)));*/
161 err
= Nt
- (MAX (d
, 0) + 1);
162 if (MPFR_LIKELY (MPFR_CAN_ROUND (t
, err
, MPFR_PREC (y
),
165 inexact
= mpfr_set4 (y
, t
, rnd_mode
, MPFR_SIGN (xt
));
171 /* actualisation of the precision */
173 MPFR_ZIV_NEXT (loop
, Nt
);
174 MPFR_GROUP_REPREC_2 (group
, Nt
, t
, ti
);
176 MPFR_ZIV_FREE (loop
);
177 MPFR_GROUP_CLEAR (group
);
178 MPFR_SAVE_EXPO_FREE (expo
);
181 return mpfr_check_range (y
, inexact
, rnd_mode
);