2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
6 #include "mathieeedoubtrans_intern.h"
10 Calculate square root of IEEE double precision floating point number
13 Motorola fast floating point number
18 overflow : square root could not be calculated
30 <p>First check for a zero and a negative argument and take
31 appropriate action.</p>
33 <code>fnum = M * 2^E</code>
35 <p>Exponent is an odd number:</p>
38 fnum = ( M*2 ) * 2^ (E-1)
39 Now E' = E-1 is an even number and
40 -> sqrt(fnum) = sqrt(M) * sqrt(2) * sqrt (2^E')
41 = sqrt(M) * sqrt(2) * 2^(E'/2)
43 = sqrt(M) * sqrt(2) * 2^(E'/2)
44 = sqrt(M) * 1/sqrt(2) * 2^(1+(E'/2))
45 = sqrt(M/2) * 2^(1+(E'/2))
49 <p>Exponent is an even number:</p>
51 <code>-> sqrt(fnum) = sqrt(M) * sqrt (2^E) =
55 <p>Now calculate the square root of the mantisse.
56 The following algorithm calculates the square of a number + delta
57 and compares it to the mantisse. If the square of that number +
58 delta is less than the mantisse then keep that number + delta.
59 Otherwise calculate a lower offset and try again.
60 Start out with number = 0;</p>
67 if ( (Root + 2^Exponent)^2 < Mantisse)
73 until you`re happy with the accuracy
78 AROS_LHQUAD1(double, IEEEDPSqrt
,
79 AROS_LHAQUAD(double, y
, D0
, D1
),
80 struct MathIeeeDoubTransBase
*, MathIeeeDoubTransBase
, 16, MathIeeeDoubTrans
85 QUAD Res
, ResSquared
, Delta
, X
, TargetMantisse
, y2
, tmp
;
89 if (is_eqC(y
, 0, 0)) /* 0 == y */
91 SetSR(Zero_Bit
, Zero_Bit
| Negative_Bit
| Overflow_Bit
);
92 Set_Value64C(Res
, 0, 0);
95 /* is fnum negative? */
96 if (is_lessSC(y
, 0, 0)) /* y < 0 */
98 SetSR(Overflow_Bit
, Zero_Bit
| Negative_Bit
| Overflow_Bit
);
99 Set_Value64C(Res
, IEEEDPNAN_Hi
, IEEEDPNAN_Lo
);
103 /* we can calculate the square-root now! */
106 AND64QC(y2
, IEEEDPMantisse_Mask_Hi
, IEEEDPMantisse_Mask_Lo
);
107 OR64QC(y2
, 0x00100000, 0x00000000 );
108 SHL64(TargetMantisse
, y2
, 11);
110 Exponent
= (Get_High32of64(y
) >> 1) & IEEEDPExponent_Mask_Hi
;
112 /* do we have an odd exponent? */
113 if (Get_High32of64(y
) & 0x00100000)
115 /* TargetMantisse = TargetMantisse / 2; */
116 SHRU64(TargetMantisse
, TargetMantisse
, 1); /* TargetMantisse >>= 1; */
117 Exponent
+= 0x20000000;
121 Exponent
+= 0x1ff00000;
124 Set_Value64C(Res
, 0x0, 0x0);
125 Set_Value64C(ResSquared
, 0x0, 0x0);
129 this calculates the sqrt of the mantisse. It`s short, isn`t it?
130 Delta starts out with 0.5, then 0.25, 0.125 etc.
132 while ( is_neq(ResSquared
, TargetMantisse
) && z
< 53)
134 QUAD Restmp
, Deltatmp
;
135 Set_Value64C(Delta
, 0x80000000, 0x00000000);
136 SHRU64(Delta
, Delta
, z
); /* Delta >> = z */
139 X = (Res+Delta)^2 = Res^2 + 2*Res*Delta + Delta^2
141 SHRU64(Restmp
, Res
, z
); /* Restmp = Res >> z */
143 SHRU64(Deltatmp
, Delta
, z
); /* Deltatmp = Delta >> (z+1) */
145 /* X = ResSquared + (Res >> z) + (Delta >> ++z); */
146 Set_Value64(X
, ResSquared
);
150 if (is_leq(X
, TargetMantisse
)) /* X <= TargetMantisse */
152 //printf("setting a bit!\n");
153 //OUTPUT(X);OUTPUT(TargetMantisse);
154 ADD64(Res
, Res
, Delta
); /* Res += Delta */
155 Set_Value64(ResSquared
, X
); /* ResSquared = X; */
159 SHRU64(Res
, Res
, 11);
160 AND64QC(Res
, IEEEDPMantisse_Mask_Hi
, IEEEDPMantisse_Mask_Lo
);
161 SHL32(tmp
, Exponent
, 32);