1 /*
2 * Correctly rounded hyperbolic sine and cosine
3 *
4 * Author : Matthieu Gallet, Florent de Dinechin
5 *
6 * This file is part of the crlibm library, developed by the Arenaire
7 * project at Ecole Normale Superieure de Lyon
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "crlibm.h"
28 #include "crlibm_private.h"
29 #include "csh_fast.h"
30 #include "triple-double.h"
31
32 void exp13(int *exponent, double *exp_h, double *exp_m, double *exp_l, double x);
33 void expm1_13(double *exp_h, double *exp_m, double *exp_l, double x);
34
35 /* switches on various printfs. Default 0 */
36 #define DEBUG 0
37 static const double largest_double = 0x1.fffffffffffffp1023;
38 static const double tiniest_double = 0x1.0p-1074;
39
40 enum{RN,RD,RU,RZ};
41
do_cosh(double x,double * preshi,double * preslo)42 static void do_cosh(double x, double* preshi, double* preslo){
43 int k;
44 db_number y;
45 double ch_hi, ch_lo, sh_hi, sh_lo;/* cosh(x) = (ch_hi + ch_lo)*(cosh(k*ln(2)) + (sh_hi + sh_lo)*(sinh(k*ln(2))) */
46 db_number table_index_float;
47 int table_index;
48 double temp_hi, temp_lo, temp;/* some temporary variables */
49 double b_hi, b_lo,b_ca_hi, b_ca_lo, b_sa_hi, b_sa_lo;
50 double ca_hi, ca_lo, sa_hi, sa_lo; /*will be the tabulated values */
51 double tcb_hi, tsb_hi; /*results of polynomial approximations*/
52 double square_b_hi;
53 double ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo;
54 double sh_2_pk_hi, sh_2_pk_lo, sh_2_mk_hi, sh_2_mk_lo;
55 db_number two_p_plus_k, two_p_minus_k; /* 2^(k-1) + 2^(-k-1) */
56
57 /* First range reduction*/
58 DOUBLE2INT(k, x * inv_ln_2.d)
59 if (k != 0){ /* b_hi+b_lo = x - (ln2_hi + ln2_lo) * k */
60 temp_hi = x - ln2_hi.d * k;
61 temp_lo = -ln2_lo.d * k;
62 Add12Cond(b_hi, b_lo, temp_hi, temp_lo);
63 }
64 else {
65 b_hi = x; b_lo = 0.;
66 }
67 /*we'll construct 2 constants for the last reconstruction */
68 two_p_plus_k.i[LO] = 0;
69 two_p_plus_k.i[HI] = (k-1+1023) << 20;
70 two_p_minus_k.i[LO] = 0;
71 two_p_minus_k.i[HI] = (-k-1+1023) << 20;
72
73 /* at this stage, we've done the first range reduction : we have b_hi + b_lo between -ln(2)/2 and ln(2)/2 */
74 /* now we can do the second range reduction */
75 /* we'll get the 8 leading bits of b_hi */
76 table_index_float.d = b_hi + two_43_44.d;
77 /*this add do the float equivalent of a rotation to the right, since -0.5 <= b_hi <= 0.5*/
78 table_index = table_index_float.i[LO];/* -89 <= table_index <= 89 */
79 table_index_float.d -= two_43_44.d;
80 table_index += bias; /* to have only positive values */
81 b_hi -= table_index_float.d;/* to remove the 8 leading bits*/
82 /* since b_hi was between -2^-1 and 2^1, we now have b_hi between -2^-9 and 2^-9 */
83
84
85 y.d = b_hi;
86 /* first, y� */
87 square_b_hi = b_hi * b_hi;
88 /* effective computation of the polynomial approximation */
89
90 if (((y.i[HI])&(0x7FFFFFFF)) < (two_minus_30.i[HI])) {
91 tcb_hi = 0;
92 tsb_hi = 0;
93 }
94 else {
95 /* second, cosh(y) = y� * (1/2 + y� * (1/24 + y� * 1/720)) */
96 tcb_hi = (square_b_hi)* (c2.d + square_b_hi * (c4.d + square_b_hi * c6.d));
97 tsb_hi = square_b_hi * (s3.d + square_b_hi * (s5.d + square_b_hi * s7.d));
98 }
99
100
101 if( table_index != bias) {
102 /* we get the tabulated the tabulated values */
103 ca_hi = cosh_sinh_table[table_index][0].d;
104 ca_lo = cosh_sinh_table[table_index][1].d;
105 sa_hi = cosh_sinh_table[table_index][2].d;
106 sa_lo = cosh_sinh_table[table_index][3].d;
107
108 /* first reconstruction of the cosh (corresponding to the second range reduction) */
109 Mul12(&b_sa_hi,&b_sa_lo, sa_hi, b_hi);
110 temp = ((((((ca_lo + (b_hi * sa_lo)) + b_lo * sa_hi) + b_sa_lo) + (b_sa_hi * tsb_hi)) + ca_hi * tcb_hi) + b_sa_hi);
111 Add12Cond(ch_hi, ch_lo, ca_hi, temp);
112 /* first reconstruction for the sinh (corresponding to the second range reduction) */
113 }
114 else {
115 Add12Cond(ch_hi, ch_lo, (double) 1, tcb_hi);
116 }
117
118
119 if(k != 0) {
120 if( table_index != bias) {
121 /* first reconstruction for the sinh (corresponding to the second range reduction) */
122 Mul12(&b_ca_hi , &b_ca_lo, ca_hi, b_hi);
123 temp = (((((sa_lo + (b_lo * ca_hi)) + (b_hi * ca_lo)) + b_ca_lo) + (sa_hi*tcb_hi)) + (b_ca_hi * tsb_hi));
124 Add12(temp_hi, temp_lo, b_ca_hi, temp);
125 Add22Cond(&sh_hi, &sh_lo, sa_hi, (double) 0, temp_hi, temp_lo);
126 }
127 else {
128 Add12Cond(sh_hi, sh_lo, b_hi, tsb_hi * b_hi + b_lo);
129 }
130 if((k < 35) && (k > -35) )
131 {
132 ch_2_pk_hi = ch_hi * two_p_plus_k.d;
133 ch_2_pk_lo = ch_lo * two_p_plus_k.d;
134 ch_2_mk_hi = ch_hi * two_p_minus_k.d;
135 ch_2_mk_lo = ch_lo * two_p_minus_k.d;
136 sh_2_pk_hi = sh_hi * two_p_plus_k.d;
137 sh_2_pk_lo = sh_lo * two_p_plus_k.d;
138 sh_2_mk_hi = - sh_hi * two_p_minus_k.d;
139 sh_2_mk_lo = - sh_lo * two_p_minus_k.d;
140
141 Add22Cond(preshi, preslo, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo);
142 Add22Cond(&ch_2_mk_hi, &ch_2_mk_lo , sh_2_pk_hi, sh_2_pk_lo, *preshi, *preslo);
143 Add22Cond(preshi, preslo, ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo);
144 }
145 else if (k >= 35)
146 {
147 ch_2_pk_hi = ch_hi * two_p_plus_k.d;
148 ch_2_pk_lo = ch_lo * two_p_plus_k.d;
149 sh_2_pk_hi = sh_hi * two_p_plus_k.d;
150 sh_2_pk_lo = sh_lo * two_p_plus_k.d;
151 Add22Cond(preshi, preslo, ch_2_pk_hi, ch_2_pk_lo, sh_2_pk_hi, sh_2_pk_lo);
152 }
153 else /* if (k <= -35) */
154 {
155 ch_2_mk_hi = ch_hi * two_p_minus_k.d;
156 ch_2_mk_lo = ch_lo * two_p_minus_k.d;
157 sh_2_mk_hi = - sh_hi * two_p_minus_k.d;
158 sh_2_mk_lo = - sh_lo * two_p_minus_k.d;
159 Add22Cond(preshi, preslo, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo);
160 }
161 }
162 else {
163 *preshi = ch_hi;
164 *preslo = ch_lo;
165 }
166
167 return;
168 }
169
170
171
do_cosh_accurate(int * pexponent,double * presh,double * presm,double * presl,double x)172 static void do_cosh_accurate(int* pexponent,
173 double* presh, double* presm, double* presl,
174 double x){
175 double exph, expm, expl;
176 double expph, exppm, exppl;
177 int exponentm, deltaexponent;
178 db_number expmh, expmm, expml;
179
180 #if EVAL_PERF==1
181 crlibm_second_step_taken++;
182 #endif
183
184 if(x<0)
185 x=-x;
186 if (x > 40.0) { /* then exp(-x) < 2^-118 exp(x) */
187 exp13(pexponent, presh, presm, presl, x);
188 }
189 else {
190 exp13(pexponent, &expph, &exppm, &exppl, x);
191 exp13(&exponentm, &(expmh.d), &(expmm.d), &(expml.d), -x);
192 /* align the mantissas.
193 The exponent is increased but stays well below overflow threshold */
194 deltaexponent = exponentm - *pexponent ;
195 expmh.i[HI] += (deltaexponent) << 20;
196 expmm.i[HI] += (deltaexponent) << 20;
197 expml.i[HI] += (deltaexponent) << 20;
198 Add33(&exph, &expm, &expl, expph, exppm, exppl, expmh.d, expmm.d, expml.d);
199 Renormalize3(presh,presm,presl, exph, expm, expl);
200 }
201 }
202
203
204
cosh_rn(double x)205 double cosh_rn(double x){
206 db_number y;
207 int hx;
208 double rh, rl;
209
210 y.d = x;
211 hx = y.i[HI] & 0x7FFFFFFF;
212
213 /* Filter special cases */
214 if (hx > max_input_csh.i[HI]) { /* strictly greater, implies x > max_input_csh */
215 if (hx >= 0x7ff00000){ /* Infty or NaN */
216 if (((hx&0x000fffff)|y.i[LO])!=0)
217 return x+x; /* Nan */
218 else {/* otherwise the result should be +infty */
219 y.i[HI] = 0x7FF00000;
220 return (y.d);
221 }
222 }
223 }
224 if (x >= max_input_csh.d || x <= -max_input_csh.d)
225 return largest_double * largest_double; /* overflow */
226 if (hx<0x3e500000) {
227 if(x==0)
228 return 1.0; /* exact */
229 else
230 return (1.0+tiniest_double); /* to raise inexact flag */
231 }
232
233 do_cosh(x, &rh, &rl);
234
235
236 if (rh == (rh + (rl * round_cst_csh))) return rh;
237 else{
238 int exponent;
239 db_number res;
240 double resh, resm, resl;
241
242 do_cosh_accurate(&exponent, &resh,&resm, &resl, x);
243 RoundToNearest3(&(res.d), resh, resm, resl);
244
245 /* Now we have to set the exponent of res as exponent -1 (division
246 by 2). However, as res may sometimes end up infinite, we first
247 set the exponent to exponent -11 and then multiply by 2^10,
248 which will cater for overflow */
249 res.i[HI] += (exponent-11) << 20;
250 return 1024. * res.d;
251 }
252 }
253
254
255
256
257
258
259
260
cosh_ru(double x)261 double cosh_ru(double x){
262 db_number y;
263 int hx;
264 double rh, rl;
265
266 y.d = x;
267 hx = y.i[HI] & 0x7FFFFFFF;
268
269 if (hx > max_input_csh.i[HI]) {
270 /* if NaN, return it */
271 if (((hx&0x7FF00000) == 0x7FF00000) && (((y.i[HI] & 0x000FFFFF)!=0) || (y.i[LO]!=0)) )
272 return x;
273 else {/* otherwise the result should be +infty */
274 y.i[LO] = 0; y.i[HI] = 0x7FF00000; return (y.d);
275 }
276 }
277
278 if (x >= max_input_csh.d || x <= -max_input_csh.d)
279 return largest_double * largest_double; /* overflow */
280
281 if (hx<0x3e500000) { /* return the successor of 1 */
282 if(x==0.) return 1.0;
283 else{
284 y.l = 0x3ff0000000000001LL;
285 return y.d;
286 }
287 }
288
289 do_cosh(x, &rh, &rl);
290
291 TEST_AND_RETURN_RU(rh, rl, maxepsilon_csh);
292
293 /* if the previous block didn't return a value, launch accurate phase */
294 {
295 int exponent;
296 db_number res;
297 double resh, resm, resl;
298
299 do_cosh_accurate(&exponent, &resh,&resm, &resl, x);
300 RoundUpwards3(&(res.d), resh,resm,resl);
301
302 /* Now we have to set the exponent of res as exponent -1 (division
303 by 2). However, as res may sometimes end up infinite, we first
304 set the exponent to exponent -11 and then multiply by 2^10,
305 which will cater for overflow */
306 res.i[HI] += (exponent-11) << 20;
307 return 1024. * res.d;
308 }
309 }
310
311
312
cosh_rd(double x)313 double cosh_rd(double x){
314 db_number y;
315 int hx;
316 double rh, rl;
317
318 y.d = x;
319 hx = y.i[HI] & 0x7FFFFFFF;
320
321
322 if (hx > max_input_csh.i[HI]) {
323 if (hx >= 0x7FF00000) { /*particular cases : QNaN, SNaN, +- oo*/
324 if (((hx&0x7FF00000) == 0x7FF00000) && (((y.i[HI] & 0x000FFFFF)!=0) || (y.i[LO]!=0)) )
325 return x; /* NaN */
326 else { /* infinity */
327 y.i[HI] = hx;
328 return (y.d);
329 }
330 }
331 }
332
333 if (y.d >= max_input_csh.d || y.d <= - max_input_csh.d) { /* out of range */
334 y.i[LO] = 0xFFFFFFFF; y.i[HI] = 0x7FEFFFFF ; return (y.d);
335 }
336
337 if (hx<0x3e500000)
338 return (1.0);
339
340 do_cosh(x, &rh, &rl);
341
342 TEST_AND_RETURN_RD(rh, rl, maxepsilon_csh);
343
344 /* if the previous block didn't return a value, launch accurate phase */
345 {
346 int exponent;
347 db_number res;
348 double resh, resm, resl;
349
350 do_cosh_accurate(&exponent, &resh,&resm, &resl, x);
351 RoundDownwards3(&(res.d), resh,resm,resl);
352
353 /* Now we have to set the exponent of res as exponent -1 (division
354 by 2). However, as res may sometimes end up infinite, we first
355 set the exponent to exponent -11 and then multiply by 2^10,
356 which will cater for overflow */
357 res.i[HI] += (exponent-11) << 20;
358 return 1024. * res.d;
359 }
360 }
361
362
363
cosh_rz(double x)364 double cosh_rz(double x){
365 return(cosh_rd(x));/* cosh is always positive, so rounding to -infinite is equivalent to rounding to zero */
366 }
367
368
369
370
371
372
373
374
375
376
do_sinh(double x,double * prh,double * prl)377 static void do_sinh(double x, double* prh, double* prl){
378
379 int k;
380 db_number y;
381 double temp1;
382 double ch_hi, ch_lo, sh_hi, sh_lo;/* cosh(x) = (sh_hi + sh_lo)*(cosh(k*ln(2)) + (ch_hi + ch_lo)*(sinh(k*ln(2))) */
383 db_number table_index_float;
384 int table_index;
385 double ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo;
386 double sh_2_pk_hi, sh_2_pk_lo, sh_2_mk_hi, sh_2_mk_lo;
387 double b_hi, b_lo;
388 double ca_b_hi, ca_b_lo, temp_hi, temp_lo, sa_b_hi, sa_b_lo;
389 double ca_hi, ca_lo, sa_hi, sa_lo; /*tabulated values */
390 double tcb_hi, tsb_hi; /*results of polynomial approximations*/
391 db_number two_p_plus_k, two_p_minus_k; /* 2^(k-1) + 2^(-k-1) */
392 double square_y_hi;
393
394 /* Now we can do the first range reduction*/
395 DOUBLE2INT(k, x * inv_ln_2.d)
396 if (k != 0){ /* b_hi + b_lo = x - (ln2_hi + ln2_lo) * k */
397 temp_hi = x - ln2_hi.d * k;
398 temp_lo = -ln2_lo.d * k;
399 Add12Cond(b_hi, b_lo, temp_hi, temp_lo);
400 }
401 else {
402 b_hi = x; b_lo = 0.;
403 }
404
405 /*we'll construct 2 constants for the last reconstruction */
406 two_p_plus_k.i[LO] = 0;
407 two_p_plus_k.i[HI] = (k-1+1023) << 20;
408 two_p_minus_k.i[LO] = 0;
409 two_p_minus_k.i[HI] = (-k-1+1023) << 20;
410
411 /* at this stage, we've done the first range reduction : we have b_hi + b_lo between -ln(2)/2 and ln(2)/2 */
412 /* now we can do the second range reduction */
413 /* we'll get the 8 leading bits of r_hi */
414
415 table_index_float.d = b_hi + two_43_44.d;
416 /*this add do the float equivalent of a rotation to the right, since -0.5 <= b_hi <= 0.5*/
417 table_index = table_index_float.i[LO];/* -89 <= table_index <= 89 */
418 table_index_float.d -= two_43_44.d;
419 table_index += bias; /* to have only positive values */
420 b_hi -= table_index_float.d;/* to remove the 8 leading bits*/
421 /* since b_hi was between -2^-1 and 2^1, we now have b_hi between -2^-9 and 2^-9 */
422
423 y.d = b_hi;
424 /* first, y� = square_y_hi + square_y_lo */
425 square_y_hi = b_hi * b_hi;
426 /* effective computation of the polyomial approximation */
427 if (((y.i[HI])&(0x7FFFFFFF)) <= (two_minus_30.i[HI])) {
428 tsb_hi = 0;
429 tcb_hi = 0;
430 }
431 else {
432 tsb_hi = square_y_hi * (s3.d + square_y_hi * (s5.d + square_y_hi * s7.d));
433 /* second, cosh(y) = y� * (1/2 + y� * (1/24 + y� * 1/720)) */
434 tcb_hi = (square_y_hi)* (c2.d + square_y_hi * (c4.d + square_y_hi * c6.d));
435 }
436
437 if( table_index != bias) {
438 /* we get the tabulated the tabulated values*/
439 ca_hi = cosh_sinh_table[table_index][0].d;
440 ca_lo = cosh_sinh_table[table_index][1].d;
441 sa_hi = cosh_sinh_table[table_index][2].d;
442 sa_lo = cosh_sinh_table[table_index][3].d;
443
444 /* first reconstruction for the sinh (corresponding to the second range reduction) */
445 temp1 = sa_lo;
446 temp1 += b_lo * ca_hi;
447 temp1 += b_hi * ca_lo;
448 Mul12(&ca_b_hi, &ca_b_lo, ca_hi, b_hi);
449 temp1 += ca_b_lo;
450 temp1 += sa_hi * tcb_hi;
451 temp1 += ca_b_hi * tsb_hi;
452 Add12Cond(temp_hi, temp_lo, ca_b_hi, temp1);
453 Add22Cond(&sh_hi, &sh_lo, sa_hi, (double) 0, temp_hi, temp_lo);
454 /* first reconstruction of the cosh (corresponding to the second range reduction) */
455 temp1 = ca_lo;
456 Mul12(&sa_b_hi,&sa_b_lo, sa_hi, b_hi);
457 temp1 += b_hi * sa_lo;
458 temp1 += b_lo * sa_hi;
459 temp1 += sa_b_lo;
460 temp1 += sa_b_hi * tsb_hi;
461 temp1 += ca_hi * tcb_hi;
462 temp1 += sa_b_hi;
463 Add12Cond(ch_hi, ch_lo, ca_hi, temp1);
464 }
465 else {
466 Add12Cond(sh_hi, sh_lo, b_hi, tsb_hi * b_hi + b_lo);
467 Add12Cond(ch_hi, ch_lo, (double) 1, tcb_hi);
468 }
469
470 if(k != 0) {
471 if( (k < 35) && (k > -35) ) {
472 ch_2_pk_hi = ch_hi * two_p_plus_k.d;
473 ch_2_pk_lo = ch_lo * two_p_plus_k.d;
474 ch_2_mk_hi = - ch_hi * two_p_minus_k.d;
475 ch_2_mk_lo = - ch_lo * two_p_minus_k.d;
476 sh_2_pk_hi = sh_hi * two_p_plus_k.d;
477 sh_2_pk_lo = sh_lo * two_p_plus_k.d;
478 sh_2_mk_hi = sh_hi * two_p_minus_k.d;
479 sh_2_mk_lo = sh_lo * two_p_minus_k.d;
480
481 Add22Cond(prh, prl, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo);
482 Add22Cond(&ch_2_mk_hi, &ch_2_mk_lo , sh_2_pk_hi, sh_2_pk_lo, *prh, *prl);
483 Add22Cond(prh, prl, ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo);
484 }
485 else if (k >= 35)
486 {
487 ch_2_pk_hi = ch_hi * two_p_plus_k.d;
488 ch_2_pk_lo = ch_lo * two_p_plus_k.d;
489 sh_2_pk_hi = sh_hi * two_p_plus_k.d;
490 sh_2_pk_lo = sh_lo * two_p_plus_k.d;
491 Add22Cond(prh, prl, ch_2_pk_hi, ch_2_pk_lo, sh_2_pk_hi, sh_2_pk_lo);
492 }
493 else
494 {
495 ch_2_mk_hi = - ch_hi * two_p_minus_k.d;
496 ch_2_mk_lo = - ch_lo * two_p_minus_k.d;
497 sh_2_mk_hi = sh_hi * two_p_minus_k.d;
498 sh_2_mk_lo = sh_lo * two_p_minus_k.d;
499 Add22Cond(prh, prl, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo);
500 }
501 }
502 else {
503 *prh = sh_hi;
504 *prl = sh_lo;
505 }
506 }
507
508
509
510
511
do_sinh_accurate(int * pexponent,double * presh,double * presm,double * presl,double x)512 static void do_sinh_accurate(int* pexponent,
513 double* presh, double* presm, double* presl,
514 double x){
515 double exph, expm, expl;
516 double expph, exppm, exppl, expmh, expmm, expml;
517
518 #if EVAL_PERF==1
519 crlibm_second_step_taken++;
520 #endif
521
522 if(x > 40.0) { /* then exp(-x) < 2^-129 exp(x) */
523 exp13(pexponent, presh, presm, presl, x);
524 return;
525 }
526 if(x < -40.0) { /* then exp(x) < 2^-129 exp(-x) */
527 exp13(pexponent, presh, presm, presl, -x);
528 *presh = -*presh;
529 *presm = -*presm;
530 *presl = -*presl;
531 return;
532 }
533 /* Otherwise we are between -40 and 40, and we also know that |x| > 2^-25 */
534 if(x>0.0) {
535 expm1_13(&expph, &exppm, &exppl, x);
536 expm1_13(&expmh, &expmm, &expml, -x);
537 /* The following is OK because expph and -expmh have the same sign */
538 Add33(&exph, &expm, &expl, expph, exppm, exppl, -expmh, -expmm, -expml);
539 Renormalize3(presh,presm,presl, exph, expm, expl);
540 *pexponent=0;
541 return;
542 }
543 else { /* x<0 */
544 expm1_13(&expph, &exppm, &exppl, x);
545 expm1_13(&expmh, &expmm, &expml, -x);
546 /* The following is OK because expph and -expmh have the same sign */
547 Add33(&exph, &expm, &expl, -expmh, -expmm, -expml, expph, exppm, exppl);
548 Renormalize3(presh,presm,presl, exph, expm, expl);
549 *pexponent=0;
550 return;
551 }
552 }
553
554
555
556
sinh_rn(double x)557 double sinh_rn(double x){
558 db_number y;
559 int hx;
560 double rh, rl;
561
562
563 y.d = x;
564 hx = y.i[HI] & 0x7FFFFFFF;
565
566 /* Filter special cases */
567 if (hx > max_input_csh.i[HI]) { /* strictly greater, implies x > max_input_csh */
568 if (hx >= 0x7ff00000){ /* infinity or NaN */
569 if (((hx&0x000fffff)|y.i[LO])!=0)
570 return x+x; /* NaN */
571 else {/* otherwise the result should be +infty */
572 return (y.d);
573 }
574 }
575 if (x > max_input_csh.d)
576 return largest_double * largest_double; /* overflow */
577 if (x < -max_input_csh.d)
578 return -largest_double * largest_double; /* overflow */
579 }
580
581 if (hx<0x3e500000) {
582 return x; /* exact, we should find some way of raising the inexact flag */
583 }
584
585
586 do_sinh(x, &rh, &rl);
587
588 if (rh == (rh + (rl * round_cst_csh))) return rh;
589 else{
590 int exponent;
591 db_number res;
592 double resh, resm, resl;
593
594 do_sinh_accurate(&exponent, &resh,&resm, &resl, x);
595 RoundToNearest3(&(res.d), resh, resm, resl);
596
597 /* Now we have to set the exponent of res as exponent -1 (division
598 by 2). However, as res may sometimes end up infinite, we first
599 set the exponent to exponent -11 and then multiply by 2^10,
600 which will cater for overflow */
601 res.i[HI] += (exponent-11) << 20;
602 return 1024. * res.d;
603 }
604
605 }
606
607
608
sinh_ru(double x)609 double sinh_ru(double x){
610 db_number y;
611 double rh, rl;
612
613
614 y.d = x;
615 y.i[HI] = y.i[HI] & 0x7FFFFFFF; /* to get the absolute value of the input */
616 if ((y.i[HI] & 0x7FF00000) >= (0x7FF00000)) { /*particular cases : QNaN, SNaN, +- oo*/
617 return (x);
618 }
619 if (y.d > max_input_csh.d) { /* out of range */
620 if(x>0) {
621 y.i[LO] = 0; y.i[HI] = 0x7FF00000; return (y.d);
622 }
623 else {
624 y.i[LO] = 0xFFFFFFFF; y.i[HI] = 0xFFEFFFFF ; return (y.d);
625 }
626 }
627
628 if(y.i[HI] < 0x3e500000) /* 2^(-26) */
629 { /* Add one ulp if x positive */
630 if(x>0) {
631 y.l++;
632 return y.d;
633 }
634 else
635 return x;
636 }
637
638 do_sinh(x, &rh, &rl);
639
640 TEST_AND_RETURN_RU(rh, rl, maxepsilon_csh);
641
642 /* if the previous block didn't return a value, launch accurate phase */
643 {
644 int exponent;
645 db_number res;
646 double resh, resm, resl;
647
648 do_sinh_accurate(&exponent, &resh,&resm, &resl, x);
649 RoundUpwards3(&(res.d), resh,resm,resl);
650
651 /* Now we have to set the exponent of res as exponent -1 (division
652 by 2). However, as res may sometimes end up infinite, we first
653 set the exponent to exponent -11 and then multiply by 2^10,
654 which will cater for overflow */
655 res.i[HI] += (exponent-11) << 20;
656 return 1024. * res.d;
657 }
658 }
659
660
sinh_rd(double x)661 double sinh_rd(double x){
662 db_number y;
663 double rh, rl;
664
665 y.d = x;
666 y.i[HI] = y.i[HI] & 0x7FFFFFFF; /* to get the absolute value of the input */
667 if ((y.i[HI] & 0x7FF00000) >= (0x7FF00000)) { /*particular cases : QNaN, SNaN, +- oo*/
668 y.d = x;
669 return (y.d);
670 }
671 if (y.d > max_input_csh.d) { /* out of range */
672 if(x>0) {
673 y.i[LO] = 0xFFFFFFFF; y.i[HI] = 0x7FEFFFFF ; return (y.d);
674 }
675 else {
676 y.i[LO] = 0; y.i[HI] = 0xFFF00000; return (y.d);
677 }
678 }
679 if(y.i[HI] < 0x3e500000) /* 2^(-26) */
680 { /* Add one ulp and restore the sign if x negative */
681 if(x<0){
682 y.l = (y.l+1);
683 return -y.d;
684 }
685 else
686 return x;
687 }
688 do_sinh(x, &rh, &rl);
689
690 TEST_AND_RETURN_RD(rh, rl, maxepsilon_csh);
691
692 /* if the previous block didn't return a value, launch accurate phase */
693 {
694 int exponent;
695 db_number res;
696 double resh, resm, resl;
697
698 do_sinh_accurate(&exponent, &resh,&resm, &resl, x);
699 RoundDownwards3(&(res.d), resh,resm,resl);
700
701 /* Now we have to set the exponent of res as exponent -1 (division
702 by 2). However, as res may sometimes end up infinite, we first
703 set the exponent to exponent -11 and then multiply by 2^10,
704 which will cater for overflow */
705 res.i[HI] += (exponent-11) << 20;
706 return 1024. * res.d;
707 }
708 }
709
710
711
712
sinh_rz(double x)713 double sinh_rz(double x){
714 if( x > 0) {
715 return(sinh_rd(x));
716 }
717 else {
718 return(sinh_ru(x));
719 }
720 }
721
722