Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
frnd.c
Go to the documentation of this file.
1 /*
2  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3  *
4  * Floating-point emulation code
5  * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <[email protected]>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 /*
22  * BEGIN_DESC
23  *
24  * Purpose:
25  * Single Floating-point Round to Integer
26  * Double Floating-point Round to Integer
27  * Quad Floating-point Round to Integer (returns unimplemented)
28  *
29  * External Interfaces:
30  * dbl_frnd(srcptr,nullptr,dstptr,status)
31  * sgl_frnd(srcptr,nullptr,dstptr,status)
32  *
33  * END_DESC
34 */
35 
36 
37 #include "float.h"
38 #include "sgl_float.h"
39 #include "dbl_float.h"
40 #include "cnv_float.h"
41 
42 /*
43  * Single Floating-point Round to Integer
44  */
45 
46 /*ARGSUSED*/
47 int
49  unsigned int *nullptr,
50  sgl_floating_point *dstptr,
51  unsigned int *status)
52 {
53  register unsigned int src, result;
54  register int src_exponent;
55  register boolean inexact = FALSE;
56 
57  src = *srcptr;
58  /*
59  * check source operand for NaN or infinity
60  */
61  if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
62  /*
63  * is signaling NaN?
64  */
65  if (Sgl_isone_signaling(src)) {
66  /* trap if INVALIDTRAP enabled */
68  /* make NaN quiet */
70  Sgl_set_quiet(src);
71  }
72  /*
73  * return quiet NaN or infinity
74  */
75  *dstptr = src;
76  return(NOEXCEPTION);
77  }
78  /*
79  * Need to round?
80  */
81  if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
82  *dstptr = src;
83  return(NOEXCEPTION);
84  }
85  /*
86  * Generate result
87  */
88  if (src_exponent >= 0) {
90  result = src;
91  Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
92  /* check for inexact */
93  if (Sgl_isinexact_to_fix(src,src_exponent)) {
94  inexact = TRUE;
95  /* round result */
96  switch (Rounding_mode()) {
97  case ROUNDPLUS:
98  if (Sgl_iszero_sign(src)) Sgl_increment(result);
99  break;
100  case ROUNDMINUS:
101  if (Sgl_isone_sign(src)) Sgl_increment(result);
102  break;
103  case ROUNDNEAREST:
104  if (Sgl_isone_roundbit(src,src_exponent))
105  if (Sgl_isone_stickybit(src,src_exponent)
106  || (Sgl_isone_lowmantissa(result)))
107  Sgl_increment(result);
108  }
109  }
110  Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
111  if (Sgl_isone_hiddenoverflow(result))
112  Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
113  else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
114  }
115  else {
116  result = src; /* set sign */
118  /* check for inexact */
120  inexact = TRUE;
121  /* round result */
122  switch (Rounding_mode()) {
123  case ROUNDPLUS:
124  if (Sgl_iszero_sign(src))
125  Sgl_set_exponent(result,SGL_BIAS);
126  break;
127  case ROUNDMINUS:
128  if (Sgl_isone_sign(src))
129  Sgl_set_exponent(result,SGL_BIAS);
130  break;
131  case ROUNDNEAREST:
132  if (src_exponent == -1)
133  if (Sgl_isnotzero_mantissa(src))
134  Sgl_set_exponent(result,SGL_BIAS);
135  }
136  }
137  }
138  *dstptr = result;
139  if (inexact) {
141  else Set_inexactflag();
142  }
143  return(NOEXCEPTION);
144 }
145 
146 /*
147  * Double Floating-point Round to Integer
148  */
149 
150 /*ARGSUSED*/
151 int
153  dbl_floating_point *srcptr,
154  unsigned int *nullptr,
155  dbl_floating_point *dstptr,
156  unsigned int *status)
157 {
158  register unsigned int srcp1, srcp2, resultp1, resultp2;
159  register int src_exponent;
160  register boolean inexact = FALSE;
161 
162  Dbl_copyfromptr(srcptr,srcp1,srcp2);
163  /*
164  * check source operand for NaN or infinity
165  */
166  if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
167  /*
168  * is signaling NaN?
169  */
170  if (Dbl_isone_signaling(srcp1)) {
171  /* trap if INVALIDTRAP enabled */
173  /* make NaN quiet */
174  Set_invalidflag();
175  Dbl_set_quiet(srcp1);
176  }
177  /*
178  * return quiet NaN or infinity
179  */
180  Dbl_copytoptr(srcp1,srcp2,dstptr);
181  return(NOEXCEPTION);
182  }
183  /*
184  * Need to round?
185  */
186  if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
187  Dbl_copytoptr(srcp1,srcp2,dstptr);
188  return(NOEXCEPTION);
189  }
190  /*
191  * Generate result
192  */
193  if (src_exponent >= 0) {
195  resultp1 = srcp1;
196  resultp2 = srcp2;
197  Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
198  /* check for inexact */
199  if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
200  inexact = TRUE;
201  /* round result */
202  switch (Rounding_mode()) {
203  case ROUNDPLUS:
204  if (Dbl_iszero_sign(srcp1))
205  Dbl_increment(resultp1,resultp2);
206  break;
207  case ROUNDMINUS:
208  if (Dbl_isone_sign(srcp1))
209  Dbl_increment(resultp1,resultp2);
210  break;
211  case ROUNDNEAREST:
212  if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
213  if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
214  || (Dbl_isone_lowmantissap2(resultp2)))
215  Dbl_increment(resultp1,resultp2);
216  }
217  }
218  Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
219  if (Dbl_isone_hiddenoverflow(resultp1))
220  Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
221  else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
222  }
223  else {
224  resultp1 = srcp1; /* set sign */
225  Dbl_setzero_exponentmantissa(resultp1,resultp2);
226  /* check for inexact */
227  if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
228  inexact = TRUE;
229  /* round result */
230  switch (Rounding_mode()) {
231  case ROUNDPLUS:
232  if (Dbl_iszero_sign(srcp1))
233  Dbl_set_exponent(resultp1,DBL_BIAS);
234  break;
235  case ROUNDMINUS:
236  if (Dbl_isone_sign(srcp1))
237  Dbl_set_exponent(resultp1,DBL_BIAS);
238  break;
239  case ROUNDNEAREST:
240  if (src_exponent == -1)
241  if (Dbl_isnotzero_mantissa(srcp1,srcp2))
242  Dbl_set_exponent(resultp1,DBL_BIAS);
243  }
244  }
245  }
246  Dbl_copytoptr(resultp1,resultp2,dstptr);
247  if (inexact) {
249  else Set_inexactflag();
250  }
251  return(NOEXCEPTION);
252 }