Support rastport clipping rectangle for layerless rastports
[tangerine.git] / rom / mathffp / spadd.c
blob5a31f3fe1dfee308cc03aa984ce2c2b3aad3fb8e
1 /*
2 Copyright © 1995-2004, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "mathffp_intern.h"
8 /*
9 FUNCTION
10 Calculate the sum of two ffp numbers
12 RESULT
13 sum of fnum1 and fnum2.
15 Flags:
16 <description>
17 <li><item>zero</item>result is zero</li>
18 <li><item>negative</item>result is negative</li>
19 <li><item>overflow</item>result is too large or too small for ffp format</li>
20 </description>
22 NOTES
24 EXAMPLE
26 BUGS
28 SEE ALSO
31 INTERNALS
32 <p>Adapt the exponent of the ffp-number with the smaller
33 exponent to the ffp-number with the larger exponent.
34 Therefore rotate the mantisse of the ffp-number with the
35 smaller exponents by n bits, where n is the absolute value
36 of the difference of the exponents.</p>
38 <p>The exponent of the target ffp-number is set to the larger
39 exponent plus 1.</p>
41 <p>Additionally rotate both numbers by one bit to the right so
42 you can catch a result &gt; 1 in the MSB.</p>
44 <p>If the signs of the two numbers are equal then simply add
45 the two mantisses. The result of the mantisses will be
46 [0.5 .. 2[. Check the MSB. If zero, then the result is &lt; 1
47 and therefore subtract 1 from the exponent. Normalize the
48 mantisse of the result by rotating it one bit to the left.
49 Check the mantisse for 0.</p>
51 <p>If the signs of the two numbers are different then subtract
52 the ffp-number with the neagtive sign from the other one.
53 The result of the mantisse will be [-1..1[. If the MSB of
54 the result is set, then the result is below zero and therefore
55 you have to calculate the absolute value of the mantisse.
56 Check the mantisse for zero. Normalize the mantisse by
57 rotating it to the left and decreasing the exponent for every
58 rotation.</p>
60 <p>Test the exponent of the result for an overflow.
61 That`s it!</p>
63 HISTORY
66 AROS_LH2(float, SPAdd,
67 AROS_LHA(float, fnum1, D1),
68 AROS_LHA(float, fnum2, D0),
69 struct LibHeader *, MathBase, 11, Mathffp
72 AROS_LIBFUNC_INIT
74 LONG Res;
75 ULONG Mant1, Mant2;
76 char Shift;
77 char Exponent;
79 SetSR(0, Zero_Bit | Overflow_Bit | Negative_Bit );
81 Mant1 = fnum1 & FFPMantisse_Mask;
82 Mant2 = fnum2 & FFPMantisse_Mask;
83 Shift = ((char)fnum1 & FFPExponent_Mask) -
84 ((char)fnum2 & FFPExponent_Mask);
86 if (Shift > 0)
88 if (Shift >= 31)
90 Mant2 = 0;
92 else
94 Mant2 >>= (Shift + 1);
96 Mant1 >>= 1;
97 Exponent = (fnum1 & FFPExponent_Mask) + 1;
99 else
101 if (Shift <= -31)
103 Mant1 = 0;
105 else
107 Mant1 >>= (-Shift + 1);
109 Mant2 >>= 1;
110 Exponent = (fnum2 & FFPExponent_Mask) + 1;
113 /* sign(fnum1) == sign(fnum2)
114 ** simple addition
115 ** 0.5 <= res < 2
117 if ( ((BYTE) fnum1 & FFPSign_Mask) - ((BYTE) fnum2 & FFPSign_Mask) == 0)
119 Res = fnum1 & FFPSign_Mask;
120 Mant1 += Mant2;
121 if ((LONG) Mant1 > 0)
123 Exponent --;
124 Mant1 +=Mant1;
127 if (0 == Mant1)
129 SetSR(Zero_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
130 return 0;
133 /* second case: sign(fnum1) != sign(fnum2)
134 ** -1 <= res < 1
136 else
138 if ((char) fnum1 < 0)
140 Mant1 = Mant2 - Mant1;
142 else /* fnum2 < 0 */
144 Mant1 = Mant1 - Mant2;
146 /* if the result is below zero */
147 if ((LONG) Mant1 < 0)
149 Res = FFPSign_Mask;
150 Mant1 =-Mant1;
151 SetSR(Negative_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
153 else
155 Res = 0;
157 /* test the result for zero, has to be done before normalizing
158 ** the mantisse
160 if (0 == Mant1)
162 SetSR(Zero_Bit, Zero_Bit | Overflow_Bit | Negative_Bit);
163 return 0;
165 /* normalize the mantisse */
166 while ((LONG) Mant1 > 0)
168 Mant1 += Mant1; /* one bit to the left. */
169 Exponent--;
171 } /* else */
173 if ((char) Exponent < 0)
175 SetSR(Overflow_Bit, Zero_Bit | Overflow_Bit);
176 /* do NOT change Negative_Bit! */
177 return (Res | (FFPMantisse_Mask | FFPExponent_Mask));
180 Res |= (Mant1 & FFPMantisse_Mask) | Exponent;
182 kprintf("SPAdd(%x,%x)=%x\n",fnum1,fnum2,Res);
184 return Res;
186 AROS_LIBFUNC_EXIT