Keep in GCC's good books by not relying on overflow when performing
[AROS.git] / workbench / libs / mathieeesingbas / ieeespdiv.c
blobd6fc570f2ee38ece3c509216ad18b7665368f4dc
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "mathieeesingbas_intern.h"
8 /*****************************************************************************
10 NAME */
12 AROS_LH2(float, IEEESPDiv,
14 /* SYNOPSIS */
15 AROS_LHA(float, y, D0),
16 AROS_LHA(float, z, D1),
18 /* LOCATION */
19 struct LibHeader *, MathIeeeSingBasBase, 14, Mathieeesingbas)
21 /* FUNCTION
22 Divide two IEEE single precision floating point numbers
23 x = y / z;
25 INPUTS
27 RESULT
28 Flags:
29 zero : result is zero
30 negative : result is negative
31 overflow : result is out of range
33 BUGS
35 INTERNALS
36 ALGORITHM:
37 Check if fnum2 == 0: result = 0;
38 Check if fnum1 == 0: result = overflow;
39 The further algorithm comes down to a pen & paper division.
41 *****************************************************************************/
43 AROS_LIBFUNC_INIT
45 LONG Res = 0;
46 LONG Exponent = (y & IEEESPExponent_Mask)
47 - (z & IEEESPExponent_Mask) + 0x3f800000;
49 LONG Mant2 = ((y & IEEESPMantisse_Mask) | 0x00800000) << 8;
50 LONG Mant1 = ((z & IEEESPMantisse_Mask) | 0x00800000) << 8;
51 ULONG Bit_Mask = 0x80000000;
53 if (0 == z && 0 == y) return 0x7f880000;
55 /* check if the dividend is zero */
56 if (0 == z)
58 SetSR(Zero_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
59 return (IEEESPExponent_Mask | ((y & IEEESPSign_Mask) ^ (z & IEEESPSign_Mask)));
62 /* check for division by zero */
63 if (0 == y)
65 SetSR(Overflow_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
66 return (y & IEEESPSign_Mask) ^ (z & IEEESPSign_Mask);
69 while (Bit_Mask >= 0x40 && Mant2 != 0)
71 if (Mant2 - Mant1 >= 0)
73 Mant2 -= Mant1;
74 Res |= Bit_Mask;
76 while (Mant2 > 0)
78 Mant2 <<= 1;
79 Bit_Mask >>= 1;
82 while (Mant1 > 0)
84 Mant1 <<=1;
85 Bit_Mask <<=1;
87 } /* if */
88 else
90 Mant1 = (ULONG) Mant1 >> 1;
91 Bit_Mask >>= 1;
93 } /* while */
95 /* normalize the mantisse */
96 while (Res > 0)
98 if (Res >= 0x40000000)
99 Res = Res - 0x80000000;
100 Res += Res;
101 Exponent -=0x00800000;
104 if ((char) Res < 0) Res += 0x00000100;
105 Res >>= 8;
107 Res &= IEEESPMantisse_Mask;
108 Res |= Exponent;
109 Res |= (y & IEEESPSign_Mask) ^ (z & IEEESPSign_Mask);
111 if (Res < 0) SetSR(Negative_Bit, Zero_Bit | Overflow_Bit | Negative_Bit);
112 if (Exponent < 0) SetSR(Overflow_Bit, Negative_Bit | Overflow_Bit);
114 return Res;
116 AROS_LIBFUNC_EXIT