/* math.c */
int * sintable;
int * tantable;
int * sqrttable;
int nsqrt;
create() {
sintable = ({
0, 0,
1, 17,
2, 34,
3, 52,
4, 69,
5, 87,
6, 104,
7, 121,
8, 139,
9, 156,
10, 173,
11, 190,
12, 207,
13, 224,
14, 241,
15, 258,
16, 275,
17, 292,
18, 309,
19, 325,
20, 342,
21, 358,
22, 374,
23, 390,
24, 406,
25, 422,
26, 438,
27, 453,
28, 469,
29, 484,
30, 500,
31, 515,
32, 529,
33, 544,
34, 559,
35, 573,
36, 587,
37, 601,
38, 615,
39, 629,
40, 642,
41, 656,
42, 669,
43, 681,
44, 694,
45, 707,
46, 719,
47, 731,
48, 743,
49, 754,
50, 766,
51, 777,
52, 788,
53, 798,
54, 809,
55, 819,
56, 829,
57, 838,
58, 848,
59, 857,
60, 866,
61, 874,
62, 882,
63, 891,
64, 898,
65, 906,
66, 913,
67, 920,
68, 927,
69, 933,
70, 939,
71, 945,
72, 951,
73, 956,
74, 961,
75, 965,
76, 970,
77, 974,
78, 978,
79, 981,
80, 984,
81, 987,
82, 990,
83, 992,
84, 994,
85, 996,
86, 997,
87, 998,
88, 999,
89, 999,
90, 1000
});
tantable = ({
0, 0,
1, 17,
2, 34,
3, 52,
4, 69,
5, 87,
6, 105,
7, 122,
8, 140,
9, 158,
10, 176,
11, 194,
12, 212,
13, 230,
14, 249,
15, 267,
16, 286,
17, 305,
18, 324,
19, 344,
20, 363,
21, 383,
22, 404,
23, 424,
24, 445,
25, 466,
26, 487,
27, 509,
28, 531,
29, 554,
30, 577,
31, 600,
32, 624,
33, 649,
34, 674,
35, 700,
36, 726,
37, 753,
38, 781,
39, 809,
40, 839,
41, 869,
42, 900,
43, 932,
44, 965,
45, 1000,
46, 1035,
47, 1072,
48, 1110,
49, 1150,
50, 1191,
51, 1234,
52, 1279,
53, 1327,
54, 1376,
55, 1428,
56, 1482,
57, 1539,
58, 1600,
59, 1664,
60, 1732,
61, 1804,
62, 1880,
63, 1962,
64, 2050,
65, 2144,
66, 2246,
67, 2355,
68, 2475,
69, 2605,
70, 2747,
71, 2904,
72, 3077,
73, 3270,
74, 3487,
75, 3732,
76, 4010,
77, 4331,
78, 4704,
79, 5144,
80, 5671,
81, 6313,
82, 7115,
83, 8144,
84, 9514,
85, 11430,
86, 14300,
87, 19081,
88, 28636,
89, 57289
});
sqrttable = ({
0,
1,
1,
2,
2,
2,
2,
3,
3,
3,
3,
3,
3,
4,
4,
4,
4,
4,
4,
4,
4,
5,
5,
5,
5,
5,
5,
5,
5,
5,
5,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
7,
7,
7,
7,
7,
7,
7,
7,
7,
7,
7,
7,
7,
7,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8
});
nsqrt = sizeof(sqrttable);
}
string repeat_str(string ch, int n) {
int i;
string tmp;
if (n<0) return "";
tmp = "";
for (i=0;i<n;i++) tmp += ch;
return tmp;
}
int sin(int theta)
{
int sign;
/* this returns the sin of an agnle * 1000 */
while(theta>360) theta -= 360;
while(theta<0) theta += 360;
if (theta > 180) {
sign=-1;
theta -= 180;
}
else sign = 1;
if (theta>90)
theta = 180 - theta;
return sign * sintable[theta*2+1];
}
int asin(int ratio) {
int sign;
int up, down, current;
if (ratio>1000 || ratio < -1000) {
throw("asin: illegal argument");
return 0;
}
if (ratio>=0) sign = 1;
else {
sign = -1;
ratio = -ratio;
}
up = 90;
down = 0;
current = (up+down)/2;
/* a binary search - worse case would take only 9 loops */
while(current!=up && current!=down) {
int tmp;
if ((tmp=sintable[current*2+1]) == ratio) return sign * current;
if (tmp < ratio) down = current;
else up = current;
current = (up+down)/2;
}
return sign*current;
}
int atan(int ratio) {
int sign;
int up, down,current;
sign = 1;
if (ratio<0) {
sign = -1;
ratio = -ratio;
}
up = 90;
down = 0;
current = (up+down)/2;
/* a binary search - worse case would take only 9 loops */
while(current!=up && current!=down) {
int tmp;
if ((tmp=tantable[current*2+1]) == ratio) return sign * current;
if (tmp < ratio) down = current;
else up = current;
current = (up+down)/2;
}
return sign*current;
}
/* 0 <= atan2 <= 2 PI */
int atan2(int x,int y) {
int ret;
if (!x) {
if (y>=0) return 90;
else return 270;
}
ret=atan(y*1000/x)+(x>0? 0 : 180) ;
return ret;
}
int cos(int theta)
{
return sin(theta + 90);
}
int tan(int theta)
{
int sign;
/* this returns the sin of an agnle * 1000 */
while(theta>180) theta -= 180;
while(theta<0) theta += 180;
if (theta==90) {
throw("tan: division by zero"); /* chuckle */
return 0;
}
sign = 1;
if (theta > 90) {
sign = -1;
theta = 180 - theta;
}
return sign * tantable[theta*2+1];
}
int sqrt(int num) {
int len, up, down, current;
string numstr;
if (num<0) {
throw("sqrt: negative");
return 0;
}
if (!num) return 0;
if (num<nsqrt) return sqrttable[num];
/* make an educated guess */
numstr=""+num;
len = strlen(numstr);
if (len/2*2==len) { /* even number of digits */
sscanf(repeat_str("9",len/2),"%d",up);
sscanf("1"+repeat_str("0",len/2-1),"%d",down);
} else {
sscanf(repeat_str("9",len/2+1),"%d",up);
sscanf("1"+repeat_str("0",len/2),"%d",down);
}
/* do a binary search within the 2 limits */
current = (up+down)/2;
while(current!=up && current!=down) {
int tmp;
tmp = current*current;
if (tmp==num) return current;
if (tmp < num) down = current;
else up = current;
current = (up+down)/2;
}
return current;
}