Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dp_tlong.c
Go to the documentation of this file.
1 /* IEEE754 floating point arithmetic
2  * double precision: common utilities
3  */
4 /*
5  * MIPS floating point support
6  * Copyright (C) 1994-2000 Algorithmics Ltd.
7  *
8  * ########################################################################
9  *
10  * This program is free software; you can distribute it and/or modify it
11  * under the terms of the GNU General Public License (Version 2) as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17  * for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * ########################################################################
24  */
25 
26 
27 #include "ieee754dp.h"
28 
29 s64 ieee754dp_tlong(ieee754dp x)
30 {
31  COMPXDP;
32 
33  CLEARCX;
34 
35  EXPLODEXDP;
36  FLUSHXDP;
37 
38  switch (xc) {
39  case IEEE754_CLASS_SNAN:
40  case IEEE754_CLASS_QNAN:
41  case IEEE754_CLASS_INF:
43  return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
44  case IEEE754_CLASS_ZERO:
45  return 0;
47  case IEEE754_CLASS_NORM:
48  break;
49  }
50  if (xe >= 63) {
51  /* look for valid corner case */
52  if (xe == 63 && xs && xm == DP_HIDDEN_BIT)
53  return -0x8000000000000000LL;
54  /* Set invalid. We will only use overflow for floating
55  point overflow */
57  return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
58  }
59  /* oh gawd */
60  if (xe > DP_MBITS) {
61  xm <<= xe - DP_MBITS;
62  } else if (xe < DP_MBITS) {
63  u64 residue;
64  int round;
65  int sticky;
66  int odd;
67 
68  if (xe < -1) {
69  residue = xm;
70  round = 0;
71  sticky = residue != 0;
72  xm = 0;
73  } else {
74  /* Shifting a u64 64 times does not work,
75  * so we do it in two steps. Be aware that xe
76  * may be -1 */
77  residue = xm << (xe + 1);
78  residue <<= 63 - DP_MBITS;
79  round = (residue >> 63) != 0;
80  sticky = (residue << 1) != 0;
81  xm >>= DP_MBITS - xe;
82  }
83  odd = (xm & 0x1) != 0x0;
84  switch (ieee754_csr.rm) {
85  case IEEE754_RN:
86  if (round && (sticky || odd))
87  xm++;
88  break;
89  case IEEE754_RZ:
90  break;
91  case IEEE754_RU: /* toward +Infinity */
92  if ((round || sticky) && !xs)
93  xm++;
94  break;
95  case IEEE754_RD: /* toward -Infinity */
96  if ((round || sticky) && xs)
97  xm++;
98  break;
99  }
100  if ((xm >> 63) != 0) {
101  /* This can happen after rounding */
103  return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
104  }
105  if (round || sticky)
107  }
108  if (xs)
109  return -xm;
110  else
111  return xm;
112 }
113 
114 
116 {
117  ieee754dp hb = ieee754dp_1e63();
118 
119  /* what if x < 0 ?? */
120  if (ieee754dp_lt(x, hb))
121  return (u64) ieee754dp_tlong(x);
122 
123  return (u64) ieee754dp_tlong(ieee754dp_sub(x, hb)) |
124  (1ULL << 63);
125 }