P
pete
pete wrote:
I just wrote a cosine function called c_os, for no special reason.
It calls no functions that I haven't also written.
On my machine, it seems to work better than
my MS compiler's standard library cos function.
They don't get the zeros right. I do.
c_os(-123 * pi / 6) is 0.000000e+000
c_os(-129 * pi / 6) is 0.000000e+000
cos(-123 * pi / 6) is 7.839514e-015
cos(-129 * pi / 6) is -4.409261e-015
/* BEGIN c_os.c output */
const double pi = 4 * atan(1);
c_os(-120 * pi / 6) is 1.000000e+000
c_os(-121 * pi / 6) is 8.660254e-001
c_os(-122 * pi / 6) is 5.000000e-001
c_os(-123 * pi / 6) is 0.000000e+000
c_os(-124 * pi / 6) is -5.000000e-001
c_os(-125 * pi / 6) is -8.660254e-001
c_os(-126 * pi / 6) is -1.000000e+000
c_os(-127 * pi / 6) is -8.660254e-001
c_os(-128 * pi / 6) is -5.000000e-001
c_os(-129 * pi / 6) is 0.000000e+000
c_os(-130 * pi / 6) is 5.000000e-001
c_os(-131 * pi / 6) is 8.660254e-001
cos(-120 * pi / 6) is 1.000000e+000
cos(-121 * pi / 6) is 8.660254e-001
cos(-122 * pi / 6) is 5.000000e-001
cos(-123 * pi / 6) is 7.839514e-015
cos(-124 * pi / 6) is -5.000000e-001
cos(-125 * pi / 6) is -8.660254e-001
cos(-126 * pi / 6) is -1.000000e+000
cos(-127 * pi / 6) is -8.660254e-001
cos(-128 * pi / 6) is -5.000000e-001
cos(-129 * pi / 6) is -4.409261e-015
cos(-130 * pi / 6) is 5.000000e-001
cos(-131 * pi / 6) is 8.660254e-001
/* END c_os.c output */
/* BEGIN c_os.c */
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <errno.h>
double c_os(double x);
double p_i(void);
double sq_rt(double x);
int main(void)
{
const double pi = 4 * atan(1);
puts("/* BEGIN c_os.c output */\n");
puts("const double pi = 4 * atan(1);\n");
printf("c_os(-120 * pi / 6) is %e\n", c_os(-120 * pi / 6));
printf("c_os(-121 * pi / 6) is %e\n", c_os(-121 * pi / 6));
printf("c_os(-122 * pi / 6) is %e\n", c_os(-122 * pi / 6));
printf("c_os(-123 * pi / 6) is %e\n", c_os(-123 * pi / 6));
printf("c_os(-124 * pi / 6) is %e\n", c_os(-124 * pi / 6));
printf("c_os(-125 * pi / 6) is %e\n", c_os(-125 * pi / 6));
printf("c_os(-126 * pi / 6) is %e\n", c_os(-126 * pi / 6));
printf("c_os(-127 * pi / 6) is %e\n", c_os(-127 * pi / 6));
printf("c_os(-128 * pi / 6) is %e\n", c_os(-128 * pi / 6));
printf("c_os(-129 * pi / 6) is %e\n", c_os(-129 * pi / 6));
printf("c_os(-130 * pi / 6) is %e\n", c_os(-130 * pi / 6));
printf("c_os(-131 * pi / 6) is %e\n", c_os(-131 * pi / 6));
putchar('\n');
printf("cos(-120 * pi / 6) is %e\n", cos(-120 * pi / 6));
printf("cos(-121 * pi / 6) is %e\n", cos(-121 * pi / 6));
printf("cos(-122 * pi / 6) is %e\n", cos(-122 * pi / 6));
printf("cos(-123 * pi / 6) is %e\n", cos(-123 * pi / 6));
printf("cos(-124 * pi / 6) is %e\n", cos(-124 * pi / 6));
printf("cos(-125 * pi / 6) is %e\n", cos(-125 * pi / 6));
printf("cos(-126 * pi / 6) is %e\n", cos(-126 * pi / 6));
printf("cos(-127 * pi / 6) is %e\n", cos(-127 * pi / 6));
printf("cos(-128 * pi / 6) is %e\n", cos(-128 * pi / 6));
printf("cos(-129 * pi / 6) is %e\n", cos(-129 * pi / 6));
printf("cos(-130 * pi / 6) is %e\n", cos(-130 * pi / 6));
printf("cos(-131 * pi / 6) is %e\n", cos(-131 * pi / 6));
puts("\n/* END c_os.c output */");
return 0;
}
double c_os(double x)
{
unsigned n, negative, sine;
double a, b, c;
static double pi, two_pi, four_pi, half_pi, quarter_pi;
if (x >= -DBL_MAX && DBL_MAX >= x) {
if (1 > pi) {
pi = p_i();
two_pi = 2 * pi;
four_pi = 4 * pi;
half_pi = pi / 2;
quarter_pi = pi / 4;
}
if (0 > x) {
x = -x;
}
while (x > two_pi) {
b = x / 2;
a = two_pi;
while (b > a) {
a *= 2;
}
x -= a;
}
if (x > pi) {
x = two_pi - x;
}
if (x > half_pi) {
x = pi - x;
negative = 1;
} else {
negative = 0;
}
if (x > quarter_pi) {
x = half_pi - x;
sine = 1;
} else {
sine = 0;
}
c = x * x;
x = n = 0;
a = 1;
do {
b = a;
a *= c / ++n;
a /= ++n;
b -= a;
a *= c / ++n;
a /= ++n;
x += b;
} while (b > DBL_EPSILON / 2);
if (sine) {
x = sq_rt(1 - x * x);
}
if (negative) {
x = -x;
}
} else {
x = -HUGE_VAL;
errno = EDOM;
}
return x;
}
double p_i(void)
{
unsigned n;
double p, a, b;
p = 0;
a = 3;
n = 1;
do {
a /= 9;
b = a / n;
a /= 9;
n += 2;
b -= a / n;
n += 2;
p += b;
} while (b > DBL_EPSILON / 4);
a = 2;
n = 1;
do {
a /= 4;
b = a / n;
a /= 4;
n += 2;
b -= a / n;
n += 2;
p += b;
} while (b > DBL_EPSILON / 2);
return 4 * p;
}
double sq_rt(double x)
{
int n;
double a, b;
if (DBL_MAX >= x) {
if (x > 0) {
for (n = 0; x > 2; x /= 4) {
++n;
}
while (0.5 > x) {
--n;
x *= 4;
}
a = x;
b = (1 + x) / 2;
do {
x = b;
b = (a / x + x) / 2;
} while (x > b);
while (n > 0) {
x *= 2;
--n;
}
while (0 > n) {
x /= 2;
++n;
}
} else {
if (0 > x) {
errno = EDOM;
x = HUGE_VAL;
}
}
} else {
errno = ERANGE;
}
return x;
}
/* END c_os.c */
.. and now for a float sqrt algorithm:
I just wrote a cosine function called c_os, for no special reason.
It calls no functions that I haven't also written.
On my machine, it seems to work better than
my MS compiler's standard library cos function.
They don't get the zeros right. I do.
c_os(-123 * pi / 6) is 0.000000e+000
c_os(-129 * pi / 6) is 0.000000e+000
cos(-123 * pi / 6) is 7.839514e-015
cos(-129 * pi / 6) is -4.409261e-015
/* BEGIN c_os.c output */
const double pi = 4 * atan(1);
c_os(-120 * pi / 6) is 1.000000e+000
c_os(-121 * pi / 6) is 8.660254e-001
c_os(-122 * pi / 6) is 5.000000e-001
c_os(-123 * pi / 6) is 0.000000e+000
c_os(-124 * pi / 6) is -5.000000e-001
c_os(-125 * pi / 6) is -8.660254e-001
c_os(-126 * pi / 6) is -1.000000e+000
c_os(-127 * pi / 6) is -8.660254e-001
c_os(-128 * pi / 6) is -5.000000e-001
c_os(-129 * pi / 6) is 0.000000e+000
c_os(-130 * pi / 6) is 5.000000e-001
c_os(-131 * pi / 6) is 8.660254e-001
cos(-120 * pi / 6) is 1.000000e+000
cos(-121 * pi / 6) is 8.660254e-001
cos(-122 * pi / 6) is 5.000000e-001
cos(-123 * pi / 6) is 7.839514e-015
cos(-124 * pi / 6) is -5.000000e-001
cos(-125 * pi / 6) is -8.660254e-001
cos(-126 * pi / 6) is -1.000000e+000
cos(-127 * pi / 6) is -8.660254e-001
cos(-128 * pi / 6) is -5.000000e-001
cos(-129 * pi / 6) is -4.409261e-015
cos(-130 * pi / 6) is 5.000000e-001
cos(-131 * pi / 6) is 8.660254e-001
/* END c_os.c output */
/* BEGIN c_os.c */
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <errno.h>
double c_os(double x);
double p_i(void);
double sq_rt(double x);
int main(void)
{
const double pi = 4 * atan(1);
puts("/* BEGIN c_os.c output */\n");
puts("const double pi = 4 * atan(1);\n");
printf("c_os(-120 * pi / 6) is %e\n", c_os(-120 * pi / 6));
printf("c_os(-121 * pi / 6) is %e\n", c_os(-121 * pi / 6));
printf("c_os(-122 * pi / 6) is %e\n", c_os(-122 * pi / 6));
printf("c_os(-123 * pi / 6) is %e\n", c_os(-123 * pi / 6));
printf("c_os(-124 * pi / 6) is %e\n", c_os(-124 * pi / 6));
printf("c_os(-125 * pi / 6) is %e\n", c_os(-125 * pi / 6));
printf("c_os(-126 * pi / 6) is %e\n", c_os(-126 * pi / 6));
printf("c_os(-127 * pi / 6) is %e\n", c_os(-127 * pi / 6));
printf("c_os(-128 * pi / 6) is %e\n", c_os(-128 * pi / 6));
printf("c_os(-129 * pi / 6) is %e\n", c_os(-129 * pi / 6));
printf("c_os(-130 * pi / 6) is %e\n", c_os(-130 * pi / 6));
printf("c_os(-131 * pi / 6) is %e\n", c_os(-131 * pi / 6));
putchar('\n');
printf("cos(-120 * pi / 6) is %e\n", cos(-120 * pi / 6));
printf("cos(-121 * pi / 6) is %e\n", cos(-121 * pi / 6));
printf("cos(-122 * pi / 6) is %e\n", cos(-122 * pi / 6));
printf("cos(-123 * pi / 6) is %e\n", cos(-123 * pi / 6));
printf("cos(-124 * pi / 6) is %e\n", cos(-124 * pi / 6));
printf("cos(-125 * pi / 6) is %e\n", cos(-125 * pi / 6));
printf("cos(-126 * pi / 6) is %e\n", cos(-126 * pi / 6));
printf("cos(-127 * pi / 6) is %e\n", cos(-127 * pi / 6));
printf("cos(-128 * pi / 6) is %e\n", cos(-128 * pi / 6));
printf("cos(-129 * pi / 6) is %e\n", cos(-129 * pi / 6));
printf("cos(-130 * pi / 6) is %e\n", cos(-130 * pi / 6));
printf("cos(-131 * pi / 6) is %e\n", cos(-131 * pi / 6));
puts("\n/* END c_os.c output */");
return 0;
}
double c_os(double x)
{
unsigned n, negative, sine;
double a, b, c;
static double pi, two_pi, four_pi, half_pi, quarter_pi;
if (x >= -DBL_MAX && DBL_MAX >= x) {
if (1 > pi) {
pi = p_i();
two_pi = 2 * pi;
four_pi = 4 * pi;
half_pi = pi / 2;
quarter_pi = pi / 4;
}
if (0 > x) {
x = -x;
}
while (x > two_pi) {
b = x / 2;
a = two_pi;
while (b > a) {
a *= 2;
}
x -= a;
}
if (x > pi) {
x = two_pi - x;
}
if (x > half_pi) {
x = pi - x;
negative = 1;
} else {
negative = 0;
}
if (x > quarter_pi) {
x = half_pi - x;
sine = 1;
} else {
sine = 0;
}
c = x * x;
x = n = 0;
a = 1;
do {
b = a;
a *= c / ++n;
a /= ++n;
b -= a;
a *= c / ++n;
a /= ++n;
x += b;
} while (b > DBL_EPSILON / 2);
if (sine) {
x = sq_rt(1 - x * x);
}
if (negative) {
x = -x;
}
} else {
x = -HUGE_VAL;
errno = EDOM;
}
return x;
}
double p_i(void)
{
unsigned n;
double p, a, b;
p = 0;
a = 3;
n = 1;
do {
a /= 9;
b = a / n;
a /= 9;
n += 2;
b -= a / n;
n += 2;
p += b;
} while (b > DBL_EPSILON / 4);
a = 2;
n = 1;
do {
a /= 4;
b = a / n;
a /= 4;
n += 2;
b -= a / n;
n += 2;
p += b;
} while (b > DBL_EPSILON / 2);
return 4 * p;
}
double sq_rt(double x)
{
int n;
double a, b;
if (DBL_MAX >= x) {
if (x > 0) {
for (n = 0; x > 2; x /= 4) {
++n;
}
while (0.5 > x) {
--n;
x *= 4;
}
a = x;
b = (1 + x) / 2;
do {
x = b;
b = (a / x + x) / 2;
} while (x > b);
while (n > 0) {
x *= 2;
--n;
}
while (0 > n) {
x /= 2;
++n;
}
} else {
if (0 > x) {
errno = EDOM;
x = HUGE_VAL;
}
}
} else {
errno = ERANGE;
}
return x;
}
/* END c_os.c */