Improved AutoDocs.
[AROS.git] / workbench / libs / mathieeedoubbas / ieeedpadd.c
blobf9c96b28408f9cae240143fb3077cc4636556be3
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "mathieeedoubbas_intern.h"
8 /*****************************************************************************
10 NAME */
12 AROS_LHQUAD2(double, IEEEDPAdd,
14 /* SYNOPSIS */
15 AROS_LHAQUAD(double, y, D0, D1),
16 AROS_LHAQUAD(double, z, D2, D3),
18 /* LOCATION */
19 struct MathIeeeDoubBasBase *, MathIeeeDoubBasBase, 11, MathIeeeDoubBas)
21 /* FUNCTION
22 Calculate the sum of two IEEE double precision numbers.
24 INPUTS
25 y - first addend.
26 z - first addend.
28 RESULT
29 x - sum of y and z.
31 Flags:
32 zero : result is zero
33 negative : result is negative
34 overflow : result is too large or too small for IEEE DP format
36 NOTES
38 EXAMPLE
40 BUGS
42 SEE ALSO
44 INTERNALS
46 *****************************************************************************/
48 AROS_LIBFUNC_INIT
50 QUAD Res;
51 QUAD Mant1, Mant2;
52 QUAD Qtmp1, Qtmp2;
53 LONG Shift;
54 QUAD Exponent;
55 LONG Ltmp1, Ltmp2;
56 QUAD * Qy = (QUAD *)&y;
57 QUAD * Qz = (QUAD *)&z;
58 double * DRes = (double *)&Res;
60 SetSR(0, Zero_Bit | Overflow_Bit | Negative_Bit );
62 AND64C(Qtmp1, *Qy, IEEEDPExponent_Mask_Hi, IEEEDPExponent_Mask_Lo);
63 AND64C(Qtmp2, *Qz, IEEEDPExponent_Mask_Hi, IEEEDPExponent_Mask_Lo);
64 SHRU32(Ltmp1, Qtmp1, 52);
65 SHRU32(Ltmp2, Qtmp2, 52);
66 Shift = Ltmp1 - Ltmp2;
70 is_neqC(*Qy, 0x0, 0x0)
71 && is_neqC(*Qy, IEEEDPSign_Mask_Hi, IEEEDPSign_Mask_Lo)
74 AND64C(Mant1, *Qy, IEEEDPMantisse_Mask_Hi, IEEEDPMantisse_Mask_Lo);
75 OR64QC(Mant1, 0x00100000, 0x00000000);
77 else
79 Set_Value64C(Mant1, 0x0, 0x0);
84 is_neqC(*Qz, 0x0, 0x0)
85 && is_neqC(*Qz, IEEEDPSign_Mask_Hi, IEEEDPSign_Mask_Lo)
88 /* Mant2 = (*Qz & IEEESPMantisse_Mask) | 0x00800000; */
89 AND64C(Mant2, *Qz, IEEEDPMantisse_Mask_Hi, IEEEDPMantisse_Mask_Lo);
90 OR64QC(Mant2, 0x00100000, 0x00000000);
92 else
94 Set_Value64C(Mant2, 0x0, 0x0);
97 if (Shift > 0)
99 SHRU64(Mant2, Mant2, Shift);
100 AND64C(Exponent, *Qy, IEEEDPExponent_Mask_Hi, IEEEDPExponent_Mask_Lo);
102 else
104 SHRU64(Mant1, Mant1, (-Shift));
105 AND64C(Exponent, *Qz, IEEEDPExponent_Mask_Hi, IEEEDPExponent_Mask_Lo);
108 // sign(fnum1) == sign(fnum2)
109 // simple addition
110 // 0.25 <= res < 1
111 AND64C(Qtmp1, *Qz, IEEEDPSign_Mask_Hi, IEEEDPSign_Mask_Lo);
112 AND64C(Qtmp2, *Qy, IEEEDPSign_Mask_Hi, IEEEDPSign_Mask_Lo);
113 if ( is_eq(Qtmp1, Qtmp2))
115 AND64C(Res, *Qy, IEEEDPSign_Mask_Hi, IEEEDPSign_Mask_Lo);
116 ADD64Q(Mant1, Mant2);
117 AND64C(Qtmp1, Mant1, 0x00200000, 0x0);
118 if ( is_neqC(Qtmp1, 0x0, 0x0))
120 ADD64QC(Exponent, 0x00100000, 0x0);
121 SHRU64(Mant1, Mant1, 1);
123 AND64QC(Mant1, IEEEDPMantisse_Mask_Hi, IEEEDPMantisse_Mask_Lo);
125 // second case: sign(fnum1) != sign(fnum2)
126 // -1 <= res < 1
127 else
129 //printf("Exponent: %x\n",Exponent);
130 if ( is_lessSC(*Qy, 0x0, 0x0))
132 SUB64(Mant1, Mant2, Mant1);
134 else // fnum2 < 0
136 SUB64(Mant1, Mant1, Mant2);
139 //if the result is below zero
140 if ( is_lessSC(Mant1, 0x0, 0x0))
142 Set_Value64C(Res, IEEEDPSign_Mask_Hi, IEEEDPSign_Mask_Lo);
143 NEG64(Mant1);
144 SetSR(Negative_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
146 else
148 Set_Value64C(Res, 0x0, 0x0);
151 if (is_eqC(Mant1, 0x0, 0x0))
153 union { QUAD i; double d; } tmp;
154 SetSR(Zero_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
155 Set_Value64C(Res, 0x0, 0x0);
156 tmp.i = Res;
157 return tmp.d;
159 else
161 /* normalize the mantisse */
162 AND64C(Qtmp1, Mant1, 0x00100000, 0x0);
163 while ( is_eqC(Qtmp1, 0x0, 0x0))
165 SHL64(Mant1, Mant1, 1); //one bit to the left.
166 SUB64QC(Exponent, 0x00100000, 0x0);
167 AND64C(Qtmp1, Mant1, 0x00100000, 0x0);
169 AND64QC(Mant1, IEEEDPMantisse_Mask_Hi, IEEEDPMantisse_Mask_Lo);
170 } /* else */
172 } /* else */
174 if ( is_lessSC(Exponent, 0x0, 0x0))
176 SetSR(Overflow_Bit, Zero_Bit | Overflow_Bit); //do not change Negative_Bit!
177 OR64QC
179 Res,
180 (IEEEDPMantisse_Mask_Hi | IEEEDPExponent_Mask_Hi),
181 (IEEEDPMantisse_Mask_Lo | IEEEDPExponent_Mask_Lo)
184 OR64Q(Res, Mant1);
185 OR64Q(Res, Exponent);
187 return *DRes;
189 AROS_LIBFUNC_EXIT