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