1mod asin_tab;
2mod cos_tab;
3mod sin_table;
4
5use asin_tab::ASIN_TAB;
6use cos_tab::COS_TAB;
7use num_traits::{Euclid, Float, FromPrimitive, Signed};
8use sin_table::SIN;
9
10pub const PI: f32 = std::f32::consts::PI;
11pub const PI_64: f64 = std::f64::consts::PI;
12pub const DEG_TO_RAD: f32 = PI / 180.0;
13pub const RAD_TO_DEG: f32 = 180.0 / PI;
14pub const EPSILON: f32 = 1.0E-5;
15pub const SQRT_OF_TWO: f32 = std::f32::consts::SQRT_2;
16const SIN_SCALE: f64 = 10430.378350470453;
17const ONE_SIXTH: f64 = 0.16666666666666666;
18const FRAC_BIAS: f64 = f64::from_bits(4805340802404319232u64);
19
20pub fn sin(x: f64) -> f32 {
21 let idx = (((x * SIN_SCALE) as i64 as u64) & 65535) as usize;
22 SIN[idx]
23}
24
25pub fn cos(x: f64) -> f32 {
26 let idx = (((x * SIN_SCALE + 16384.0) as i64 as u64) & 65535) as usize;
27 SIN[idx]
28}
29
30pub fn sqrt(x: f32) -> f32 {
31 x.sqrt()
32}
33
34pub fn floor<T: Float>(v: T) -> T {
35 let _ = v;
36 todo!()
37}
38
39pub fn lfloor(v: f64) -> i64 {
40 let _ = v;
41 todo!()
42}
43
44pub fn abs<T: Signed>(v: T) -> T {
45 v.abs()
46}
47
48pub fn ceil<T: Float>(v: T) -> i32 {
49 let _ = v;
50 todo!()
51}
52
53pub fn ceil_long(v: f64) -> i64 {
54 let _ = v;
55 todo!()
56}
57
58pub fn clamp<T: PartialOrd>(value: T, min: T, max: T) -> T {
59 num_traits::clamp(value, min, max)
60}
61
62pub fn clamped_lerp<T: Float>(factor: T, min: T, max: T) -> T {
63 let _ = (factor, min, max);
64 todo!()
65}
66
67pub fn abs_max<T: Signed + PartialOrd>(a: T, b: T) -> T {
68 let abs_a = a.abs();
69 let abs_b = b.abs();
70 if abs_a > abs_b { abs_a } else { abs_b }
71}
72
73pub fn chessboard_distance(x0: i32, z0: i32, x1: i32, z1: i32) -> i32 {
74 abs_max(x1 - x0, z1 - z0)
75}
76
77pub fn floor_div(a: i32, b: i32) -> i32 {
78 a.div_euclid(b)
79}
80
81pub fn equal<T: Float>(a: T, b: T) -> bool {
82 let eps = T::from(1e-5).unwrap();
83 (b - a).abs() < eps
84}
85
86pub fn positive_modulo<T: Euclid>(input: T, r#mod: T) -> T {
87 input.rem_euclid(&r#mod)
88}
89
90pub fn is_miltiple_of(dividend: i32, divisor: i32) -> bool {
91 dividend % divisor == 0
92}
93
94pub fn pack_degrees(angle: f32) -> i8 {
95 (angle * 256.0 / 360.0).floor() as i8
96}
97
98pub fn unpack_degress(rot: i8) -> f32 {
99 rot as f32 * 360.0 / 256.0
100}
101
102pub fn wrap_degrees<T>(angle: T) -> T
103where
104 T: Signed + Copy + FromPrimitive + PartialOrd,
105{
106 let deg180 = T::from_i32(180).unwrap();
107 let deg360 = T::from_i32(360).unwrap();
108 let a: T = angle % deg360;
109
110 match a {
111 x if x >= deg180 => x - deg360,
112 x if x < -deg180 => x + deg360,
113 x => x,
114 }
115}
116
117pub fn degrees_difference(from_angle: f32, to_angle: f32) -> f32 {
118 wrap_degrees(to_angle - from_angle)
119}
120
121pub fn degrees_difference_abs(angle_a: f32, angle_b: f32) -> f32 {
122 degrees_difference(angle_a, angle_b).abs()
123}
124
125pub fn rotate_if_necessary(base_angle: f32, target_angle: f32, max_angle_diff: f32) -> f32 {
126 let _ = (base_angle, target_angle, max_angle_diff);
127 todo!()
128}
129
130pub fn approach(current: f32, target: f32, increment: f32) -> f32 {
131 let _ = (current, target, increment);
132 todo!()
133}
134
135pub fn approach_degress(current: f32, target: f32, increment: f32) -> f32 {
136 let _ = (current, target, increment);
137 todo!()
138}
139
140pub fn get_int(input: &str, default: i32) -> i32 {
141 input.parse::<i32>().unwrap_or(default)
142}
143
144pub fn smallest_encompassing_power_of_two(input: i32) -> i32 {
145 let _ = input;
146 todo!()
147}
148
149pub fn is_power_of_two(input: u32) -> bool {
150 input.is_power_of_two()
151}
152
153pub fn ceillog2(input: u32) -> u32 {
154 if is_power_of_two(input) {
155 log2(input)
156 } else {
157 log2(input) + 1
158 }
159}
160
161pub fn log2(input: u32) -> u32 {
162 input.ilog2()
163}
164
165pub fn frac<T: Float>(num: T) -> T {
166 let _ = num;
167 todo!()
168}
169
170pub fn inverse_lerp<T: Float>(value: T, min: T, max: T) -> T {
171 let _ = (value, min, max);
172 todo!()
173}
174
175pub fn atan2(y: f64, x: f64) -> f64 {
176 let mut x = x;
177 let mut y = y;
178 let d2 = x * x + y * y;
179
180 if d2.is_nan() {
181 return f64::NAN;
182 }
183
184 let neg_y = y < 0.0;
185 if neg_y {
186 y = -y;
187 }
188
189 let neg_x = x < 0.0;
190 if neg_x {
191 x = -x;
192 }
193
194 let steep = y > x;
195 if steep {
196 (x, y) = (y, x)
197 }
198
199 let rinv = fast_inv_sqrt(d2);
200
201 x *= rinv;
202 y *= rinv;
203
204 let yp = FRAC_BIAS + y;
205 let index = yp.to_bits() as usize;
206 let phi = ASIN_TAB[index];
207 let c_phi = COS_TAB[index];
208 let s_phi = yp - FRAC_BIAS;
209
210 let sd = y * c_phi - x * s_phi;
211
212 let d = (6.0 + sd * sd) * sd * ONE_SIXTH;
213
214 let mut theta = phi + d;
215
216 if steep {
217 theta = PI_64 / 2.0 - theta
218 }
219
220 if neg_x {
221 theta = PI_64 - theta
222 }
223
224 if neg_y {
225 theta = -theta
226 }
227
228 theta
229}
230
231pub fn inv_sqrt<T: Float>(x: T) -> T {
232 x.sqrt().recip()
233}
234
235pub fn fast_inv_sqrt(x: f64) -> f64 {
236 let xhalf = 0.5 * x;
237 let mut i = x.to_bits();
238 i = 6910469410427058090_u64 - (i >> 1);
239 let y = f64::from_bits(i);
240
241 y * (1.5 - xhalf * y * y)
242}
243
244pub fn fast_inv_cube_root(x: f32) -> f32 {
245 let _ = x;
246 todo!()
247}
248
249pub fn hsv_to_rgb(hue: f32, saturation: f32, value: f32) -> i32 {
250 let _ = (hue, saturation, value);
251 todo!()
252}
253
254pub fn hsv_to_argb(hue: f32, saturation: f32, value: f32, alpha: i32) -> i32 {
255 let _ = (hue, saturation, value, alpha);
256 todo!()
257}
258
259pub fn lerp_int(alpha1: f32, p0: i32, p1: i32) -> i32 {
260 let _ = (alpha1, p0, p1);
261 todo!()
262}
263
264pub fn lerp_discrete(alpha1: f32, p0: i32, p1: i32) -> i32 {
265 let _ = (alpha1, p0, p1);
266 todo!()
267}
268
269pub fn lerp<T: Float>(alpha1: T, p0: T, p1: T) -> T {
270 p0 + alpha1 * (p1 - p0)
271}
272
273pub fn lerp2(alpha1: f64, alpha2: f64, x00: f64, x10: f64, x01: f64, x11: f64) -> f64 {
274 lerp(alpha2, lerp(alpha1, x00, x10), lerp(alpha1, x01, x11))
275}
276
277#[allow(clippy::too_many_arguments)]
278pub fn lerp3(
279 alpha1: f64,
280 alpha2: f64,
281 alpha3: f64,
282 x000: f64,
283 x100: f64,
284 x010: f64,
285 x110: f64,
286 x001: f64,
287 x101: f64,
288 x011: f64,
289 x111: f64,
290) -> f64 {
291 lerp(
292 alpha3,
293 lerp2(alpha1, alpha2, x000, x100, x010, x110),
294 lerp2(alpha1, alpha2, x001, x101, x011, x111),
295 )
296}
297
298pub fn catmullrom(alpha: f32, p0: f32, p1: f32, p2: f32, p3: f32) -> f32 {
299 let _ = (alpha, p0, p1, p2, p3);
300 todo!()
301}
302
303pub fn smoothstep(x: f64) -> f64 {
304 let _ = x;
305 todo!()
306}
307
308pub fn smoothstep_derivative(x: f64) -> f64 {
309 let _ = x;
310 todo!()
311}
312
313pub fn sign(number: f64) -> i32 {
314 number.signum() as i32
315}
316
317pub fn rot_lerp<T>(a: T, from: T, to: T) -> T
318where
319 T: Signed + Copy + FromPrimitive + PartialOrd + Float,
320{
321 from + a * wrap_degrees(to - from)
322}
323
324pub fn rot_lerp_rad(a: f32, from: f32, to: f32) -> f32 {
325 let diff = (to - from + PI).rem_euclid(2.0 * PI) - PI;
326 from + a * diff
327}
328
329pub fn triangle_wave(index: f32, period: f32) -> f32 {
330 let _ = (index, period);
331 todo!()
332}
333
334pub fn clamped_map<T: Float>(value: T, from_min: T, from_max: T, to_min: T, to_max: T) -> T {
335 clamped_lerp(inverse_lerp(value, from_min, from_max), to_min, to_max)
336}
337
338pub fn map<T: Float>(value: T, from_min: T, from_max: T, to_min: T, to_max: T) -> T {
339 lerp(inverse_lerp(value, from_min, from_max), to_min, to_max)
340}
341
342pub fn round_toward(input: i32, multiple: i32) -> i32 {
343 positive_ceil_div(input, multiple) * multiple
344}
345
346pub fn positive_ceil_div(input: i32, divisor: i32) -> i32 {
347 -floor_div(-input, divisor)
348}
349
350pub fn length_squared<T: Float>(x: T, y: T) -> T {
351 x * x + y * y
352}
353
354pub fn length<T: Float>(x: T, y: T) -> T {
355 length_squared(x, y).sqrt()
356}
357
358pub fn length_squared_3<T: Float>(x: T, y: T, z: T) -> T {
359 x * x + y * y + z * z
360}
361
362pub fn length_3<T: Float>(x: T, y: T, z: T) -> T {
363 length_squared_3(x, y, z).sqrt()
364}
365
366pub fn quantize(value: f64, quantize_resolution: f64) -> f64 {
367 floor(value / quantize_resolution) * quantize_resolution
368}