eigenmath/cos.cpp

381 lines
4.3 KiB
C++
Raw Permalink Normal View History

2005-10-16 00:10:22 +02:00
// Cosine function of numerical and symbolic arguments
2004-06-18 01:02:29 +02:00
#include "stdafx.h"
2004-03-03 21:24:06 +01:00
#include "defs.h"
void
eval_cos(void)
{
push(cadr(p1));
eval();
cosine();
}
void
cosine(void)
{
save();
2007-05-09 04:45:06 +02:00
yycosine_phase();
2004-03-03 21:24:06 +01:00
restore();
}
2007-05-09 04:45:06 +02:00
void
yycosine_phase(void)
{
int n = 0;
p1 = pop();
if (car(p1) != symbol(ADD)) {
push(p1);
yycosine();
return;
}
p2 = cdr(p1);
while (iscons(p2)) {
n = isnpi(car(p2));
if (n)
break;
p2 = cdr(p2);
}
if (n == 0) {
push(p1);
yycosine();
return;
}
push(p1);
push(car(p2));
subtract(); // remove phase
switch (n) {
case 1:
yysine();
negate();
break;
case 2:
yycosine();
negate();
break;
case 3:
yysine();
break;
case 4:
yycosine();
break;
}
}
2005-10-15 22:41:33 +02:00
void
yycosine(void)
2004-03-03 21:24:06 +01:00
{
int n;
double d;
p1 = pop();
2006-04-19 01:18:30 +02:00
if (car(p1) == symbol(ARCCOS)) {
push(cadr(p1));
return;
}
2005-08-06 22:57:37 +02:00
if (isdouble(p1)) {
2004-03-03 21:24:06 +01:00
d = cos(p1->u.d);
if (fabs(d) < 1e-10)
d = 0.0;
push_double(d);
return;
}
2007-05-09 04:45:06 +02:00
// cosine function is symmetric, cos(-x) = cos(x)
if (isnegative(p1)) {
push(p1);
negate();
p1 = pop();
}
2006-02-11 21:11:26 +01:00
// cos(arctan(x)) = 1 / sqrt(1 + x^2)
// see p. 173 of the CRC Handbook of Mathematical Sciences
if (car(p1) == symbol(ARCTAN)) {
push_integer(1);
push(cadr(p1));
push_integer(2);
power();
add();
push_rational(-1, 2);
power();
return;
}
2004-03-03 21:24:06 +01:00
// multiply by 180/pi
push(p1);
push_integer(180);
multiply();
push_symbol(PI);
divide();
n = pop_integer();
if (n < 0) {
2005-10-15 22:41:33 +02:00
push(symbol(COS));
2004-03-03 21:24:06 +01:00
push(p1);
list(2);
return;
}
switch (n % 360) {
2005-10-15 22:41:33 +02:00
case 90:
case 270:
push_integer(0);
2004-03-03 21:24:06 +01:00
break;
case 60:
2005-10-15 22:41:33 +02:00
case 300:
2004-03-03 21:24:06 +01:00
push_rational(1, 2);
break;
case 120:
2005-10-15 22:41:33 +02:00
case 240:
2004-03-03 21:24:06 +01:00
push_rational(-1, 2);
break;
2005-10-15 22:41:33 +02:00
case 45:
case 315:
push_rational(1, 2);
push_integer(2);
push_rational(1, 2);
power();
multiply();
2004-03-03 21:24:06 +01:00
break;
2005-10-15 22:41:33 +02:00
case 135:
case 225:
2004-03-03 21:24:06 +01:00
push_rational(-1, 2);
2005-10-15 22:41:33 +02:00
push_integer(2);
push_rational(1, 2);
power();
multiply();
2004-03-03 21:24:06 +01:00
break;
2005-10-15 22:41:33 +02:00
case 30:
case 330:
push_rational(1, 2);
push_integer(3);
push_rational(1, 2);
power();
multiply();
2004-03-03 21:24:06 +01:00
break;
2005-10-15 22:41:33 +02:00
case 150:
case 210:
push_rational(-1, 2);
push_integer(3);
2004-03-03 21:24:06 +01:00
push_rational(1, 2);
2005-10-15 22:41:33 +02:00
power();
multiply();
break;
case 0:
push_integer(1);
break;
case 180:
push_integer(-1);
2004-03-03 21:24:06 +01:00
break;
default:
2006-09-18 21:16:44 +02:00
push(symbol(COS));
2004-03-03 21:24:06 +01:00
push(p1);
list(2);
break;
}
}
2007-05-08 16:57:30 +02:00
#if SELFTEST
2004-03-03 21:24:06 +01:00
static char *s[] = {
2005-10-15 22:41:33 +02:00
"cos(x)",
"cos(x)",
"cos(-x)",
"cos(x)",
"cos(b-a)",
"cos(a-b)",
// check against the floating point math library
"f(a,x)=1+cos(float(a/360*2*pi))-float(x)+cos(a/360*2*pi)-x",
2004-03-03 21:24:06 +01:00
"",
2005-10-15 22:41:33 +02:00
"f(0,1)", // 0
"1",
"f(90,0)", // 90
"1",
"f(180,-1)", // 180
"1",
"f(270,0)", // 270
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(360,1)", // 360
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-90,0)", // -90
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-180,-1)", // -180
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-270,0)", // -270
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-360,1)", // -360
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(45,sqrt(2)/2)", // 45
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(135,-sqrt(2)/2)", // 135
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(225,-sqrt(2)/2)", // 225
2004-03-03 21:24:06 +01:00
"1",
2005-10-15 22:41:33 +02:00
"f(315,sqrt(2)/2)", // 315
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-45,sqrt(2)/2)", // -45
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-135,-sqrt(2)/2)", // -135
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-225,-sqrt(2)/2)", // -225
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-315,sqrt(2)/2)", // -315
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(30,sqrt(3)/2)", // 30
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(150,-sqrt(3)/2)", // 150
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(210,-sqrt(3)/2)", // 210
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(330,sqrt(3)/2)", // 330
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-30,sqrt(3)/2)", // -30
"1",
2004-03-03 21:24:06 +01:00
2005-10-15 22:41:33 +02:00
"f(-150,-sqrt(3)/2)", // -150
"1",
2005-10-15 22:41:33 +02:00
"f(-210,-sqrt(3)/2)", // -210
"1",
2005-10-15 22:41:33 +02:00
"f(-330,sqrt(3)/2)", // -330
"1",
2005-10-15 22:41:33 +02:00
"f(60,1/2)", // 60
"1",
"f(120,-1/2)", // 120
"1",
"f(240,-1/2)", // 240
"1",
"f(300,1/2)", // 300
"1",
"f(-60,1/2)", // -60
"1",
"f(-120,-1/2)", // -120
"1",
"f(-240,-1/2)", // -240
"1",
"f(-300,1/2)", // -300
"1",
"f=quote(f)",
"",
2006-04-19 01:18:30 +02:00
"cos(arccos(x))",
"x",
2006-05-06 01:57:37 +02:00
2006-09-18 21:16:44 +02:00
// bug fix for version 119
"cos(1/12*pi)",
"cos(1/12*pi)",
2007-05-09 04:45:06 +02:00
"cos(arctan(4/3))",
"3/5",
"cos(-arctan(4/3))",
"3/5",
// phase
"cos(x-8/2*pi)",
"cos(x)",
"cos(x-7/2*pi)",
"-sin(x)",
"cos(x-6/2*pi)",
"-cos(x)",
"cos(x-5/2*pi)",
"sin(x)",
"cos(x-4/2*pi)",
"cos(x)",
"cos(x-3/2*pi)",
"-sin(x)",
"cos(x-2/2*pi)",
"-cos(x)",
"cos(x-1/2*pi)",
"sin(x)",
"cos(x+0/2*pi)",
"cos(x)",
"cos(x+1/2*pi)",
"-sin(x)",
"cos(x+2/2*pi)",
"-cos(x)",
"cos(x+3/2*pi)",
"sin(x)",
"cos(x+4/2*pi)",
"cos(x)",
"cos(x+5/2*pi)",
"-sin(x)",
"cos(x+6/2*pi)",
"-cos(x)",
"cos(x+7/2*pi)",
"sin(x)",
"cos(x+8/2*pi)",
"cos(x)",
2004-03-03 21:24:06 +01:00
};
void
test_cos(void)
{
test(__FILE__, s, sizeof s / sizeof (char *));
}
2007-05-08 16:57:30 +02:00
#endif