1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77#if HAVE_CONFIG_H
78#include <config.h>
79#endif
80
81/*
82**
83**  NAME:
84**
85**      round.c.h
86**
87**  FACILITY:
88**
89**      IDL Stub Runtime Support
90**
91**  ABSTRACT:
92**
93**      This module is an include file.
94**
95**	This module rounds CVT floating point data to any specified position.
96**	Any of the following rounding modes can be applied:
97**
98**      Note: None of the following implementations ever perform true truncation
99**            on their values.  Whenever truncation becomes necessary - either
100**            by being specified directly or by being required indirectly
101**            through rounding - values are actually left untouched.  Users
102**            of this routine must zero out fractional fields themselves if
103**            true truncation is needed.
104**
105**         VAX ROUNDING
106**
107**              Input data are rounded such that the representable value nearest
108**              the infinitely precise result is delivered; if two representable
109**              values are equally near, the one greatest in magnitude is
110**              delivered.
111**
112**         ROUND TO NEAREST
113**
114**              Input data are rounded such that the representable value nearest
115**              the infinitely precise result is delivered; if two representable
116**              values are equally near, the one with its least significant bit
117**              zero is delivered.
118**
119**         ROUND TO POSITIVE INFINITY
120**
121**              Input data are rounded such that the representable value closest
122**              to and no less than the infinitely precise result is delivered.
123**
124**         ROUND TO NEGATIVE INFINITY
125**
126**              Input data are rounded such that the representable value closest
127**              to and no greater than the infinitely precise result is
128**              delivered.
129**
130**         TRUNCATION (ROUND TOWARDS ZERO)
131**
132**              True truncation is not implemented here.  Input values are
133**              delivered in their original, untouched form.
134**
135**              A definition of "true" truncation follows:  Truncation, or
136**              rounding towards zero, implies input data are rounded such
137**              that the representable value closest to and no greater in
138**              magnitude than the infinitely precise result is delivered.
139**
140**  VERSION: DCE 1.0
141**
142*/
143
144/*
145**
146**  Implicit input/output:
147**
148**	r			On input, a valid CVT floating point number.
149**				On output, a rounded representation of the
150**				input.
151**
152**
153**  Implicit input:
154**
155**	round_bit_position	An integer specifying the position to round to.
156**				0 <= round_bit_position <= 127.
157**
158**				Note: Valid CVT mantissa bits are addressed as 1
159**				through 128.  Accordingly, specifying 0 as a
160**				position to round to implies an exponent
161**				increase whenever rounding occurs.  As for
162**				truncation: truncation allways leaves a CVT
163**				number untouched.
164**
165**	options			A valid CVT options bit mask in which at least
166**				one, and only one, CVT rounding mode is
167**				specified.  If no rounding mode is specified,
168**				results are unpredictable.  Rounding is
169**				performed in accordance with this mask.
170**
171**	i			An uninitialized integer used for indexing.
172**
173**
174**  Note: for efficiency this routine performs no explicit error checking.
175**
176*/
177
178{
179  int roundup, more_bits;
180  unsigned32  bit_mask;
181
182      /* Check TRUNCATE option */
183
184  if ( ! (options & CVT_C_TRUNCATE) ) {
185
186           /* Determine which word the round bit resides in */
187
188      i = (round_bit_position >> 5) + 1;
189
190           /* Create a mask isolating the round bit */
191
192      bit_mask = 0x1 << (31 - (round_bit_position & 0x1FL));
193
194           /* Check VAX ROUNDING option */
195
196      if (options & CVT_C_VAX_ROUNDING)
197          roundup = r[i] & bit_mask;
198
199      else {
200          roundup = 0;
201          switch ( r[i] & bit_mask ) {
202
203                /* If round bit is clear, and ROUND TO NEAREST option */
204                /* is selected we truncate */
205
206          case  0 : if (options & CVT_C_ROUND_TO_NEAREST)
207                      break;
208
209                /* Otherwise, make note of wheather there are any bits set */
210                /* after the round bit, and then check the remaining cases */
211
212          default : if ( ! (more_bits = r[i] & (bit_mask - 1)) )
213                      switch ( i ) {
214                        case  1 : more_bits = r[2];
215                        case  2 : more_bits |= r[3];
216                        case  3 : more_bits |= r[4];
217                        default : break;
218                      }
219
220                /* Re-check ROUND TO NEAREST option.  NOTE: if we've reached  */
221                /* this point and ROUND TO NEAREST has been selected, the     */
222                /* round bit is set. */
223
224                    if (options & CVT_C_ROUND_TO_NEAREST) {
225                        if ( ! ( roundup = more_bits ) )
226								{
227                            if ( bit_mask << 1 )
228                               roundup = r[i] & (bit_mask << 1);
229                            else if (i != 1)
230                               roundup = r[i-1] & 1;
231								}
232
233                /* Check ROUND TO POSITIVE INFINITY option */
234
235                    } else if (options & CVT_C_ROUND_TO_POS) {
236                        if ( !(r[U_R_FLAGS] & U_R_NEGATIVE) )
237                          roundup = (r[i] & bit_mask) | more_bits;
238
239                /* Check ROUND TO NEGITIVE INFINITY option */
240
241                    } else if (r[U_R_FLAGS] & U_R_NEGATIVE)
242                        roundup = (r[i] & bit_mask) | more_bits;
243          }
244      }
245
246      if ( roundup ) {          /* Perform rounding if necessary */
247
248               /* Add 1 at round position */
249
250         bit_mask <<= 1;
251         r[i] = (r[i] & ~(bit_mask - 1)) + bit_mask;
252
253               /* Propagate any carry */
254
255	 while ( ! r[i] )
256           r[--i] += 1;
257
258               /* If carry reaches exponent MSB gets zeroed and must be reset */
259
260         if ( ! i )
261           r[1] = 0x80000000L;
262      }
263  }
264}
265