grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / libs / mathtrans / spsqrt.c
blob2af504868fbc3ca3cbbc156761bed136612e4596
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "mathtrans_intern.h"
8 /*****************************************************************************
10 NAME */
12 AROS_LH1(float, SPSqrt,
14 /* SYNOPSIS */
15 AROS_LHA(float, fnum1, D0),
17 /* LOCATION */
18 struct Library *, MathTransBase, 16, MathTrans)
20 /* FUNCTION
21 Calculate square root of ffp number
23 INPUTS
25 RESULT
26 Motorola fast floating point 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 fnum1 = M * 2^E
41 If exponent is an odd number:
43 fnum = ( M*2 ) * 2^ (E-1)
44 Now E' = E-1 is an even number and
45 -> sqrt(fnum) = sqrt(M) * sqrt(2) * sqrt (2^E')
46 = sqrt(M) * sqrt(2) * 2^(E'/2)
47 (with sqrt(M*2)>1)
48 = sqrt(M) * sqrt(2) * 2^(E'/2)
49 = sqrt(M) * 1/sqrt(2) * 2^(1+(E'/2))
50 = sqrt(M/2) * 2^(1+(E'/2))
53 If Exponent is an even number:
54 -> sqrt(fnum) = sqrt(M) * sqrt (2^E) =
55 = sqrt(M) * 2^(E/2)
57 Now calculate the square root of the mantisse.
58 The following algorithm calculates the square of a number + delta
59 and compares it to the mantisse. If the square of that number +
60 delta is less than the mantisse then keep that number + delta.
61 Otherwise calculate a lower delta and try again.
62 Start out with number = 0;
65 Exponent = -1;
66 Root = 0;
67 repeat
69 if ( ( Root + 2^Exponent ) ^2 < Mantisse)
70 Root += 2^Exponent
71 Exponent --;
73 until you`re happy with the accuracy
75 *****************************************************************************/
77 AROS_LIBFUNC_INIT
79 ULONG Res, ResSquared, Delta, X, TargetMantisse;
80 int z;
81 BYTE Exponent;
83 if (0 == fnum1)
85 SetSR(Zero_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
86 return 0;
88 /* is fnum negative */
89 if ((char)fnum1 < 0)
91 SetSR(Overflow_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
92 return fnum1;
95 /* let us calculate the square-root now! */
97 TargetMantisse = ((ULONG)fnum1 & FFPMantisse_Mask);
99 if (fnum1 & 1)
101 /* TargetMantisse = TargetMantisse / 2; */
102 TargetMantisse >>= 1;
103 Exponent = ((BYTE)fnum1 >> 1) + 0x21;
105 else
107 Exponent = ((BYTE)fnum1 >> 1) + 0x20;
110 Res = 0;
111 ResSquared = 0;
112 z = 0;
115 this calculates the sqrt of the mantisse. It`s short, isn`t it?
116 Delta starts out with 0.5, then 0.25, 0.125 etc.
118 while (ResSquared != TargetMantisse && z < 25)
120 Delta = (0x80000000 >> z);
122 X = (Res+Delta)^2 =
123 = Res^2 + 2*Res*Delta + Delta^2
125 X = ResSquared + (Res >> z) + (Delta >> (z+1));
126 z++;
127 if (X <= TargetMantisse)
129 Res += Delta;
130 ResSquared = X;
134 /* an adjustment for precision */
135 if ((char) Res < 0) Res += 0x100;
137 Res &= FFPMantisse_Mask;
138 Res |= Exponent;
140 return Res;
142 AROS_LIBFUNC_EXIT