revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / mathieeesingtrans / ieeespsqrt.c
blobc13b680872b2b1acb27d024c9cb74510bd5cc286
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "mathieeesingtrans_intern.h"
8 /*****************************************************************************
10 NAME */
12 AROS_LH1(float, IEEESPSqrt,
14 /* SYNOPSIS */
15 AROS_LHA(float, y, D0),
17 /* LOCATION */
18 struct Library *, MathIeeeSingTransBase, 16, MathIeeeSingTrans)
20 /* FUNCTION
21 Calculate square root of IEEE single precision number
23 INPUTS
25 RESULT
26 IEEE single precision number
28 flags:
29 zero : result is zero
30 negative : 0
31 overflow : square root could not be calculated
33 BUGS
35 INTERNALS
36 ALGORITHM:
37 First check for a zero and a negative argument and take
38 appropriate action.
39 y = M * 2^E
41 Exponent is an odd number:
42 y = ( M*2 ) * 2^ (E-1)
43 Now E' = E-1 is an even number and
44 -> sqrt(y) = sqrt(M) * sqrt(2) * sqrt (2^E')
45 = sqrt(M) * sqrt(2) * 2^(E'/2)
46 (with sqrt(M*2)>1)
47 = sqrt(M) * sqrt(2) * 2^(E'/2)
48 = sqrt(M) * 1/sqrt(2) * 2^(1+(E'/2))
49 = sqrt(M/2) * 2^(1+(E'/2))
52 Exponent is an even number:
53 -> sqrt(y) = sqrt(M) * sqrt (2^E) =
54 = sqrt(M) * 2^(E/2)
56 Now calculate the square root of the mantisse.
57 The following algorithm calculates the square of a number + delta
58 and compares it to the mantisse. If the square of that number +
59 delta is less than the mantisse then keep that number + delta.
60 Otherwise calculate a lower offset and try again.
61 Start out with number = 0;
64 Exponent = -1;
65 Root = 0;
66 repeat
68 if ( (Root + 2^Exponent)^2 < Mantisse)
69 Root += 2^Exponent
70 Exponent --;
72 until you`re happy with the accuracy
74 *****************************************************************************/
76 AROS_LIBFUNC_INIT
78 ULONG Res, ResSquared, Delta, X, TargetMantisse;
79 int z;
80 ULONG Exponent;
82 if (0 == y)
84 SetSR(Zero_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
85 return 0;
87 /* is fnum negative? */
88 if (y < 0)
90 SetSR(Overflow_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
91 return y;
94 /* we can calculate the square-root now! */
96 TargetMantisse = ((y & IEEESPMantisse_Mask) | 0x00800000) << 8;
98 if (y & 0x00800000)
100 /* TargetMantisse = TargetMantisse / 2; */
101 TargetMantisse >>= 1;
102 Exponent = ((y >> 1) & IEEESPExponent_Mask) + 0x20000000;
104 else
106 Exponent = ((y >> 1) & IEEESPExponent_Mask) + 0x1f800000;
109 Res = 0;
110 ResSquared = 0;
111 z = 0;
114 this calculates the sqrt of the mantisse. It`s short, isn`t it?
115 Delta starts out with 0.5, then 0.25, 0.125 etc.
117 while (ResSquared != TargetMantisse && z < 25)
119 Delta = (0x80000000 >> z);
121 X = (Res+Delta)^2 = Res^2 + 2*Res*Delta + Delta^2
123 X = ResSquared + (Res >> z) + (Delta >> (z+1));
124 z++;
125 if (X <= TargetMantisse)
127 Res += Delta;
128 ResSquared = X;
132 /* an adjustment for precision
134 if ((char) Res < 0) Res += 0x100;
136 Res >>=8;
137 Res &= IEEESPMantisse_Mask;
138 Res |= Exponent;
140 return Res;
142 AROS_LIBFUNC_EXIT