1 /*
2 WORLD.C
3
4 Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 and the "Aleph One" developers.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 This license is contained in the file "COPYING",
18 which is included with this source code; it is available online at
19 http://www.gnu.org/licenses/gpl.html
20
21 Sunday, May 31, 1992 3:57:12 PM
22
23 Friday, January 15, 1993 9:59:14 AM
24 added arctangent function.
25 Thursday, January 21, 1993 9:46:24 PM
26 fixed arctangent function. normalize_angle() could stand to be improved.
27 Saturday, January 23, 1993 9:46:34 PM
28 fixed arctangent, hopefully for the last time. normalize_angle() is a little faster.
29 Monday, January 25, 1993 3:01:47 PM
30 arctangent works (tested at 0.5� increments against SANE�s tan), the only anomoly was
31 apparently arctan(0)==180�.
32 Wednesday, January 27, 1993 3:49:04 PM
33 final fix to arctangent, we swear. recall lim(arctan(x)) as x approaches �/2 or 3�/4 is ��,
34 depending on which side we come from. because we didn't realize this, arctan failed in the
35 case where x was very close to but slightly below �/2. i think we�ve seen the last monster
36 suddenly �panic� and bolt directly into a wall.
37 Sunday, July 25, 1993 11:51:42 PM
38 the arctan of 0/0 is now (arbitrairly) �/2 because we�re sick of assert(y) failing.
39 Monday, June 20, 1994 4:15:06 PM
40 bug fix in translate_point3d().
41
42 Feb 10, 2000 (Loren Petrich):
43 Fixed range check in translate_point3d()
44
45 Feb 14, 2000 (Loren Petrich):
46 Doing some arithmetic as long values instead of short ones, so as to avoid annoying long-distance wraparound.
47
48 Feb 17, 2000 (Loren Petrich):
49 Fixed arctangent() so that it gets the values into the right octants, and then does a binary search
50
51 Jul 1, 2000 (Loren Petrich):
52 Inlined the angle normalization; doing it automatically for all the functions that work with angles
53 */
54
55 #include "cseries.h"
56 #include "world.h"
57 #include "FilmProfile.h"
58
59 #include <stdlib.h>
60 #include <math.h>
61 #include <limits.h>
62
63
64
65
66 /* ---------- globals */
67
68 int16 *cosine_table;
69 int16 *sine_table;
70 static int32 *tangent_table;
71
72 static uint16 random_seed= 0x1;
73 static uint16 local_random_seed= 0x1;
74
75 /* ---------- code */
76
77 /*
78 angle normalize_angle(
79 angle theta)
80 {
81 while (theta<0) theta+= NUMBER_OF_ANGLES;
82 while (theta>=NUMBER_OF_ANGLES) theta-= NUMBER_OF_ANGLES;
83
84 return theta;
85 }
86 */
87
88 /* remember this is not wholly accurate, both distance or the sine/cosine values could be
89 negative, and the shift can�t make negative numbers zero; this is probably ok because
90 we�ll have -1/1024th instead of zero, which is basically our margin for error anyway ... */
translate_point2d(world_point2d * point,world_distance distance,angle theta)91 world_point2d *translate_point2d(
92 world_point2d *point,
93 world_distance distance,
94 angle theta)
95 {
96 // LP change: idiot-proofed this
97 theta = normalize_angle(theta);
98 fc_assert(cosine_table[0]==TRIG_MAGNITUDE);
99
100 point->x+= (distance*cosine_table[theta])>>TRIG_SHIFT;
101 point->y+= (distance*sine_table[theta])>>TRIG_SHIFT;
102
103 return point;
104 }
105
106 /* same comment as above */
translate_point3d(world_point3d * point,world_distance distance,angle theta,angle phi)107 world_point3d *translate_point3d(
108 world_point3d *point,
109 world_distance distance,
110 angle theta,
111 angle phi)
112 {
113 world_distance transformed_distance;
114
115 // LP change: idiot-proofed this
116 theta = normalize_angle(theta);
117 phi = normalize_angle(phi);
118
119 transformed_distance= (distance*cosine_table[phi])>>TRIG_SHIFT;
120 point->x+= (transformed_distance*cosine_table[theta])>>TRIG_SHIFT;
121 point->y+= (transformed_distance*sine_table[theta])>>TRIG_SHIFT;
122 point->z+= (distance*sine_table[phi])>>TRIG_SHIFT;
123
124 return point;
125 }
126
rotate_point2d(world_point2d * point,world_point2d * origin,angle theta)127 world_point2d *rotate_point2d(
128 world_point2d *point,
129 world_point2d *origin,
130 angle theta)
131 {
132 // LP change: lengthening the values for more precise calculations
133 long_vector2d temp;
134
135 theta = normalize_angle(theta);
136 fc_assert(cosine_table[0]==TRIG_MAGNITUDE);
137
138 temp.i= int32(point->x)-int32(origin->x);
139 temp.j= int32(point->y)-int32(origin->y);
140
141 point->x= ((temp.i*cosine_table[theta])>>TRIG_SHIFT) + ((temp.j*sine_table[theta])>>TRIG_SHIFT) +
142 origin->x;
143 point->y= ((temp.j*cosine_table[theta])>>TRIG_SHIFT) - ((temp.i*sine_table[theta])>>TRIG_SHIFT) +
144 origin->y;
145
146 return point;
147 }
148
transform_point2d(world_point2d * point,world_point2d * origin,angle theta)149 world_point2d *transform_point2d(
150 world_point2d *point,
151 world_point2d *origin,
152 angle theta)
153 {
154 // LP change: lengthening the values for more precise calculations
155 long_vector2d temp;
156
157 theta = normalize_angle(theta);
158 fc_assert(cosine_table[0]==TRIG_MAGNITUDE);
159
160 temp.i= int32(point->x)-int32(origin->x);
161 temp.j= int32(point->y)-int32(origin->y);
162
163 point->x= ((temp.i*cosine_table[theta])>>TRIG_SHIFT) + ((temp.j*sine_table[theta])>>TRIG_SHIFT);
164 point->y= ((temp.j*cosine_table[theta])>>TRIG_SHIFT) - ((temp.i*sine_table[theta])>>TRIG_SHIFT);
165
166 return point;
167 }
168
transform_point3d(world_point3d * point,world_point3d * origin,angle theta,angle phi)169 world_point3d *transform_point3d(
170 world_point3d *point,
171 world_point3d *origin,
172 angle theta,
173 angle phi)
174 {
175 // LP change: lengthening the values for more precise calculations
176 long_vector3d temporary;
177
178 temporary.i= int32(point->x)-int32(origin->x);
179 temporary.j= int32(point->y)-int32(origin->y);
180 temporary.k= int32(point->z)-int32(origin->z);
181
182 /* do theta rotation (in x-y plane) */
183 point->x= ((temporary.i*cosine_table[theta])>>TRIG_SHIFT) + ((temporary.j*sine_table[theta])>>TRIG_SHIFT);
184 point->y= ((temporary.j*cosine_table[theta])>>TRIG_SHIFT) - ((temporary.i*sine_table[theta])>>TRIG_SHIFT);
185
186 /* do phi rotation (in x-z plane) */
187 if (phi)
188 {
189 temporary.i= point->x;
190 /* temporary.z is already set */
191
192 point->x= ((temporary.i*cosine_table[phi])>>TRIG_SHIFT) + ((temporary.k*sine_table[phi])>>TRIG_SHIFT);
193 point->z= ((temporary.k*cosine_table[phi])>>TRIG_SHIFT) - ((temporary.i*sine_table[phi])>>TRIG_SHIFT);
194 /* y-coordinate is unchanged */
195 }
196 else
197 {
198 point->z= temporary.k;
199 }
200
201 return point;
202 }
203
build_trig_tables(void)204 void build_trig_tables(
205 void)
206 {
207 short i;
208 double two_pi= 8.0*atan(1.0);
209 double theta;
210
211 sine_table= (int16 *) malloc(sizeof(int16)*NUMBER_OF_ANGLES);
212 cosine_table= (int16 *) malloc(sizeof(int16)*NUMBER_OF_ANGLES);
213 tangent_table= (int32 *) malloc(sizeof(int32)*NUMBER_OF_ANGLES);
214 fc_assert(sine_table&&cosine_table&&tangent_table);
215
216 for (i=0;i<NUMBER_OF_ANGLES;++i)
217 {
218 theta= two_pi*(double)i/(double)NUMBER_OF_ANGLES;
219
220 cosine_table[i]= (short) ((double)TRIG_MAGNITUDE*cos(theta)+0.5);
221 sine_table[i]= (short) ((double)TRIG_MAGNITUDE*sin(theta)+0.5);
222
223 if (i==0) sine_table[i]= 0, cosine_table[i]= TRIG_MAGNITUDE;
224 if (i==QUARTER_CIRCLE) sine_table[i]= TRIG_MAGNITUDE, cosine_table[i]= 0;
225 if (i==HALF_CIRCLE) sine_table[i]= 0, cosine_table[i]= -TRIG_MAGNITUDE;
226 if (i==THREE_QUARTER_CIRCLE) sine_table[i]= -TRIG_MAGNITUDE, cosine_table[i]= 0;
227
228 /* what we care about here is NOT accuracy, rather we�re concerned with matching the
229 ratio of the existing sine and cosine tables as exactly as possible */
230 if (cosine_table[i])
231 {
232 tangent_table[i]= ((TRIG_MAGNITUDE*sine_table[i])/cosine_table[i]);
233 }
234 else
235 {
236 /* we always take -�, even though the limit is ��, depending on which side you
237 approach it from. this is because of the direction we traverse the circle
238 looking for matches during arctan. */
239 tangent_table[i]= INT32_MIN;
240 }
241 }
242 }
243
m2_arctangent(int32 xx,int32 yy)244 static angle m2_arctangent(
245 int32 xx,
246 int32 yy)
247 {
248 // the original Marathon 2 function took world_distance parameters
249 world_distance x = xx;
250 world_distance y = yy;
251
252 long tangent;
253 long last_difference, new_difference;
254 angle search_arc, theta;
255
256 if (x)
257 {
258 tangent= (TRIG_MAGNITUDE*y)/x;
259
260 if (tangent)
261 {
262 theta= (y>0) ? 1 : HALF_CIRCLE+1;
263 if (tangent<0) theta+= QUARTER_CIRCLE;
264
265 last_difference= tangent-tangent_table[theta-1];
266 for (search_arc=QUARTER_CIRCLE-1;search_arc;search_arc--,theta++)
267 {
268 new_difference= tangent-tangent_table[theta];
269
270 if ((last_difference<=0&&new_difference>=0) || (last_difference>=0&&new_difference<=0))
271 {
272 if (ABS(last_difference)<ABS(new_difference))
273 {
274 return theta-1;
275 }
276 else
277 {
278 return theta;
279 }
280 }
281
282 last_difference= new_difference;
283 }
284
285 return theta==NUMBER_OF_ANGLES ? 0 : theta;
286 }
287 else
288 {
289 return x<0 ? HALF_CIRCLE : 0;
290 }
291 }
292 else
293 {
294 /* so arctan(0,0)==�/2 (bill me) */
295 return y<0 ? THREE_QUARTER_CIRCLE : QUARTER_CIRCLE;
296 }
297 }
298 /* one day we�ll come back here and actually make this run fast */
299 // LP change: made this long-distance friendly
300 //
a1_arctangent(int32 x,int32 y)301 static angle a1_arctangent(
302 int32 x, // world_distance x,
303 int32 y) // world_distance y)
304 {
305 int32 tangent;
306 angle theta;
307
308 // LP change: reworked everything in here
309
310 // Intermediate transformed values
311 int32 xtfm = x, ytfm = y;
312
313 // Initial angle:
314 theta = 0;
315
316 // Reduce 2nd/3rd quadrant to 1st/4th quadrant
317 if (xtfm < 0)
318 {
319 xtfm = -xtfm;
320 ytfm = -ytfm;
321 theta += HALF_CIRCLE;
322 }
323
324 // Reduce 4th quadrant to 1st quadrant
325 if (ytfm < 0)
326 {
327 int32 temp = ytfm;
328 ytfm = xtfm;
329 xtfm = - temp;
330 theta += THREE_QUARTER_CIRCLE;
331 }
332
333 // The 1st quadrant has two octants; which one to choose?
334 bool other_octant = false;
335 if (ytfm > xtfm)
336 {
337 // Choosing the second octant instead of the first one..
338 other_octant = true;
339 int32 temp = ytfm;
340 ytfm = xtfm;
341 xtfm = temp;
342 }
343
344 // Find the tangent; exit if both xtfm and ytfm are 0
345 if (xtfm == 0) return 0;
346 tangent= (TRIG_MAGNITUDE*ytfm)/xtfm;
347
348 // Find the search endpoints and test them:
349 angle dtheta = 0, dth0 = 0, dth1 = EIGHTH_CIRCLE;
350 int32 tan0 = tangent_table[dth0];
351 int32 tan1 = tangent_table[dth1];
352 if (tangent <= tan0) dtheta = dth0;
353 else if (tangent >= tan1) dtheta = dth1;
354 else
355 {
356 // Do binary search
357 bool exact_hit = false;
358 while(dth1 > dth0+1)
359 {
360 // Divide the interval in half
361 angle dthnew = (dth0 + dth1) >> 1;
362 // Where's the point?
363 int32 tannew = tangent_table[dthnew];
364 if (tangent > tannew)
365 {
366 dth0 = dthnew;
367 tan0 = tannew;
368 }
369 else if (tangent < tannew)
370 {
371 dth1 = dthnew;
372 tan1 = tannew;
373 }
374 else
375 {
376 dtheta = dthnew;
377 exact_hit = true;
378 break;
379 }
380 }
381 // If didn't hit exactly, find the closest one
382 if (!exact_hit)
383 {
384 if ((tan1 - tangent) < (tangent - tan0))
385 dtheta = dth1;
386 else
387 dtheta = dth0;
388 }
389 }
390
391 // Adjust the octant and add in
392 if (other_octant) dtheta = QUARTER_CIRCLE - dtheta;
393 theta += dtheta;
394
395 // Idiot-proofed exit
396 return NORMALIZE_ANGLE(theta);
397 }
398
arctangent(int32 x,int32 y)399 angle arctangent(int32 x, int32 y)
400 {
401 if (film_profile.long_distance_physics)
402 {
403 return a1_arctangent(x, y);
404 }
405 else
406 {
407 return m2_arctangent(x, y);
408 }
409 }
410
set_random_seed(uint16 seed)411 void set_random_seed(
412 uint16 seed)
413 {
414 random_seed= seed ? seed : DEFAULT_RANDOM_SEED;
415 }
416
get_random_seed(void)417 uint16 get_random_seed(
418 void)
419 {
420 return random_seed;
421 }
422
global_random(void)423 uint16 global_random(
424 void)
425 {
426 uint16 seed= random_seed;
427
428 if (seed&1)
429 {
430 seed= (seed>>1)^0xb400;
431 }
432 else
433 {
434 seed>>= 1;
435 }
436
437 return (random_seed= seed);
438 }
439
local_random(void)440 uint16 local_random(
441 void)
442 {
443 uint16 seed= local_random_seed;
444
445 if (seed&1)
446 {
447 seed= (seed>>1)^0xb400;
448 }
449 else
450 {
451 seed>>= 1;
452 }
453
454 return (local_random_seed= seed);
455 }
456
guess_distance2d(world_point2d * p0,world_point2d * p1)457 world_distance guess_distance2d(
458 world_point2d *p0,
459 world_point2d *p1)
460 {
461 int32 dx= (int32)p0->x - p1->x;
462 int32 dy= (int32)p0->y - p1->y;
463 int32 distance;
464
465 if (dx<0) dx= -dx;
466 if (dy<0) dy= -dy;
467 distance= GUESS_HYPOTENUSE(dx, dy);
468
469 return distance>INT16_MAX ? INT16_MAX : distance;
470 }
471
472 // Return min(round(distance), INT16_MAX)
distance3d(world_point3d * p0,world_point3d * p1)473 world_distance distance3d(
474 world_point3d *p0,
475 world_point3d *p1)
476 {
477 int32 dx= (int32)p0->x - p1->x;
478 int32 dy= (int32)p0->y - p1->y;
479 int32 dz= (int32)p0->z - p1->z;
480 const Sint64 dist_squared = 1LL*dx*dx + 1LL*dy*dy + 1LL*dz*dz; // [0, ~2^33.6]
481 return dist_squared < 1L*INT16_MAX*INT16_MAX ? isqrt(dist_squared) : INT16_MAX;
482 }
483
484 // Return round(distance) if distance < 65536, else nonsense value round(sqrt(distance^2 - 2^32)); output in [0, 65536]
m2_distance2d_int32(const world_point2d * p0,const world_point2d * p1)485 static int32 m2_distance2d_int32(
486 const world_point2d* p0,
487 const world_point2d* p1)
488 {
489 const int32 dx = 1L*p1->x - p0->x; // [-65535, 65535]
490 const int32 dy = 1L*p1->y - p0->y; // [-65535, 65535]
491 const Sint64 dist_squared = 1LL*dx*dx + 1LL*dy*dy; // [0, ~2^33]
492 return isqrt(uint32(dist_squared));
493 }
494
m2_distance2d(world_point2d * p0,world_point2d * p1)495 static world_distance m2_distance2d(
496 world_point2d *p0,
497 world_point2d *p1)
498 {
499 return int16(m2_distance2d_int32(p0, p1));
500 }
501
a1_distance2d(world_point2d * p0,world_point2d * p1)502 static world_distance a1_distance2d(
503 world_point2d *p0,
504 world_point2d *p1)
505 {
506 const int32 distance = m2_distance2d_int32(p0, p1);
507 return distance>INT16_MAX ? INT16_MAX : distance;
508 }
509
distance2d(world_point2d * p0,world_point2d * p1)510 world_distance distance2d(
511 world_point2d *p0,
512 world_point2d *p1)
513 {
514 if (film_profile.long_distance_physics)
515 {
516 return a1_distance2d(p0, p1);
517 }
518 else
519 {
520 return m2_distance2d(p0, p1);
521 }
522 }
523
524 /*
525 * It requires more space to describe this implementation of the manual
526 * square root algorithm than it did to code it. The basic idea is that
527 * the square root is computed one bit at a time from the high end. Because
528 * the original number is 32 bits (unsigned), the root cannot exceed 16 bits
529 * in length, so we start with the 0x8000 bit.
530 *
531 * Let "x" be the value whose root we desire, "t" be the square root
532 * that we desire, and "s" be a bitmask. A simple way to compute
533 * the root is to set "s" to 0x8000, and loop doing the following:
534 *
535 * t = 0;
536 * s = 0x8000;
537 * do {
538 * if ((t + s) * (t + s) <= x)
539 * t += s;
540 * s >>= 1;
541 * while (s != 0);
542 *
543 * The primary disadvantage to this approach is the multiplication. To
544 * eliminate this, we begin simplying. First, we observe that
545 *
546 * (t + s) * (t + s) == (t * t) + (2 * t * s) + (s * s)
547 *
548 * Therefore, if we redefine "x" to be the original argument minus the
549 * current value of (t * t), we can determine if we should add "s" to
550 * the root if
551 *
552 * (2 * t * s) + (s * s) <= x
553 *
554 * If we define a new temporary "nr", we can express this as
555 *
556 * t = 0;
557 * s = 0x8000;
558 * do {
559 * nr = (2 * t * s) + (s * s);
560 * if (nr <= x) {
561 * x -= nr;
562 * t += s;
563 * }
564 * s >>= 1;
565 * while (s != 0);
566 *
567 * We can improve the performance of this by noting that "s" is always a
568 * power of two, so multiplication by "s" is just a shift. Also, because
569 * "s" changes in a predictable manner (shifted right after each iteration)
570 * we can precompute (0x8000 * t) and (0x8000 * 0x8000) and then adjust
571 * them by shifting after each step. First, we let "m" hold the value
572 * (s * s) and adjust it after each step by shifting right twice. We
573 * also introduce "r" to hold (2 * t * s) and adjust it after each step
574 * by shifting right once. When we update "t" we must also update "r",
575 * and we do so by noting that (2 * (old_t + s) * s) is the same as
576 * (2 * old_t * s) + (2 * s * s). Noting that (s * s) is "m" and that
577 * (r + 2 * m) == ((r + m) + m) == (nr + m):
578 *
579 * t = 0;
580 * s = 0x8000;
581 * m = 0x40000000;
582 * r = 0;
583 * do {
584 * nr = r + m;
585 * if (nr <= x) {
586 * x -= nr;
587 * t += s;
588 * r = nr + m;
589 * }
590 * s >>= 1;
591 * r >>= 1;
592 * m >>= 2;
593 * } while (s != 0);
594 *
595 * Finally, we note that, if we were using fractional arithmetic, after
596 * 16 iterations "s" would be a binary 0.5, so the value of "r" when
597 * the loop terminates is (2 * t * 0.5) or "t". Because the values in
598 * "t" and "r" are identical after the loop terminates, and because we
599 * do not otherwise use "t" explicitly within the loop, we can omit it.
600 * When we do so, there is no need for "s" except to terminate the loop,
601 * but we observe that "m" will become zero at the same time as "s",
602 * so we can use it instead.
603 *
604 * The result we have at this point is the floor of the square root. If
605 * we want to round to the nearest integer, we need to consider whether
606 * the remainder in "x" is greater than or equal to the difference
607 * between ((r + 0.5) * (r + 0.5)) and (r * r). Noting that the former
608 * quantity is (r * r + r + 0.25), we want to check if the remainder is
609 * greater than or equal to (r + 0.25). Because we are dealing with
610 * integers, we can't have equality, so we round up if "x" is strictly
611 * greater than "r":
612 *
613 * if (x > r)
614 * r++;
615 */
616
isqrt(uint32 x)617 int32 isqrt(uint32 x)
618 {
619 uint32 r, nr, m;
620
621 r= 0;
622 m= 0x40000000;
623
624 do
625 {
626 nr= r + m;
627 if (nr<=x)
628 {
629 x-= nr;
630 r= nr + m;
631 }
632 r>>= 1;
633 m>>= 2;
634 }
635 while (m!=0);
636
637 if (x>r) r+= 1;
638 return r;
639 }
640
641 // LP additions: stuff for handling long-distance views
642
long_to_overflow_short_2d(long_vector2d & LVec,world_point2d & WVec,uint16 & flags)643 void long_to_overflow_short_2d(long_vector2d& LVec, world_point2d& WVec, uint16& flags)
644 {
645 // Clear upper byte of flags
646 flags &= 0x00ff;
647
648 // Extract upper digits and put them into place
649 uint16 xupper = uint16(LVec.i >> 16) & 0x000f;
650 uint16 yupper = uint16(LVec.j >> 16) & 0x000f;
651
652 // Put them into place
653 flags |= xupper << 12;
654 flags |= yupper << 8;
655
656 // Move lower values
657 WVec.x = LVec.i;
658 WVec.y = LVec.j;
659 }
660
overflow_short_to_long_2d(world_point2d & WVec,uint16 & flags,long_vector2d & LVec)661 void overflow_short_to_long_2d(world_point2d& WVec, uint16& flags, long_vector2d& LVec)
662 {
663 // Move lower values
664 LVec.i = int32(WVec.x) & 0x0000ffff;
665 LVec.j = int32(WVec.y) & 0x0000ffff;
666
667 // Extract upper digits
668 uint16 xupper = (flags >> 12) & 0x000f;
669 uint16 yupper = (flags >> 8) & 0x000f;
670
671 // Sign-extend them
672 if (xupper & 0x0008) xupper |= 0xfff0;
673 if (yupper & 0x0008) yupper |= 0xfff0;
674
675 // Put them into place
676 LVec.i |= int32(xupper) << 16;
677 LVec.j |= int32(yupper) << 16;
678 }
679
680
transform_overflow_point2d(world_point2d * point,world_point2d * origin,angle theta,uint16 * flags)681 world_point2d *transform_overflow_point2d(
682 world_point2d *point,
683 world_point2d *origin,
684 angle theta,
685 uint16 *flags)
686 {
687 // LP change: lengthening the values for more precise calculations
688 long_vector2d temp, tempr;
689
690 theta = normalize_angle(theta);
691 fc_assert(cosine_table[0]==TRIG_MAGNITUDE);
692
693 temp.i= int32(point->x)-int32(origin->x);
694 temp.j= int32(point->y)-int32(origin->y);
695
696 tempr.i= ((temp.i*cosine_table[theta])>>TRIG_SHIFT) + ((temp.j*sine_table[theta])>>TRIG_SHIFT);
697 tempr.j= ((temp.j*cosine_table[theta])>>TRIG_SHIFT) - ((temp.i*sine_table[theta])>>TRIG_SHIFT);
698
699 long_to_overflow_short_2d(tempr,*point,*flags);
700
701 return point;
702 }
703