Annotation of sys/arch/hppa/spmath/dfrem.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: dfrem.c,v 1.5 2002/05/07 22:19:30 mickey Exp $ */
2: /*
3: (c) Copyright 1986 HEWLETT-PACKARD COMPANY
4: To anyone who acknowledges that this file is provided "AS IS"
5: without any express or implied warranty:
6: permission to use, copy, modify, and distribute this file
7: for any purpose is hereby granted without fee, provided that
8: the above copyright notice and this notice appears in all
9: copies, and that the name of Hewlett-Packard Company not be
10: used in advertising or publicity pertaining to distribution
11: of the software without specific, written prior permission.
12: Hewlett-Packard Company makes no representations about the
13: suitability of this software for any purpose.
14: */
15: /* @(#)dfrem.c: Revision: 1.7.88.1 Date: 93/12/07 15:05:43 */
16:
17: #include "float.h"
18: #include "dbl_float.h"
19:
20: /*
21: * Double Precision Floating-point Remainder
22: */
23: int
24: dbl_frem(srcptr1,srcptr2,dstptr,status)
25: dbl_floating_point *srcptr1, *srcptr2, *dstptr;
26: unsigned int *status;
27: {
28: register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
29: register unsigned int resultp1, resultp2;
30: register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
31: register int roundup = FALSE;
32:
33: Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
34: Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
35: /*
36: * check first operand for NaN's or infinity
37: */
38: if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
39: if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
40: if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
41: /* invalid since first operand is infinity */
42: if (Is_invalidtrap_enabled())
43: return(INVALIDEXCEPTION);
44: Set_invalidflag();
45: Dbl_makequietnan(resultp1,resultp2);
46: Dbl_copytoptr(resultp1,resultp2,dstptr);
47: return(NOEXCEPTION);
48: }
49: }
50: else {
51: /*
52: * is NaN; signaling or quiet?
53: */
54: if (Dbl_isone_signaling(opnd1p1)) {
55: /* trap if INVALIDTRAP enabled */
56: if (Is_invalidtrap_enabled())
57: return(INVALIDEXCEPTION);
58: /* make NaN quiet */
59: Set_invalidflag();
60: Dbl_set_quiet(opnd1p1);
61: }
62: /*
63: * is second operand a signaling NaN?
64: */
65: else if (Dbl_is_signalingnan(opnd2p1)) {
66: /* trap if INVALIDTRAP enabled */
67: if (Is_invalidtrap_enabled())
68: return(INVALIDEXCEPTION);
69: /* make NaN quiet */
70: Set_invalidflag();
71: Dbl_set_quiet(opnd2p1);
72: Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
73: return(NOEXCEPTION);
74: }
75: /*
76: * return quiet NaN
77: */
78: Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
79: return(NOEXCEPTION);
80: }
81: }
82: /*
83: * check second operand for NaN's or infinity
84: */
85: if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
86: if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
87: /*
88: * return first operand
89: */
90: Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
91: return(NOEXCEPTION);
92: }
93: /*
94: * is NaN; signaling or quiet?
95: */
96: if (Dbl_isone_signaling(opnd2p1)) {
97: /* trap if INVALIDTRAP enabled */
98: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
99: /* make NaN quiet */
100: Set_invalidflag();
101: Dbl_set_quiet(opnd2p1);
102: }
103: /*
104: * return quiet NaN
105: */
106: Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
107: return(NOEXCEPTION);
108: }
109: /*
110: * check second operand for zero
111: */
112: if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
113: /* invalid since second operand is zero */
114: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
115: Set_invalidflag();
116: Dbl_makequietnan(resultp1,resultp2);
117: Dbl_copytoptr(resultp1,resultp2,dstptr);
118: return(NOEXCEPTION);
119: }
120:
121: /*
122: * get sign of result
123: */
124: resultp1 = opnd1p1;
125:
126: /*
127: * check for denormalized operands
128: */
129: if (opnd1_exponent == 0) {
130: /* check for zero */
131: if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
132: Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
133: return(NOEXCEPTION);
134: }
135: /* normalize, then continue */
136: opnd1_exponent = 1;
137: Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
138: }
139: else {
140: Dbl_clear_signexponent_set_hidden(opnd1p1);
141: }
142: if (opnd2_exponent == 0) {
143: /* normalize, then continue */
144: opnd2_exponent = 1;
145: Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
146: }
147: else {
148: Dbl_clear_signexponent_set_hidden(opnd2p1);
149: }
150:
151: /* find result exponent and divide step loop count */
152: dest_exponent = opnd2_exponent - 1;
153: stepcount = opnd1_exponent - opnd2_exponent;
154:
155: /*
156: * check for opnd1/opnd2 < 1
157: */
158: if (stepcount < 0) {
159: /*
160: * check for opnd1/opnd2 > 1/2
161: *
162: * In this case n will round to 1, so
163: * r = opnd1 - opnd2
164: */
165: if (stepcount == -1 &&
166: Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
167: /* set sign */
168: Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
169: /* align opnd2 with opnd1 */
170: Dbl_leftshiftby1(opnd2p1,opnd2p2);
171: Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
172: opnd2p1,opnd2p2);
173: /* now normalize */
174: while (Dbl_iszero_hidden(opnd2p1)) {
175: Dbl_leftshiftby1(opnd2p1,opnd2p2);
176: dest_exponent--;
177: }
178: Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
179: goto testforunderflow;
180: }
181: /*
182: * opnd1/opnd2 <= 1/2
183: *
184: * In this case n will round to zero, so
185: * r = opnd1
186: */
187: Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
188: dest_exponent = opnd1_exponent;
189: goto testforunderflow;
190: }
191:
192: /*
193: * Generate result
194: *
195: * Do iterative subtract until remainder is less than operand 2.
196: */
197: while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
198: if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
199: Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
200: }
201: Dbl_leftshiftby1(opnd1p1,opnd1p2);
202: }
203: /*
204: * Do last subtract, then determine which way to round if remainder
205: * is exactly 1/2 of opnd2
206: */
207: if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
208: Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
209: roundup = TRUE;
210: }
211: if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
212: /* division is exact, remainder is zero */
213: Dbl_setzero_exponentmantissa(resultp1,resultp2);
214: Dbl_copytoptr(resultp1,resultp2,dstptr);
215: return(NOEXCEPTION);
216: }
217:
218: /*
219: * Check for cases where opnd1/opnd2 < n
220: *
221: * In this case the result's sign will be opposite that of
222: * opnd1. The mantissa also needs some correction.
223: */
224: Dbl_leftshiftby1(opnd1p1,opnd1p2);
225: if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
226: Dbl_invert_sign(resultp1);
227: Dbl_leftshiftby1(opnd2p1,opnd2p2);
228: Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
229: }
230: /* check for remainder being exactly 1/2 of opnd2 */
231: else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) {
232: Dbl_invert_sign(resultp1);
233: }
234:
235: /* normalize result's mantissa */
236: while (Dbl_iszero_hidden(opnd1p1)) {
237: dest_exponent--;
238: Dbl_leftshiftby1(opnd1p1,opnd1p2);
239: }
240: Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
241:
242: /*
243: * Test for underflow
244: */
245: testforunderflow:
246: if (dest_exponent <= 0) {
247: /* trap if UNDERFLOWTRAP enabled */
248: if (Is_underflowtrap_enabled()) {
249: /*
250: * Adjust bias of result
251: */
252: Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
253: /* frem is always exact */
254: Dbl_copytoptr(resultp1,resultp2,dstptr);
255: return(UNDERFLOWEXCEPTION);
256: }
257: /*
258: * denormalize result or set to signed zero
259: */
260: if (dest_exponent >= (1 - DBL_P)) {
261: Dbl_rightshift_exponentmantissa(resultp1,resultp2,
262: 1-dest_exponent);
263: }
264: else {
265: Dbl_setzero_exponentmantissa(resultp1,resultp2);
266: }
267: }
268: else Dbl_set_exponent(resultp1,dest_exponent);
269: Dbl_copytoptr(resultp1,resultp2,dstptr);
270: return(NOEXCEPTION);
271: }
CVSweb