home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
language
/
sozobon2
/
sqrt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-23
|
1KB
|
48 lines
/* SQRT function for Sozobon C. */
/* Copyright = David Brooks, 1989 All Rights Reserved */
/* */
/* The method is from Hart et al: "Computer Approximations". We reduce */
/* the range to [0.25..1.0], then apply the polynomial: */
/* 0.25927688 + 1.0520212n - 0.31632214n^2, giving 2.3 digits */
/* approximation. Then we do two Newton's iterations (giving ~9 digits */
/* precision). */
/* */
/* A negative argument gives a return value of 0.0 and sets EDOM. */
#include <fplib.h>
#include <errno.h>
/* Sadly we can't use register for objects of type fstruct. */
float sqrt(n)
fstruct n;
{ register int exp; /* Separate unbiased exponent. */
fstruct s;
if (n.sc[3] == 0) /* Check for 0.0 */
return 0.0;
if ((exp = n.sc[3]) < 0) /* Test argument's sign. */
{ errno = EDOM;
return 0.0;
}
exp -= BIAS; /* Get unbiased exponent. */
if (exp & 1)
{ n.sc[3] = BIAS-1; /* Convert to 0.25..0.5. */
++exp;
}
else
n.sc[3] = BIAS; /* Or convert to 0.5..1. */
s.f = 0.25927688 + n.f * (1.0520212 + n.f * -0.31632214);
s.f = s.f + n.f / s.f; /* One Newton. */
s.sc[3] -= 1; /* (here's the divide by 2). */
s.f = s.f + n.f / s.f; /* The other Newton. */
s.sc[3] += ((unsigned int)exp >> 1) - 1;
/* Divide by 2 and insert
half the original exponent. */
return s.f;
}