revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / mathffp / spadd.c
blob9cd33a5643ad6fb6ece15a1241f2ab40f4f82324
1 /*
2 Copyright © 1995-2004, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "mathffp_intern.h"
8 /*****************************************************************************
10 NAME */
12 AROS_LH2(float, SPAdd,
14 /* SYNOPSIS */
15 AROS_LHA(float, fnum1, D1),
16 AROS_LHA(float, fnum2, D0),
18 /* LOCATION */
19 struct LibHeader *, MathBase, 11, Mathffp)
21 /* FUNCTION
22 Calculate the sum of two ffp numbers
24 INPUTS
26 RESULT
27 sum of fnum1 and fnum2.
29 Flags:
30 zero : result is zero
31 negative : result is negative
32 overflow : result is too large or too small for ffp format
34 BUGS
36 INTERNALS
37 Adapt the exponent of the ffp-number with the smaller
38 exponent to the ffp-number with the larger exponent.
39 Therefore rotate the mantisse of the ffp-number with the
40 smaller exponents by n bits, where n is the absolute value
41 of the difference of the exponents.
43 The exponent of the target ffp-number is set to the larger
44 exponent plus 1.
46 Additionally rotate both numbers by one bit to the right so
47 you can catch a result > 1 in the MSB.
49 If the signs of the two numbers are equal then simply add
50 the two mantisses. The result of the mantisses will be
51 [0.5 .. 2[. Check the MSB. If zero, then the result is < 1
52 and therefore subtract 1 from the exponent. Normalize the
53 mantisse of the result by rotating it one bit to the left.
54 Check the mantisse for 0.
56 If the signs of the two numbers are different then subtract
57 the ffp-number with the neagtive sign from the other one.
58 The result of the mantisse will be [-1..1[. If the MSB of
59 the result is set, then the result is below zero and therefore
60 you have to calculate the absolute value of the mantisse.
61 Check the mantisse for zero. Normalize the mantisse by
62 rotating it to the left and decreasing the exponent for every
63 rotation.
65 Test the exponent of the result for an overflow.
66 That`s it!
68 *****************************************************************************/
70 AROS_LIBFUNC_INIT
72 LONG Res;
73 ULONG Mant1, Mant2;
74 char Shift;
75 char Exponent;
77 SetSR(0, Zero_Bit | Overflow_Bit | Negative_Bit );
79 Mant1 = fnum1 & FFPMantisse_Mask;
80 Mant2 = fnum2 & FFPMantisse_Mask;
81 Shift = ((char)fnum1 & FFPExponent_Mask) -
82 ((char)fnum2 & FFPExponent_Mask);
84 if (Shift > 0)
86 if (Shift >= 31)
88 Mant2 = 0;
90 else
92 Mant2 >>= (Shift + 1);
94 Mant1 >>= 1;
95 Exponent = (fnum1 & FFPExponent_Mask) + 1;
97 else
99 if (Shift <= -31)
101 Mant1 = 0;
103 else
105 Mant1 >>= (-Shift + 1);
107 Mant2 >>= 1;
108 Exponent = (fnum2 & FFPExponent_Mask) + 1;
111 /* sign(fnum1) == sign(fnum2)
112 ** simple addition
113 ** 0.5 <= res < 2
115 if ( ((BYTE) fnum1 & FFPSign_Mask) - ((BYTE) fnum2 & FFPSign_Mask) == 0)
117 Res = fnum1 & FFPSign_Mask;
118 Mant1 += Mant2;
119 if ((LONG) Mant1 > 0)
121 Exponent --;
122 Mant1 +=Mant1;
125 if (0 == Mant1)
127 SetSR(Zero_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
128 return 0;
131 /* second case: sign(fnum1) != sign(fnum2)
132 ** -1 <= res < 1
134 else
136 if ((char) fnum1 < 0)
138 Mant1 = Mant2 - Mant1;
140 else /* fnum2 < 0 */
142 Mant1 = Mant1 - Mant2;
144 /* if the result is below zero */
145 if ((LONG) Mant1 < 0)
147 Res = FFPSign_Mask;
148 Mant1 =-Mant1;
149 SetSR(Negative_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
151 else
153 Res = 0;
155 /* test the result for zero, has to be done before normalizing
156 ** the mantisse
158 if (0 == Mant1)
160 SetSR(Zero_Bit, Zero_Bit | Overflow_Bit | Negative_Bit);
161 return 0;
163 /* normalize the mantisse */
164 while ((LONG) Mant1 > 0)
166 Mant1 += Mant1; /* one bit to the left. */
167 Exponent--;
169 } /* else */
171 if ((char) Exponent < 0)
173 SetSR(Overflow_Bit, Zero_Bit | Overflow_Bit);
174 /* do NOT change Negative_Bit! */
175 return (Res | (FFPMantisse_Mask | FFPExponent_Mask));
178 Res |= (Mant1 & FFPMantisse_Mask) | Exponent;
180 D(kprintf("SPAdd(%x + %x) = %x\n", fnum1, fnum2, Res));
182 return Res;
184 AROS_LIBFUNC_EXIT