Annotation of sys/arch/hppa/spmath/sfrem.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sfrem.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: /* @(#)sfrem.c: Revision: 1.7.88.1 Date: 93/12/07 15:07:10 */
16:
17: #include "float.h"
18: #include "sgl_float.h"
19:
20: /*
21: * Single Precision Floating-point Remainder
22: */
23: int
24: sgl_frem(srcptr1,srcptr2,dstptr,status)
25: sgl_floating_point *srcptr1, *srcptr2, *dstptr;
26: unsigned int *status;
27: {
28: register unsigned int opnd1, opnd2, result;
29: register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
30: register int roundup = FALSE;
31:
32: opnd1 = *srcptr1;
33: opnd2 = *srcptr2;
34: /*
35: * check first operand for NaN's or infinity
36: */
37: if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) {
38: if (Sgl_iszero_mantissa(opnd1)) {
39: if (Sgl_isnotnan(opnd2)) {
40: /* invalid since first operand is infinity */
41: if (Is_invalidtrap_enabled())
42: return(INVALIDEXCEPTION);
43: Set_invalidflag();
44: Sgl_makequietnan(result);
45: *dstptr = result;
46: return(NOEXCEPTION);
47: }
48: }
49: else {
50: /*
51: * is NaN; signaling or quiet?
52: */
53: if (Sgl_isone_signaling(opnd1)) {
54: /* trap if INVALIDTRAP enabled */
55: if (Is_invalidtrap_enabled())
56: return(INVALIDEXCEPTION);
57: /* make NaN quiet */
58: Set_invalidflag();
59: Sgl_set_quiet(opnd1);
60: }
61: /*
62: * is second operand a signaling NaN?
63: */
64: else if (Sgl_is_signalingnan(opnd2)) {
65: /* trap if INVALIDTRAP enabled */
66: if (Is_invalidtrap_enabled())
67: return(INVALIDEXCEPTION);
68: /* make NaN quiet */
69: Set_invalidflag();
70: Sgl_set_quiet(opnd2);
71: *dstptr = opnd2;
72: return(NOEXCEPTION);
73: }
74: /*
75: * return quiet NaN
76: */
77: *dstptr = opnd1;
78: return(NOEXCEPTION);
79: }
80: }
81: /*
82: * check second operand for NaN's or infinity
83: */
84: if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) {
85: if (Sgl_iszero_mantissa(opnd2)) {
86: /*
87: * return first operand
88: */
89: *dstptr = opnd1;
90: return(NOEXCEPTION);
91: }
92: /*
93: * is NaN; signaling or quiet?
94: */
95: if (Sgl_isone_signaling(opnd2)) {
96: /* trap if INVALIDTRAP enabled */
97: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
98: /* make NaN quiet */
99: Set_invalidflag();
100: Sgl_set_quiet(opnd2);
101: }
102: /*
103: * return quiet NaN
104: */
105: *dstptr = opnd2;
106: return(NOEXCEPTION);
107: }
108: /*
109: * check second operand for zero
110: */
111: if (Sgl_iszero_exponentmantissa(opnd2)) {
112: /* invalid since second operand is zero */
113: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
114: Set_invalidflag();
115: Sgl_makequietnan(result);
116: *dstptr = result;
117: return(NOEXCEPTION);
118: }
119:
120: /*
121: * get sign of result
122: */
123: result = opnd1;
124:
125: /*
126: * check for denormalized operands
127: */
128: if (opnd1_exponent == 0) {
129: /* check for zero */
130: if (Sgl_iszero_mantissa(opnd1)) {
131: *dstptr = opnd1;
132: return(NOEXCEPTION);
133: }
134: /* normalize, then continue */
135: opnd1_exponent = 1;
136: Sgl_normalize(opnd1,opnd1_exponent);
137: }
138: else {
139: Sgl_clear_signexponent_set_hidden(opnd1);
140: }
141: if (opnd2_exponent == 0) {
142: /* normalize, then continue */
143: opnd2_exponent = 1;
144: Sgl_normalize(opnd2,opnd2_exponent);
145: }
146: else {
147: Sgl_clear_signexponent_set_hidden(opnd2);
148: }
149:
150: /* find result exponent and divide step loop count */
151: dest_exponent = opnd2_exponent - 1;
152: stepcount = opnd1_exponent - opnd2_exponent;
153:
154: /*
155: * check for opnd1/opnd2 < 1
156: */
157: if (stepcount < 0) {
158: /*
159: * check for opnd1/opnd2 > 1/2
160: *
161: * In this case n will round to 1, so
162: * r = opnd1 - opnd2
163: */
164: if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) {
165: Sgl_all(result) = ~Sgl_all(result); /* set sign */
166: /* align opnd2 with opnd1 */
167: Sgl_leftshiftby1(opnd2);
168: Sgl_subtract(opnd2,opnd1,opnd2);
169: /* now normalize */
170: while (Sgl_iszero_hidden(opnd2)) {
171: Sgl_leftshiftby1(opnd2);
172: dest_exponent--;
173: }
174: Sgl_set_exponentmantissa(result,opnd2);
175: goto testforunderflow;
176: }
177: /*
178: * opnd1/opnd2 <= 1/2
179: *
180: * In this case n will round to zero, so
181: * r = opnd1
182: */
183: Sgl_set_exponentmantissa(result,opnd1);
184: dest_exponent = opnd1_exponent;
185: goto testforunderflow;
186: }
187:
188: /*
189: * Generate result
190: *
191: * Do iterative subtract until remainder is less than operand 2.
192: */
193: while (stepcount-- > 0 && Sgl_all(opnd1)) {
194: if (Sgl_isnotlessthan(opnd1,opnd2))
195: Sgl_subtract(opnd1,opnd2,opnd1);
196: Sgl_leftshiftby1(opnd1);
197: }
198: /*
199: * Do last subtract, then determine which way to round if remainder
200: * is exactly 1/2 of opnd2
201: */
202: if (Sgl_isnotlessthan(opnd1,opnd2)) {
203: Sgl_subtract(opnd1,opnd2,opnd1);
204: roundup = TRUE;
205: }
206: if (stepcount > 0 || Sgl_iszero(opnd1)) {
207: /* division is exact, remainder is zero */
208: Sgl_setzero_exponentmantissa(result);
209: *dstptr = result;
210: return(NOEXCEPTION);
211: }
212:
213: /*
214: * Check for cases where opnd1/opnd2 < n
215: *
216: * In this case the result's sign will be opposite that of
217: * opnd1. The mantissa also needs some correction.
218: */
219: Sgl_leftshiftby1(opnd1);
220: if (Sgl_isgreaterthan(opnd1,opnd2)) {
221: Sgl_invert_sign(result);
222: Sgl_subtract((opnd2<<1),opnd1,opnd1);
223: }
224: /* check for remainder being exactly 1/2 of opnd2 */
225: else if (Sgl_isequal(opnd1,opnd2) && roundup) {
226: Sgl_invert_sign(result);
227: }
228:
229: /* normalize result's mantissa */
230: while (Sgl_iszero_hidden(opnd1)) {
231: dest_exponent--;
232: Sgl_leftshiftby1(opnd1);
233: }
234: Sgl_set_exponentmantissa(result,opnd1);
235:
236: /*
237: * Test for underflow
238: */
239: testforunderflow:
240: if (dest_exponent <= 0) {
241: /* trap if UNDERFLOWTRAP enabled */
242: if (Is_underflowtrap_enabled()) {
243: /*
244: * Adjust bias of result
245: */
246: Sgl_setwrapped_exponent(result,dest_exponent,unfl);
247: *dstptr = result;
248: /* frem is always exact */
249: return(UNDERFLOWEXCEPTION);
250: }
251: /*
252: * denormalize result or set to signed zero
253: */
254: if (dest_exponent >= (1 - SGL_P)) {
255: Sgl_rightshift_exponentmantissa(result,1-dest_exponent);
256: } else {
257: Sgl_setzero_exponentmantissa(result);
258: }
259: }
260: else Sgl_set_exponent(result,dest_exponent);
261: *dstptr = result;
262: return(NOEXCEPTION);
263: }
CVSweb