Annotation of sys/arch/hppa/spmath/dfsub.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: dfsub.c,v 1.7 2002/11/29 09:27:34 deraadt 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: /* @(#)dfsub.c: Revision: 2.8.88.1 Date: 93/12/07 15:05:48 */
16:
17: #include "float.h"
18: #include "dbl_float.h"
19:
20: /*
21: * Double_subtract: subtract two double precision values.
22: */
23: int
24: dbl_fsub(leftptr, rightptr, dstptr, status)
25: dbl_floating_point *leftptr, *rightptr, *dstptr;
26: unsigned int *status;
27: {
28: register unsigned int signless_upper_left, signless_upper_right, save;
29: register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
30: register unsigned int resultp1 = 0, resultp2 = 0;
31:
32: register int result_exponent, right_exponent, diff_exponent;
33: register int sign_save, jumpsize;
34: register int inexact = FALSE, underflowtrap;
35:
36: /* Create local copies of the numbers */
37: Dbl_copyfromptr(leftptr,leftp1,leftp2);
38: Dbl_copyfromptr(rightptr,rightp1,rightp2);
39:
40: /* A zero "save" helps discover equal operands (for later), *
41: * and is used in swapping operands (if needed). */
42: Dbl_xortointp1(leftp1,rightp1,/*to*/save);
43:
44: /*
45: * check first operand for NaN's or infinity
46: */
47: if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
48: {
49: if (Dbl_iszero_mantissa(leftp1,leftp2))
50: {
51: if (Dbl_isnotnan(rightp1,rightp2))
52: {
53: if (Dbl_isinfinity(rightp1,rightp2) && save==0)
54: {
55: /*
56: * invalid since operands are same signed infinity's
57: */
58: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
59: Set_invalidflag();
60: Dbl_makequietnan(resultp1,resultp2);
61: Dbl_copytoptr(resultp1,resultp2,dstptr);
62: return(NOEXCEPTION);
63: }
64: /*
65: * return infinity
66: */
67: Dbl_copytoptr(leftp1,leftp2,dstptr);
68: return(NOEXCEPTION);
69: }
70: }
71: else
72: {
73: /*
74: * is NaN; signaling or quiet?
75: */
76: if (Dbl_isone_signaling(leftp1))
77: {
78: /* trap if INVALIDTRAP enabled */
79: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
80: /* make NaN quiet */
81: Set_invalidflag();
82: Dbl_set_quiet(leftp1);
83: }
84: /*
85: * is second operand a signaling NaN?
86: */
87: else if (Dbl_is_signalingnan(rightp1))
88: {
89: /* trap if INVALIDTRAP enabled */
90: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
91: /* make NaN quiet */
92: Set_invalidflag();
93: Dbl_set_quiet(rightp1);
94: Dbl_copytoptr(rightp1,rightp2,dstptr);
95: return(NOEXCEPTION);
96: }
97: /*
98: * return quiet NaN
99: */
100: Dbl_copytoptr(leftp1,leftp2,dstptr);
101: return(NOEXCEPTION);
102: }
103: } /* End left NaN or Infinity processing */
104: /*
105: * check second operand for NaN's or infinity
106: */
107: if (Dbl_isinfinity_exponent(rightp1))
108: {
109: if (Dbl_iszero_mantissa(rightp1,rightp2))
110: {
111: /* return infinity */
112: Dbl_invert_sign(rightp1);
113: Dbl_copytoptr(rightp1,rightp2,dstptr);
114: return(NOEXCEPTION);
115: }
116: /*
117: * is NaN; signaling or quiet?
118: */
119: if (Dbl_isone_signaling(rightp1))
120: {
121: /* trap if INVALIDTRAP enabled */
122: if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
123: /* make NaN quiet */
124: Set_invalidflag();
125: Dbl_set_quiet(rightp1);
126: }
127: /*
128: * return quiet NaN
129: */
130: Dbl_copytoptr(rightp1,rightp2,dstptr);
131: return(NOEXCEPTION);
132: } /* End right NaN or Infinity processing */
133:
134: /* Invariant: Must be dealing with finite numbers */
135:
136: /* Compare operands by removing the sign */
137: Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
138: Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
139:
140: /* sign difference selects add or sub operation. */
141: if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
142: {
143: /* Set the left operand to the larger one by XOR swap *
144: * First finish the first word using "save" */
145: Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
146: Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
147: Dbl_swap_lower(leftp2,rightp2);
148: result_exponent = Dbl_exponent(leftp1);
149: Dbl_invert_sign(leftp1);
150: }
151: /* Invariant: left is not smaller than right. */
152:
153: if((right_exponent = Dbl_exponent(rightp1)) == 0)
154: {
155: /* Denormalized operands. First look for zeroes */
156: if(Dbl_iszero_mantissa(rightp1,rightp2))
157: {
158: /* right is zero */
159: if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
160: {
161: /* Both operands are zeros */
162: Dbl_invert_sign(rightp1);
163: if(Is_rounding_mode(ROUNDMINUS))
164: {
165: Dbl_or_signs(leftp1,/*with*/rightp1);
166: }
167: else
168: {
169: Dbl_and_signs(leftp1,/*with*/rightp1);
170: }
171: }
172: else
173: {
174: /* Left is not a zero and must be the result. Trapped
175: * underflows are signaled if left is denormalized. Result
176: * is always exact. */
177: if( (result_exponent == 0) && Is_underflowtrap_enabled() )
178: {
179: /* need to normalize results mantissa */
180: sign_save = Dbl_signextendedsign(leftp1);
181: Dbl_leftshiftby1(leftp1,leftp2);
182: Dbl_normalize(leftp1,leftp2,result_exponent);
183: Dbl_set_sign(leftp1,/*using*/sign_save);
184: Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
185: Dbl_copytoptr(leftp1,leftp2,dstptr);
186: /* inexact = FALSE */
187: return(UNDERFLOWEXCEPTION);
188: }
189: }
190: Dbl_copytoptr(leftp1,leftp2,dstptr);
191: return(NOEXCEPTION);
192: }
193:
194: /* Neither are zeroes */
195: Dbl_clear_sign(rightp1); /* Exponent is already cleared */
196: if(result_exponent == 0 )
197: {
198: /* Both operands are denormalized. The result must be exact
199: * and is simply calculated. A sum could become normalized and a
200: * difference could cancel to a true zero. */
201: if( (/*signed*/int) save >= 0 )
202: {
203: Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
204: /*into*/resultp1,resultp2);
205: if(Dbl_iszero_mantissa(resultp1,resultp2))
206: {
207: if(Is_rounding_mode(ROUNDMINUS))
208: {
209: Dbl_setone_sign(resultp1);
210: }
211: else
212: {
213: Dbl_setzero_sign(resultp1);
214: }
215: Dbl_copytoptr(resultp1,resultp2,dstptr);
216: return(NOEXCEPTION);
217: }
218: }
219: else
220: {
221: Dbl_addition(leftp1,leftp2,rightp1,rightp2,
222: /*into*/resultp1,resultp2);
223: if(Dbl_isone_hidden(resultp1))
224: {
225: Dbl_copytoptr(resultp1,resultp2,dstptr);
226: return(NOEXCEPTION);
227: }
228: }
229: if(Is_underflowtrap_enabled())
230: {
231: /* need to normalize result */
232: sign_save = Dbl_signextendedsign(resultp1);
233: Dbl_leftshiftby1(resultp1,resultp2);
234: Dbl_normalize(resultp1,resultp2,result_exponent);
235: Dbl_set_sign(resultp1,/*using*/sign_save);
236: Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
237: Dbl_copytoptr(resultp1,resultp2,dstptr);
238: /* inexact = FALSE */
239: return(UNDERFLOWEXCEPTION);
240: }
241: Dbl_copytoptr(resultp1,resultp2,dstptr);
242: return(NOEXCEPTION);
243: }
244: right_exponent = 1; /* Set exponent to reflect different bias
245: * with denomalized numbers. */
246: }
247: else
248: {
249: Dbl_clear_signexponent_set_hidden(rightp1);
250: }
251: Dbl_clear_exponent_set_hidden(leftp1);
252: diff_exponent = result_exponent - right_exponent;
253:
254: /*
255: * Special case alignment of operands that would force alignment
256: * beyond the extent of the extension. A further optimization
257: * could special case this but only reduces the path length for this
258: * infrequent case.
259: */
260: if(diff_exponent > DBL_THRESHOLD)
261: {
262: diff_exponent = DBL_THRESHOLD;
263: }
264:
265: /* Align right operand by shifting to right */
266: Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
267: /*and lower to*/extent);
268:
269: /* Treat sum and difference of the operands separately. */
270: if( (/*signed*/int) save >= 0 )
271: {
272: /*
273: * Difference of the two operands. Their can be no overflow. A
274: * borrow can occur out of the hidden bit and force a post
275: * normalization phase.
276: */
277: Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
278: /*with*/extent,/*into*/resultp1,resultp2);
279: if(Dbl_iszero_hidden(resultp1))
280: {
281: /* Handle normalization */
282: /* A straight forward algorithm would now shift the result
283: * and extension left until the hidden bit becomes one. Not
284: * all of the extension bits need participate in the shift.
285: * Only the two most significant bits (round and guard) are
286: * needed. If only a single shift is needed then the guard
287: * bit becomes a significant low order bit and the extension
288: * must participate in the rounding. If more than a single
289: * shift is needed, then all bits to the right of the guard
290: * bit are zeros, and the guard bit may or may not be zero. */
291: sign_save = Dbl_signextendedsign(resultp1);
292: Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
293:
294: /* Need to check for a zero result. The sign and exponent
295: * fields have already been zeroed. The more efficient test
296: * of the full object can be used.
297: */
298: if(Dbl_iszero(resultp1,resultp2))
299: /* Must have been "x-x" or "x+(-x)". */
300: {
301: if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
302: Dbl_copytoptr(resultp1,resultp2,dstptr);
303: return(NOEXCEPTION);
304: }
305: result_exponent--;
306: /* Look to see if normalization is finished. */
307: if(Dbl_isone_hidden(resultp1)) {
308: if(result_exponent==0) {
309: /* Denormalized, exponent should be zero. Left operand *
310: * was normalized, so extent (guard, round) was zero */
311: goto underflow;
312: } else {
313: /* No further normalization is needed. */
314: Dbl_set_sign(resultp1,/*using*/sign_save);
315: Ext_leftshiftby1(extent);
316: goto round;
317: }
318: }
319:
320: /* Check for denormalized, exponent should be zero. Left *
321: * operand was normalized, so extent (guard, round) was zero */
322: if(!(underflowtrap = Is_underflowtrap_enabled()) &&
323: result_exponent==0) goto underflow;
324:
325: /* Shift extension to complete one bit of normalization and
326: * update exponent. */
327: Ext_leftshiftby1(extent);
328:
329: /* Discover first one bit to determine shift amount. Use a
330: * modified binary search. We have already shifted the result
331: * one position right and still not found a one so the remainder
332: * of the extension must be zero and simplifies rounding. */
333: /* Scan bytes */
334: while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
335: {
336: Dbl_leftshiftby8(resultp1,resultp2);
337: if((result_exponent -= 8) <= 0 && !underflowtrap)
338: goto underflow;
339: }
340: /* Now narrow it down to the nibble */
341: if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
342: {
343: /* The lower nibble contains the normalizing one */
344: Dbl_leftshiftby4(resultp1,resultp2);
345: if((result_exponent -= 4) <= 0 && !underflowtrap)
346: goto underflow;
347: }
348: /* Select case were first bit is set (already normalized)
349: * otherwise select the proper shift. */
350: if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
351: {
352: /* Already normalized */
353: if(result_exponent <= 0) goto underflow;
354: Dbl_set_sign(resultp1,/*using*/sign_save);
355: Dbl_set_exponent(resultp1,/*using*/result_exponent);
356: Dbl_copytoptr(resultp1,resultp2,dstptr);
357: return(NOEXCEPTION);
358: }
359: Dbl_sethigh4bits(resultp1,/*using*/sign_save);
360: switch(jumpsize)
361: {
362: case 1:
363: {
364: Dbl_leftshiftby3(resultp1,resultp2);
365: result_exponent -= 3;
366: break;
367: }
368: case 2:
369: case 3:
370: {
371: Dbl_leftshiftby2(resultp1,resultp2);
372: result_exponent -= 2;
373: break;
374: }
375: case 4:
376: case 5:
377: case 6:
378: case 7:
379: {
380: Dbl_leftshiftby1(resultp1,resultp2);
381: result_exponent -= 1;
382: break;
383: }
384: }
385: if(result_exponent > 0)
386: {
387: Dbl_set_exponent(resultp1,/*using*/result_exponent);
388: Dbl_copytoptr(resultp1,resultp2,dstptr);
389: return(NOEXCEPTION); /* Sign bit is already set */
390: }
391: /* Fixup potential underflows */
392: underflow:
393: if(Is_underflowtrap_enabled())
394: {
395: Dbl_set_sign(resultp1,sign_save);
396: Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
397: Dbl_copytoptr(resultp1,resultp2,dstptr);
398: /* inexact = FALSE */
399: return(UNDERFLOWEXCEPTION);
400: }
401: /*
402: * Since we cannot get an inexact denormalized result,
403: * we can now return.
404: */
405: Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
406: Dbl_clear_signexponent(resultp1);
407: Dbl_set_sign(resultp1,sign_save);
408: Dbl_copytoptr(resultp1,resultp2,dstptr);
409: return(NOEXCEPTION);
410: } /* end if(hidden...)... */
411: /* Fall through and round */
412: } /* end if(save >= 0)... */
413: else
414: {
415: /* Subtract magnitudes */
416: Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
417: if(Dbl_isone_hiddenoverflow(resultp1))
418: {
419: /* Prenormalization required. */
420: Dbl_rightshiftby1_withextent(resultp2,extent,extent);
421: Dbl_arithrightshiftby1(resultp1,resultp2);
422: result_exponent++;
423: } /* end if hiddenoverflow... */
424: } /* end else ...subtract magnitudes... */
425:
426: /* Round the result. If the extension is all zeros,then the result is
427: * exact. Otherwise round in the correct direction. No underflow is
428: * possible. If a postnormalization is necessary, then the mantissa is
429: * all zeros so no shift is needed. */
430: round:
431: if(Ext_isnotzero(extent))
432: {
433: inexact = TRUE;
434: switch(Rounding_mode())
435: {
436: case ROUNDNEAREST: /* The default. */
437: if(Ext_isone_sign(extent))
438: {
439: /* at least 1/2 ulp */
440: if(Ext_isnotzero_lower(extent) ||
441: Dbl_isone_lowmantissap2(resultp2))
442: {
443: /* either exactly half way and odd or more than 1/2ulp */
444: Dbl_increment(resultp1,resultp2);
445: }
446: }
447: break;
448:
449: case ROUNDPLUS:
450: if(Dbl_iszero_sign(resultp1))
451: {
452: /* Round up positive results */
453: Dbl_increment(resultp1,resultp2);
454: }
455: break;
456:
457: case ROUNDMINUS:
458: if(Dbl_isone_sign(resultp1))
459: {
460: /* Round down negative results */
461: Dbl_increment(resultp1,resultp2);
462: }
463:
464: case ROUNDZERO:;
465: /* truncate is simple */
466: } /* end switch... */
467: if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
468: }
469: if(result_exponent == DBL_INFINITY_EXPONENT)
470: {
471: /* Overflow */
472: if(Is_overflowtrap_enabled())
473: {
474: Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
475: Dbl_copytoptr(resultp1,resultp2,dstptr);
476: if (inexact) {
477: if (Is_inexacttrap_enabled())
478: return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
479: else
480: Set_inexactflag();
481: }
482: return(OVERFLOWEXCEPTION);
483: }
484: else
485: {
486: inexact = TRUE;
487: Set_overflowflag();
488: Dbl_setoverflow(resultp1,resultp2);
489: }
490: }
491: else Dbl_set_exponent(resultp1,result_exponent);
492: Dbl_copytoptr(resultp1,resultp2,dstptr);
493: if(inexact) {
494: if(Is_inexacttrap_enabled())
495: return(INEXACTEXCEPTION);
496: else
497: Set_inexactflag();
498: }
499: return(NOEXCEPTION);
500: }
CVSweb