1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Header: r:/prj/lib/src/fixpp/RCS/fixpp.h 1.45 1994/08/08 18:27:45 ept Exp $
21  */
22 
23 /*
24 I'd like to dedicate this fixpoint library to Dan and Matt for their
25 inspirational bravery, and to C++ for being such a complex and neurotic
26 language.
27 */
28 
29 #ifndef __FIXPP_H
30 #define __FIXPP_H
31 
32 #include <istream>
33 #include <cstdio>
34 #include <cstdlib>
35 
36 extern "C" {
37 //#include "mprintf.h"
38 #include "fix.h" // A big thank you to Dan and Matt.
39 }
40 
41 // How many bits to shift an integer up to make it a fixpoint.
42 // ===========================================================
43 #ifdef FIXPOINT_SHIFTUP
44 #define SHIFTUP FIXPOINT_SHIFTUP
45 #else
46 #define SHIFTUP 16 // 16:16 default format.
47 #endif
48 
49 #define SHIFTMULTIPLIER (1 << SHIFTUP)
50 
51 // Here are some flags for your convenience.
52 // =========================================
53 
54 // Define this for some misc. debugging things like touch()
55 // ========================================================
56 //#define FIXDEBUG
57 
58 #ifdef FIXDEBUG
59 #define CLICK(c) c += (Fixpoint::click_bool)
60 #else
61 #define CLICK(c)
62 #endif
63 
64 // Here is a nice forward declaration.
65 // ===================================
66 
67 class Fixpoint;
68 
69 #define Q Fixpoint
70 
71 class Fixpoint {
72 
73     friend Fixpoint rawConstruct(int32_t l);
74 
75   public:
76     // The data is stored here.
77     // ========================
78     int32_t val;
79 
80     // Some invasive functions to get right at the internal rep.
81     // What?  Me not secure?  I'm no fascist.
82     // =========================================================
83 
84     uint32_t bits();
85     void setbits(uint32_t ul);
86 
87     // Constructors.
88     // =============
89 
90     Fixpoint();
91 
92     Fixpoint(const Fixpoint &);
93 
94     Fixpoint(int32_t i);
95 
96     Fixpoint(uint32_t i);
97 
98     Fixpoint(double);
99 
100     // Conversions.
101     // ============
102 
103     double to_double() const;
104 
105     float to_float() const;
106 
107     int32_t to_int() const;
108 
109     fix to_fix() const;
110 
111     fixang to_fixang() const;
112 
113     // Reverse Conversions.
114     // ====================
115 
116     void fix_to(fix);
117 
118     void fixang_to(fixang);
119 
120     // Assignments.
121     // ============
122 
123     // REMOVED!!!!
124 
125     // Arithmetic operators (homogeneous)!!
126     // ====================================
127 
128     Fixpoint &operator+=(Fixpoint);
129 
130     Fixpoint &operator-=(Fixpoint);
131 
132     Fixpoint &operator*=(Fixpoint);
133 
134     Fixpoint &operator/=(Fixpoint);
135 
136     Fixpoint &operator<<=(uint32_t n);
137 
138     Fixpoint &operator>>=(uint32_t n);
139 
140     Fixpoint operator-() const;
141 
142     Fixpoint operator+() const;
143 
144     int32_t operator<(const Fixpoint &) const;
145 
146     int32_t operator>(const Fixpoint &) const;
147 
148     int32_t operator<=(const Fixpoint &fp2) const;
149 
150     int32_t operator>=(const Fixpoint &fp2) const;
151 
152     int32_t operator==(const Fixpoint &fp2) const;
153 
154     int32_t operator!=(const Fixpoint &fp2) const;
155 
156     // Signed shifts
157     // =============
158 
159     void shift(int32_t n);
160     Fixpoint shifted(int32_t n) const;
161 
162     // Fast comparisons with zero (maybe... perhaps Q(0) isn't so slow after all)
163     // (and a trip down memory lane for FORTRAN-ites)
164     // ====================================
165 
166     int32_t gt_zero() const;
167 
168     int32_t ge_zero() const;
169 
170     int32_t eq_zero() const;
171 
172     int32_t ne_zero() const;
173 
174     int32_t le_zero() const;
175 
176     int32_t lt_zero() const;
177 
178     // Friendly math function declarations.
179     // ====================================
180 
181     friend inline Fixpoint sqrt(Fixpoint);
182     friend inline Fixpoint exp(Fixpoint);
183     friend inline int32_t floor(Fixpoint);
184     friend inline Fixpoint sin(Fixpoint);
185     friend inline Fixpoint cos(Fixpoint);
186     friend inline Fixpoint tan(Fixpoint);
187     friend inline Fixpoint acos(Fixpoint);
188     friend inline Fixpoint asin(Fixpoint);
189     friend inline void sincos(Fixpoint ang, Fixpoint *sn, Fixpoint *cs);
190     friend inline Fixpoint atan2(Fixpoint, Fixpoint);
191     friend inline Fixpoint fsin(Fixpoint);
192     friend inline Fixpoint fcos(Fixpoint);
193     friend inline void fsincos(Fixpoint ang, Fixpoint *sn, Fixpoint *cs);
194     friend inline Fixpoint abs(Fixpoint);
195 
196 #ifdef FIXDEBUG
197 
198     friend char *bitdump(Fixpoint &);
199 
200     // Reporting.
201     // ==========
202 
203     static uint8_t click_bool;
204 
205     static uint32_t constructor_void, constructor_Fixpoint, constructor_int, constructor_uint, constructor_lint,
206         constructor_ulint, constructor_double;
207 
208     static uint32_t ass_Fixpoint, ass_int, ass_uint, ass_lint, ass_ulint, ass_double;
209 
210     static uint32_t binary_add, binary_sub, binary_mul, binary_div;
211 
212     static uint32_t add_eq, sub_eq, mul_eq, div_eq;
213 
214     static uint32_t unary_minus, unary_plus;
215 
216     static uint32_t cond_l, cond_g, cond_le, cond_ge, cond_eq, cond_neq;
217 
report_on(void)218     static void report_on(void) { click_bool = 1; }
report_off(void)219     static void report_off(void) { click_bool = 0; }
220 
221     static void report(std::ostream &);
222     static void report(void);
223     static void reset_report(void);
224 
225 #endif /* FIXDEBUG */
226 
227 } /* Blessed be!! */;
228 
229 // Constructors
230 // ============
231 
bits()232 inline uint32_t Fixpoint::bits() { return (uint32_t)val; }
setbits(uint32_t ul)233 inline void Fixpoint::setbits(uint32_t ul) { val = ul; }
234 
Fixpoint()235 inline Fixpoint::Fixpoint() { CLICK(constructor_void); } // Hey, why not define our own....
236 
Fixpoint(const Fixpoint & fp)237 inline Fixpoint::Fixpoint(const Fixpoint &fp) {
238     CLICK(constructor_Fixpoint);
239     val = fp.val;
240 }
241 
Fixpoint(int32_t i)242 inline Fixpoint::Fixpoint(int32_t i) {
243     CLICK(constructor_int);
244     val = i << SHIFTUP;
245 }
246 
Fixpoint(uint32_t i)247 inline Fixpoint::Fixpoint(uint32_t i) {
248     CLICK(constructor_uint);
249     val = i << SHIFTUP;
250 }
251 
Fixpoint(double d)252 inline Fixpoint::Fixpoint(double d) {
253     CLICK(constructor_double);
254     val = (int32_t)(d * SHIFTMULTIPLIER);
255 }
256 
rawConstruct(int32_t l)257 inline Fixpoint rawConstruct(int32_t l) {
258     Fixpoint f;
259     f.val = l;
260     return f;
261 }
262 #define f2Fixpoint(x) (rawConstruct((int32_t)((x)*SHIFTMULTIPLIER)))
263 
264 // ======================================
265 //
266 // Math functions.
267 //
268 // ======================================
269 
270 ////////////
271 //        //
272 //   +=   //
273 //        //
274 ////////////
275 inline Fixpoint &Fixpoint::operator+=(Fixpoint fp2) {
276     CLICK(add_eq);
277 
278     val += fp2.val;
279 
280     return *this;
281 }
282 
283 ////////////
284 //        //
285 //   -=   //
286 //        //
287 ////////////
288 inline Fixpoint &Fixpoint::operator-=(Fixpoint fp2) {
289     CLICK(sub_eq);
290 
291     val -= fp2.val;
292     return *this;
293 }
294 
295 ////////////
296 //        //
297 //   *=   //
298 //        //
299 ////////////
300 inline Fixpoint &Fixpoint::operator*=(Fixpoint fp2) {
301     CLICK(mul_eq);
302 
303     val = (int32_t)fix_mul((fix)val, (fix)fp2.val);
304     return *this;
305 }
306 
307 ////////////
308 //        //
309 //   /=   //
310 //        //
311 ////////////
312 inline Fixpoint &Fixpoint::operator/=(Fixpoint fp2) {
313     CLICK(div_eq);
314 
315     val = (int32_t)fix_div((fix)val, (fix)fp2.val);
316     // val = _fix_do_div(val, fp2.val);
317     return *this;
318 }
319 
320 inline Fixpoint &Fixpoint::operator<<=(uint32_t n) {
321     val <<= n;
322     return *this;
323 }
324 
325 inline Fixpoint &Fixpoint::operator>>=(uint32_t n) {
326     val >>= n;
327     return *this;
328 }
329 
330 inline Fixpoint operator+(Fixpoint a, Fixpoint b) {
331     CLICK(Fixpoint::binary_add);
332     a.val += b.val;
333     return a;
334 }
335 
336 inline Fixpoint operator-(Fixpoint a, Fixpoint b) {
337     CLICK(Fixpoint::binary_sub);
338     a.val -= b.val;
339     return a;
340 }
341 
342 inline Fixpoint operator*(Fixpoint a, Fixpoint b) {
343     CLICK(Fixpoint::binary_mul);
344     a.val = (int32_t)fix_mul((fix)a.val, (fix)b.val);
345     return a;
346 }
347 
348 inline Fixpoint operator/(Fixpoint a, Fixpoint b) {
349     CLICK(Fixpoint::binary_div);
350     a.val = (int32_t)fix_div((fix)a.val, (fix)b.val);
351     // a.val=_fix_do_div(a.val,b.val);
352     return a;
353 }
354 
355 ///////////
356 //       //
357 //   -   //
358 //       //
359 ///////////
360 inline Fixpoint Fixpoint::operator-() const {
361     Fixpoint ans;
362 
363     CLICK(unary_minus);
364 
365     ans.val = -this->val;
366 
367     return ans;
368 }
369 
370 ///////////
371 //       //
372 //   +   //
373 //       //
374 ///////////
375 inline Fixpoint Fixpoint::operator+() const {
376     CLICK(unary_plus);
377 
378     return *this;
379 }
380 
shift(int32_t n)381 inline void Fixpoint::shift(int32_t n) {
382     if (n > 0)
383         val <<= n;
384     else if (n < 0)
385         val >>= (-n);
386 }
387 
shifted(int32_t n)388 inline Fixpoint Fixpoint::shifted(int32_t n) const {
389     Fixpoint r(*this);
390     if (n > 0)
391         r.val <<= n;
392     else if (n < 0)
393         r.val >>= (-n);
394     return r;
395 }
396 
397 inline Fixpoint operator<<(Fixpoint p, unsigned int n) {
398     p.val <<= n;
399     return p;
400 }
401 
402 inline Fixpoint operator>>(Fixpoint p, unsigned int n) {
403     p.val >>= n;
404     return p;
405 }
406 
407 // Conversions.
408 // ============
409 
to_double()410 inline double Fixpoint::to_double() const { return ((double)val) / SHIFTMULTIPLIER; }
411 
to_float()412 inline float Fixpoint::to_float() const { return ((float)val) / SHIFTMULTIPLIER; }
413 
to_int()414 inline int32_t Fixpoint::to_int() const { return (int32_t)(val >> SHIFTUP); }
415 
to_fix()416 inline fix Fixpoint::to_fix() const { return (fix)val; }
417 
to_fixang()418 inline fixang Fixpoint::to_fixang() const {
419     Fixpoint temp = *this * f2Fixpoint(0.159154943);
420 
421     // for temp, 360 degrees = 1.0.
422     // The lower 16 bits of the internal rep is the fixang.
423 
424     return (uint16_t)temp.val;
425 }
426 
fix_to(fix f)427 inline void Fixpoint::fix_to(fix f) { val = f; }
428 
fixang_to(fixang f)429 inline void Fixpoint::fixang_to(fixang f) {
430     val = ((int32_t)(int16_t)(f - 1)) + 1;
431     *this *= f2Fixpoint(6.283185306);
432 }
433 
434 // Comparisons.
435 // ============
436 
437 ///////////
438 //       //
439 //   <   //
440 //       //
441 ///////////
442 inline int32_t Fixpoint::operator<(const Fixpoint &fp2) const {
443     CLICK(cond_l);
444 
445     return this->val < fp2.val;
446 }
447 
448 ///////////
449 //       //
450 //   >   //
451 //       //
452 ///////////
453 inline int32_t Fixpoint::operator>(const Fixpoint &fp2) const {
454     CLICK(cond_g);
455 
456     return this->val > fp2.val;
457 }
458 
459 ////////////
460 //        //
461 //   <=   //
462 //        //
463 ////////////
464 inline int32_t Fixpoint::operator<=(const Fixpoint &fp2) const {
465     CLICK(cond_le);
466 
467     return this->val <= fp2.val;
468 }
469 
470 ////////////
471 //        //
472 //   >=   //
473 //        //
474 ////////////
475 inline int32_t Fixpoint::operator>=(const Fixpoint &fp2) const {
476     CLICK(cond_ge);
477 
478     return this->val >= fp2.val;
479 }
480 
481 ////////////
482 //        //
483 //   ==   //
484 //        //
485 ////////////
486 inline int32_t Fixpoint::operator==(const Fixpoint &fp2) const {
487     CLICK(cond_eq);
488 
489     return this->val == fp2.val;
490 }
491 
492 ////////////
493 //        //
494 //   !=   //
495 //        //
496 ////////////
497 inline int32_t Fixpoint::operator!=(const Fixpoint &fp2) const {
498     CLICK(cond_neq);
499 
500     return this->val != fp2.val;
501 }
502 
503 // ======================================
504 //
505 // Comparisons with zero
506 //
507 // ======================================
508 
gt_zero()509 inline int32_t Fixpoint::gt_zero() const { return (val > 0); }
510 
ge_zero()511 inline int32_t Fixpoint::ge_zero() const { return (val >= 0); }
512 
eq_zero()513 inline int32_t Fixpoint::eq_zero() const { return (val == 0); }
514 
ne_zero()515 inline int32_t Fixpoint::ne_zero() const { return (val != 0); }
516 
le_zero()517 inline int32_t Fixpoint::le_zero() const { return (val <= 0); }
518 
lt_zero()519 inline int32_t Fixpoint::lt_zero() const { return (val < 0); }
520 
521 // ======================================
522 //
523 // Mixed math.
524 //
525 // ======================================
526 
527 inline Fixpoint operator*(int32_t i, Fixpoint const &fp) { return Fixpoint(i) * fp; }
528 inline Fixpoint operator*(uint32_t i, Fixpoint const &fp) { return Fixpoint(i) * fp; }
529 inline Fixpoint operator*(double d, Fixpoint const &fp) { return Fixpoint(d) * fp; }
530 
531 inline Fixpoint operator-(int32_t i, Fixpoint const &fp) { return Fixpoint(i) - fp; }
532 inline Fixpoint operator-(uint32_t i, Fixpoint const &fp) { return Fixpoint(i) - fp; }
533 inline Fixpoint operator-(double d, Fixpoint const &fp) { return Fixpoint(d) - fp; }
534 
535 inline Fixpoint operator+(int32_t i, Fixpoint const &fp) { return Fixpoint(i) + fp; }
536 inline Fixpoint operator+(uint32_t i, Fixpoint const &fp) { return Fixpoint(i) + fp; }
537 inline Fixpoint operator+(double d, Fixpoint const &fp) { return Fixpoint(d) + fp; }
538 
539 inline Fixpoint operator/(int32_t i, Fixpoint const &fp) { return Fixpoint(i) / fp; }
540 inline Fixpoint operator/(uint32_t i, Fixpoint const &fp) { return Fixpoint(i) / fp; }
541 inline Fixpoint operator/(double d, Fixpoint const &fp) { return Fixpoint(d) / fp; }
542 
543 #ifdef BADMIX
544 
545 inline Fixpoint operator*=(int32_t i, Fixpoint fp) { return Fixpoint(i) *= fp; }
546 inline Fixpoint operator*=(uint32_t i, Fixpoint fp) { return Fixpoint(i) *= fp; }
547 inline Fixpoint operator*=(double d, Fixpoint fp) { return Fixpoint(d) *= fp; }
548 
549 #endif
550 
551 // ======================================
552 //
553 // I/O functions.
554 //
555 // ======================================
556 
557 // ======================================
558 //
559 // I/O functions.
560 //
561 // ======================================
562 
563 inline std::ostream &operator<<(std::ostream &os, const Fixpoint &fp) {
564     os << fp.to_double();
565 
566     return os;
567 }
568 
569 inline std::istream &operator>>(std::istream &is, Fixpoint &fp) {
570     double temp;
571 
572     is >> temp;
573 
574     fp = temp;
575 
576     return is;
577 }
578 
579 // ====================================================
580 //
581 // Math functions.
582 //
583 // ====================================================
584 
mul_div(Fixpoint a,Fixpoint b,Fixpoint c)585 inline Fixpoint mul_div(Fixpoint a, Fixpoint b, Fixpoint c) {
586     Fixpoint r;
587     r.val = (int32_t)fix_mul_div((fix)a.val, (fix)b.val, (fix)c.val);
588     return r;
589 }
590 
sqrt(Fixpoint a)591 inline Fixpoint sqrt(Fixpoint a) {
592     Fixpoint ans;
593 
594     ans.val = fix_sqrt(a.val);
595 
596     return ans;
597 }
598 
exp(Fixpoint a)599 inline Fixpoint exp(Fixpoint a) {
600     Fixpoint ans;
601     ans.val = fix_exp(a.val);
602     return ans;
603 }
604 
floor(Fixpoint a)605 inline int32_t floor(Fixpoint a) { return a.val >> SHIFTUP; }
606 
sin(Fixpoint a)607 inline Fixpoint sin(Fixpoint a) {
608     Fixpoint ans;
609 
610     ans.val = fix_sin(a.to_fixang());
611 
612     return ans;
613 }
614 
cos(Fixpoint a)615 inline Fixpoint cos(Fixpoint a) {
616     Fixpoint ans;
617 
618     ans.val = fix_cos(a.to_fixang());
619 
620     return ans;
621 }
622 
tan(Fixpoint a)623 inline Fixpoint tan(Fixpoint a) {
624     Fixpoint sn, cs;
625 
626     sn = sin(a);
627     cs = cos(a);
628     if (cs == 0)
629         return 0;
630     else
631         return sn / cs;
632 }
633 
asin(Fixpoint a)634 inline Fixpoint asin(Fixpoint a) {
635     Fixpoint ans;
636 
637     ans.fixang_to(fix_asin(a.to_fix()));
638 
639     return ans;
640 }
641 
acos(Fixpoint a)642 inline Fixpoint acos(Fixpoint a) {
643     Fixpoint ans;
644 
645     ans.fixang_to(fix_acos(a.to_fix()));
646 
647     return ans;
648 }
649 
sincos(Fixpoint ang,Fixpoint * sn,Fixpoint * cs)650 inline void sincos(Fixpoint ang, Fixpoint *sn, Fixpoint *cs) {
651     fix fsn, fcs;
652     fix_sincos(ang.to_fixang(), &fsn, &fcs);
653     sn->val = fsn;
654     cs->val = fcs;
655 }
656 
atan2(Fixpoint y,Fixpoint x)657 inline Fixpoint atan2(Fixpoint y, Fixpoint x) {
658     Fixpoint ans;
659 
660     ans.fixang_to(fix_atan2(y.to_fix(), x.to_fix()));
661 
662     return ans;
663 }
664 
fsin(Fixpoint a)665 inline Fixpoint fsin(Fixpoint a) {
666     Fixpoint ans;
667 
668     ans.val = fix_fastsin(a.to_fixang());
669 
670     return ans;
671 }
672 
fcos(Fixpoint a)673 inline Fixpoint fcos(Fixpoint a) {
674     Fixpoint ans;
675 
676     ans.val = fix_fastcos(a.to_fixang());
677 
678     return ans;
679 }
680 
fsincos(Fixpoint ang,Fixpoint * sn,Fixpoint * cs)681 inline void fsincos(Fixpoint ang, Fixpoint *sn, Fixpoint *cs) {
682     fix fsn, fcs;
683     fix_fastsincos(ang.to_fixang(), &fsn, &fcs);
684     sn->val = fsn;
685     cs->val = fcs;
686 }
687 
abs(Fixpoint fp)688 inline Fixpoint abs(Fixpoint fp) {
689     Fixpoint ans;
690 
691     ans.val = labs(fp.val);
692 
693     return ans;
694 }
695 
696 #ifdef FIXDEBUG
697 
698 void touch(Fixpoint &);
699 
700 #endif /* FIXDEBUG */
701 
702 #endif /* !__FIXPP_H */
703