1 /*
2  * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
3  * It is copyright by its individual contributors, as recorded in the
4  * project's Git history.  See COPYING.txt at the top level for license
5  * terms and a link to the Git history.
6  */
7 /* Maths.h library header file */
8 
9 #pragma once
10 
11 #include <cstdint>
12 #include <stdlib.h>
13 #include "pstypes.h"
14 
15 
16 
17 #define D_RAND_MAX 32767
18 
19 #include <cstddef>
20 #include "dsx-ns.h"
21 #include <array>
22 
23 namespace dcx {
24 
25 void d_srand (unsigned int seed);
26 
27 [[nodiscard]]
28 int d_rand ();			// Random number function which returns in the range 0-0x7FFF
29 
30 
31 //=============================== FIXED POINT ===============================
32 
33 typedef int64_t fix64;		//64 bits int, for timers
34 typedef int32_t fix;		//16 bits int, 16 bits frac
35 typedef int16_t fixang;		//angles
36 
37 typedef struct quadint // integer 64 bit, previously called "quad"
38   {
39 	  union {
40 		  struct {
41     uint32_t low;
42     int32_t high;
43 		  };
44 		  int64_t q;
45 	  };
46   }
47 quadint;
48 
49 
50 //Convert an int to a fix/fix64 and back
i2f(const int & i)51 static constexpr fix i2f(const int &i)
52 {
53 	return i << 16;
54 }
55 
f2i(const fix & f)56 static constexpr int f2i(const fix &f)
57 {
58 	return f >> 16;
59 }
60 
61 //Convert fix to float and float to fix
f2fl(const fix & f)62 static constexpr float f2fl(const fix &f)
63 {
64 	return static_cast<float>(f) / static_cast<float>(65536.0);
65 }
66 
f2db(const fix & f)67 static constexpr double f2db(const fix &f)
68 {
69 	return static_cast<double>(f) / 65536.0;
70 }
71 
fl2f(const float & f)72 static constexpr fix fl2f(const float &f)
73 {
74 	return static_cast<fix>(f * 65536);
75 }
76 
77 //Some handy constants
78 #define f0_0	0
79 #define f1_0	0x10000
80 #define f2_0	0x20000
81 #define f3_0	0x30000
82 #define f10_0	0xa0000
83 
84 #define f0_5 0x8000
85 #define f0_1 0x199a
86 
87 //Get the int part of a fix, with rounding
f2ir(const fix & f)88 static constexpr int f2ir(const fix &f)
89 {
90 	return (f + f0_5) >> 16;
91 }
92 
93 #define F0_0	f0_0
94 #define F1_0	f1_0
95 #define F2_0	f2_0
96 #define F3_0	f3_0
97 #define F10_0	f10_0
98 
99 #define F0_5 	f0_5
100 #define F0_1 	f0_1
101 
102 //multiply two fixes, return a fix(64)
103 [[nodiscard]]
104 fix64 fixmul64 (fix a, fix b);
105 
106 /* On x86/amd64 for Windows/Linux, truncating fix64->fix is free. */
107 [[nodiscard]]
fixmul(fix a,fix b)108 static inline fix fixmul(fix a, fix b)
109 {
110 	return static_cast<fix>(fixmul64(a, b));
111 }
112 
113 //divide two fixes, return a fix
114 [[nodiscard]]
115 fix fixdiv (fix a, fix b);
116 
117 //multiply two fixes, then divide by a third, return a fix
118 [[nodiscard]]
119 fix fixmuldiv (fix a, fix b, fix c);
120 
121 //multiply two fixes, and add 64-bit product to a quadint
fixmulaccum(quadint * q,const fix & a,const fix & b)122 static inline void fixmulaccum (quadint * q, const fix &a, const fix &b)
123 {
124 	q->q += static_cast<int64_t>(a) * static_cast<int64_t>(b);
125 }
126 
127 //extract a fix from a quadint product
128 [[nodiscard]]
fixquadadjust(const quadint * q)129 static inline fix fixquadadjust (const quadint *q)
130 {
131 	return static_cast<fix>(q->q >> 16);
132 }
133 
134 //negate a quadint
fixquadnegate(quadint * q)135 static inline void fixquadnegate (quadint * q)
136 {
137 	q->q = -q->q;
138 }
139 
140 //computes the square root of a long, returning a short
141 [[nodiscard]]
142 ushort long_sqrt (int32_t a);
143 
144 //computes the square root of a quadint, returning a long
145 [[nodiscard]]
146 uint32_t quad_sqrt (quadint);
147 
148 //computes the square root of a fix, returning a fix
149 [[nodiscard]]
150 fix fix_sqrt (fix a);
151 
152 struct fix_sincos_result
153 {
154 	fix sin, cos;
155 };
156 
157 [[nodiscard]]
158 fix_sincos_result fix_sincos(fixang);
159 
160 //compute sine and cosine of an angle, filling in the variables
161 //either of the pointers can be NULL
162 
163 [[nodiscard]]
164 fix fix_sin(fixang a);
165 
166 [[nodiscard]]
167 fix fix_cos(fixang a);
168 
169 [[nodiscard]]
170 fix fix_fastsin(fixang a);	//no interpolation
171 
172 //compute inverse sine & cosine
173 [[nodiscard]]
174 fixang fix_asin (fix v);
175 
176 [[nodiscard]]
177 fixang fix_acos (fix v);
178 
179 //given cos & sin of an angle, return that angle.
180 //parms need not be normalized, that is, the ratio of the parms cos/sin must
181 //equal the ratio of the actual cos & sin for the result angle, but the parms
182 //need not be the actual cos & sin.
183 //NOTE: this is different from the standard C atan2, since it is left-handed.
184 [[nodiscard]]
185 fixang fix_atan2 (fix cos, fix sin);
186 
187 [[nodiscard]]
188 int checkmuldiv(fix *r,fix a,fix b,fix c);
189 
190 extern const std::array<ubyte, 256> guess_table;
191 extern const std::array<int16_t, 256> sincos_table;
192 extern const std::array<ushort, 258> asin_table;
193 extern const std::array<ushort, 258> acos_table;
194 
clamp_fix_lh(fix & f,const fix & low,const fix & high)195 static inline void clamp_fix_lh(fix& f, const fix& low, const fix& high)
196 {
197 	if (f < low)
198 		f = low;
199 	else if (high < f)
200 		f = high;
201 }
202 
clamp_fix_symmetric(fix & f,const fix & bound)203 static inline void clamp_fix_symmetric(fix& f, const fix& bound)
204 {
205 	clamp_fix_lh(f, -bound, bound);
206 }
207 
208 }
209