nstd_sys/core/math.rs
1//! Low level math operations.
2use crate::{
3 core::optional::{
4 NSTDOptional, NSTDOptionalInt, NSTDOptionalInt16, NSTDOptionalInt32, NSTDOptionalInt64,
5 NSTDOptionalInt8, NSTDOptionalUInt, NSTDOptionalUInt16, NSTDOptionalUInt32,
6 NSTDOptionalUInt64, NSTDOptionalUInt8,
7 },
8 NSTDFloat32, NSTDFloat64, NSTDInt, NSTDInt16, NSTDInt32, NSTDInt64, NSTDInt8, NSTDUInt,
9 NSTDUInt16, NSTDUInt32, NSTDUInt64, NSTDUInt8,
10};
11use nstdapi::nstdapi;
12
13/// Converts radians to degrees.
14///
15/// # Parameters:
16///
17/// - `NSTDFloat32 rad` - The radians value.
18///
19/// # Returns
20///
21/// `NSTDFloat32 deg` - The radians value converted to degrees.
22#[inline]
23#[nstdapi]
24pub fn nstd_core_math_deg_f32(rad: NSTDFloat32) -> NSTDFloat32 {
25 rad.to_degrees()
26}
27/// Converts radians to degrees.
28///
29/// # Parameters:
30///
31/// - `NSTDFloat64 rad` - The radians value.
32///
33/// # Returns
34///
35/// `NSTDFloat64 deg` - The radians value converted to degrees.
36#[inline]
37#[nstdapi]
38pub fn nstd_core_math_deg_f64(rad: NSTDFloat64) -> NSTDFloat64 {
39 rad.to_degrees()
40}
41
42/// Converts degrees to radians.
43///
44/// # Parameters:
45///
46/// - `NSTDFloat32 deg` - The degrees value.
47///
48/// # Returns
49///
50/// `NSTDFloat32 rad` - The degrees value converted to radians.
51#[inline]
52#[nstdapi]
53pub fn nstd_core_math_rad_f32(deg: NSTDFloat32) -> NSTDFloat32 {
54 deg.to_radians()
55}
56/// Converts degrees to radians.
57///
58/// # Parameters:
59///
60/// - `NSTDFloat64 deg` - The degrees value.
61///
62/// # Returns
63///
64/// `NSTDFloat64 rad` - The degrees value converted to radians.
65#[inline]
66#[nstdapi]
67pub fn nstd_core_math_rad_f64(deg: NSTDFloat64) -> NSTDFloat64 {
68 deg.to_radians()
69}
70
71/// Generates the `abs` functions.
72macro_rules! gen_abs {
73 ($name: ident, $T: ty) => {
74 /// Computes the absolute (positive) value of `x`.
75 ///
76 /// # Parameters:
77 ///
78 #[doc = concat!("- `", stringify!($T), " x` - The value.")]
79 ///
80 /// # Returns
81 ///
82 #[doc = concat!("`", stringify!($T), " abs` - The absolute value of `x`.")]
83 ///
84 /// # Example
85 ///
86 /// ```
87 #[doc = concat!("use nstd_sys::core::math::", stringify!($name), ";")]
88 /// # unsafe {
89 #[doc = concat!("assert!(", stringify!($name), "(10) == 10);")]
90 #[doc = concat!("assert!(", stringify!($name), "(-10) == 10);")]
91 /// # }
92 /// ```
93 #[inline]
94 #[nstdapi]
95 pub const fn $name(x: $T) -> $T {
96 x.abs()
97 }
98 };
99}
100gen_abs!(nstd_core_math_abs_int, NSTDInt);
101gen_abs!(nstd_core_math_abs_i8, NSTDInt8);
102gen_abs!(nstd_core_math_abs_i16, NSTDInt16);
103gen_abs!(nstd_core_math_abs_i32, NSTDInt32);
104gen_abs!(nstd_core_math_abs_i64, NSTDInt64);
105
106/// Generates the `pow` functions.
107macro_rules! gen_pow {
108 ($name: ident, $T: ty) => {
109 /// Raises the value `x` to the power of `exp`
110 ///
111 /// # Parameters:
112 ///
113 #[doc = concat!("- `", stringify!($T), " x` - The value.")]
114 ///
115 /// - `NSTDUInt32 exp` - The exponent.
116 ///
117 /// # Returns
118 ///
119 #[doc = concat!("`", stringify!($T), " pow` - `x` raised to the power of `exp`.")]
120 ///
121 /// # Example
122 ///
123 /// ```
124 #[doc = concat!("use nstd_sys::core::math::", stringify!($name), ";")]
125 /// # unsafe {
126 #[doc = concat!("assert!(", stringify!($name), "(2, 3) == 8);")]
127 #[doc = concat!("assert!(", stringify!($name), "(2, 5) == 32);")]
128 /// # }
129 /// ```
130 #[inline]
131 #[nstdapi]
132 pub const fn $name(x: $T, exp: NSTDUInt32) -> $T {
133 x.pow(exp)
134 }
135 };
136}
137gen_pow!(nstd_core_math_pow_int, NSTDInt);
138gen_pow!(nstd_core_math_pow_uint, NSTDUInt);
139gen_pow!(nstd_core_math_pow_i8, NSTDInt8);
140gen_pow!(nstd_core_math_pow_u8, NSTDUInt8);
141gen_pow!(nstd_core_math_pow_i16, NSTDInt16);
142gen_pow!(nstd_core_math_pow_u16, NSTDUInt16);
143gen_pow!(nstd_core_math_pow_i32, NSTDInt32);
144gen_pow!(nstd_core_math_pow_u32, NSTDUInt32);
145gen_pow!(nstd_core_math_pow_i64, NSTDInt64);
146gen_pow!(nstd_core_math_pow_u64, NSTDUInt64);
147
148/// Generates the `clamp` functions.
149macro_rules! gen_clamp {
150 (
151 $(#[$meta:meta])*
152 $name: ident, $T: ty
153 ) => {
154 /// Clamps the value `x` to the bounds `min` and `max`.
155 ///
156 /// # Parameters:
157 ///
158 #[doc = concat!("- `", stringify!($T), " x` - The value to clamp.")]
159 ///
160 #[doc = concat!("- `", stringify!($T), " min` - The minimum clamp value.")]
161 ///
162 #[doc = concat!("- `", stringify!($T), " max` - The maximum clamp value.")]
163 ///
164 /// # Returns
165 ///
166 #[doc = concat!("`", stringify!($T), " v` - The clamped value.")]
167 $(#[$meta])*
168 #[inline]
169 #[nstdapi]
170 pub fn $name(x: $T, min: $T, max: $T) -> $T {
171 x.clamp(min, max)
172 }
173 };
174}
175gen_clamp!(
176 ///
177 /// # Panics
178 ///
179 /// Panics if `min` > `max`, `min` is NaN, or `max` is NaN.
180 ///
181 /// # Example
182 ///
183 /// ```
184 /// use nstd_sys::core::math::nstd_core_math_clamp_f32;
185 ///
186 /// # unsafe {
187 /// assert!(nstd_core_math_clamp_f32(2.5, 3.0, 5.0) == 3.0);
188 /// assert!(nstd_core_math_clamp_f32(4.0, 3.0, 5.0) == 4.0);
189 /// assert!(nstd_core_math_clamp_f32(7.5, 3.0, 5.0) == 5.0);
190 /// # }
191 /// ```
192 nstd_core_math_clamp_f32,
193 NSTDFloat32
194);
195gen_clamp!(
196 ///
197 /// # Panics
198 ///
199 /// Panics if `min` > `max`, `min` is NaN, or `max` is NaN.
200 ///
201 /// # Example
202 ///
203 /// ```
204 /// use nstd_sys::core::math::nstd_core_math_clamp_f64;
205 ///
206 /// # unsafe {
207 /// assert!(nstd_core_math_clamp_f64(2.5, 3.0, 5.0) == 3.0);
208 /// assert!(nstd_core_math_clamp_f64(4.0, 3.0, 5.0) == 4.0);
209 /// assert!(nstd_core_math_clamp_f64(7.5, 3.0, 5.0) == 5.0);
210 /// # }
211 /// ```
212 nstd_core_math_clamp_f64,
213 NSTDFloat64
214);
215gen_clamp!(
216 ///
217 /// # Panics
218 ///
219 /// Panics if `min` > `max`.
220 ///
221 /// # Example
222 ///
223 /// ```
224 /// use nstd_sys::core::math::nstd_core_math_clamp_int;
225 ///
226 /// # unsafe {
227 /// assert!(nstd_core_math_clamp_int(2, 5, 10) == 5);
228 /// assert!(nstd_core_math_clamp_int(8, 5, 10) == 8);
229 /// assert!(nstd_core_math_clamp_int(14, 5, 10) == 10);
230 /// # }
231 /// ```
232 nstd_core_math_clamp_int,
233 NSTDInt
234);
235gen_clamp!(
236 ///
237 /// # Panics
238 ///
239 /// Panics if `min` > `max`.
240 ///
241 /// # Example
242 ///
243 /// ```
244 /// use nstd_sys::core::math::nstd_core_math_clamp_uint;
245 ///
246 /// # unsafe {
247 /// assert!(nstd_core_math_clamp_uint(2, 5, 10) == 5);
248 /// assert!(nstd_core_math_clamp_uint(8, 5, 10) == 8);
249 /// assert!(nstd_core_math_clamp_uint(14, 5, 10) == 10);
250 /// # }
251 /// ```
252 nstd_core_math_clamp_uint,
253 NSTDUInt
254);
255gen_clamp!(
256 ///
257 /// # Panics
258 ///
259 /// Panics if `min` > `max`.
260 ///
261 /// # Example
262 ///
263 /// ```
264 /// use nstd_sys::core::math::nstd_core_math_clamp_i8;
265 ///
266 /// # unsafe {
267 /// assert!(nstd_core_math_clamp_i8(2, 5, 10) == 5);
268 /// assert!(nstd_core_math_clamp_i8(8, 5, 10) == 8);
269 /// assert!(nstd_core_math_clamp_i8(14, 5, 10) == 10);
270 /// # }
271 /// ```
272 nstd_core_math_clamp_i8,
273 NSTDInt8
274);
275gen_clamp!(
276 ///
277 /// # Panics
278 ///
279 /// Panics if `min` > `max`.
280 ///
281 /// # Example
282 ///
283 /// ```
284 /// use nstd_sys::core::math::nstd_core_math_clamp_u8;
285 ///
286 /// # unsafe {
287 /// assert!(nstd_core_math_clamp_u8(2, 5, 10) == 5);
288 /// assert!(nstd_core_math_clamp_u8(8, 5, 10) == 8);
289 /// assert!(nstd_core_math_clamp_u8(14, 5, 10) == 10);
290 /// # }
291 /// ```
292 nstd_core_math_clamp_u8,
293 NSTDUInt8
294);
295gen_clamp!(
296 ///
297 /// # Panics
298 ///
299 /// Panics if `min` > `max`.
300 ///
301 /// # Example
302 ///
303 /// ```
304 /// use nstd_sys::core::math::nstd_core_math_clamp_i16;
305 ///
306 /// # unsafe {
307 /// assert!(nstd_core_math_clamp_i16(2, 5, 10) == 5);
308 /// assert!(nstd_core_math_clamp_i16(8, 5, 10) == 8);
309 /// assert!(nstd_core_math_clamp_i16(14, 5, 10) == 10);
310 /// # }
311 /// ```
312 nstd_core_math_clamp_i16,
313 NSTDInt16
314);
315gen_clamp!(
316 ///
317 /// # Panics
318 ///
319 /// Panics if `min` > `max`.
320 ///
321 /// # Example
322 ///
323 /// ```
324 /// use nstd_sys::core::math::nstd_core_math_clamp_u16;
325 ///
326 /// # unsafe {
327 /// assert!(nstd_core_math_clamp_u16(2, 5, 10) == 5);
328 /// assert!(nstd_core_math_clamp_u16(8, 5, 10) == 8);
329 /// assert!(nstd_core_math_clamp_u16(14, 5, 10) == 10);
330 /// # }
331 /// ```
332 nstd_core_math_clamp_u16,
333 NSTDUInt16
334);
335gen_clamp!(
336 ///
337 /// # Panics
338 ///
339 /// Panics if `min` > `max`.
340 ///
341 /// # Example
342 ///
343 /// ```
344 /// use nstd_sys::core::math::nstd_core_math_clamp_i32;
345 ///
346 /// # unsafe {
347 /// assert!(nstd_core_math_clamp_i32(2, 5, 10) == 5);
348 /// assert!(nstd_core_math_clamp_i32(8, 5, 10) == 8);
349 /// assert!(nstd_core_math_clamp_i32(14, 5, 10) == 10);
350 /// # }
351 /// ```
352 nstd_core_math_clamp_i32,
353 NSTDInt32
354);
355gen_clamp!(
356 ///
357 /// # Panics
358 ///
359 /// Panics if `min` > `max`.
360 ///
361 /// # Example
362 ///
363 /// ```
364 /// use nstd_sys::core::math::nstd_core_math_clamp_u32;
365 ///
366 /// # unsafe {
367 /// assert!(nstd_core_math_clamp_u32(2, 5, 10) == 5);
368 /// assert!(nstd_core_math_clamp_u32(8, 5, 10) == 8);
369 /// assert!(nstd_core_math_clamp_u32(14, 5, 10) == 10);
370 /// # }
371 /// ```
372 nstd_core_math_clamp_u32,
373 NSTDUInt32
374);
375gen_clamp!(
376 ///
377 /// # Panics
378 ///
379 /// Panics if `min` > `max`.
380 ///
381 /// # Example
382 ///
383 /// ```
384 /// use nstd_sys::core::math::nstd_core_math_clamp_i64;
385 ///
386 /// # unsafe {
387 /// assert!(nstd_core_math_clamp_i64(2, 5, 10) == 5);
388 /// assert!(nstd_core_math_clamp_i64(8, 5, 10) == 8);
389 /// assert!(nstd_core_math_clamp_i64(14, 5, 10) == 10);
390 /// # }
391 /// ```
392 nstd_core_math_clamp_i64,
393 NSTDInt64
394);
395gen_clamp!(
396 ///
397 /// # Panics
398 ///
399 /// Panics if `min` > `max`.
400 ///
401 /// # Example
402 ///
403 /// ```
404 /// use nstd_sys::core::math::nstd_core_math_clamp_u64;
405 ///
406 /// # unsafe {
407 /// assert!(nstd_core_math_clamp_u64(2, 5, 10) == 5);
408 /// assert!(nstd_core_math_clamp_u64(8, 5, 10) == 8);
409 /// assert!(nstd_core_math_clamp_u64(14, 5, 10) == 10);
410 /// # }
411 /// ```
412 nstd_core_math_clamp_u64,
413 NSTDUInt64
414);
415
416/// Generates the `div_ceil` functions.
417macro_rules! gen_div_ceil {
418 ($name: ident, $T: ty, $Opt: ty) => {
419 /// Divides two numbers and rounds the result up to the next integer.
420 ///
421 /// # Parameters:
422 ///
423 #[doc = concat!("- `", stringify!($T), " x` - The first value.")]
424 ///
425 #[doc = concat!("- `", stringify!($T), " y` - The second value.")]
426 ///
427 /// # Returns
428 ///
429 #[doc = concat!("`", stringify!($Opt), " v` - The divided value rounded up on success, or an uninitialized \"none\" variant if `y` is 0 or overflow occurs.")]
430 ///
431 /// # Example
432 ///
433 /// ```
434 #[doc = concat!("use nstd_sys::core::{math::", stringify!($name), ", optional::NSTDOptional};")]
435 ///
436 /// # unsafe {
437 #[doc = concat!("assert!(", stringify!($name), "(8, 5) == NSTDOptional::Some(2));")]
438 #[doc = concat!("assert!(", stringify!($name), "(8, 3) == NSTDOptional::Some(3));")]
439 #[doc = concat!("assert!(", stringify!($name), "(8, 2) == NSTDOptional::Some(4));")]
440 #[doc = concat!("assert!(", stringify!($name), "(8, 0) == NSTDOptional::None);")]
441 /// # }
442 /// ```
443 #[nstdapi]
444 #[allow(unused_comparisons)]
445 pub const fn $name(x: $T, y: $T) -> $Opt {
446 if let Some(v) = x.checked_div(y) {
447 if let Some(r) = x.checked_rem(y) {
448 return match (r > 0 && y > 0) || (r < 0 && y < 0) {
449 true => match v.checked_add(1) {
450 Some(v) => NSTDOptional::Some(v),
451 _ => NSTDOptional::None,
452 },
453 false => NSTDOptional::Some(v),
454 };
455 }
456 }
457 NSTDOptional::None
458 }
459 };
460}
461gen_div_ceil!(nstd_core_math_div_ceil_int, NSTDInt, NSTDOptionalInt);
462gen_div_ceil!(nstd_core_math_div_ceil_uint, NSTDUInt, NSTDOptionalUInt);
463gen_div_ceil!(nstd_core_math_div_ceil_i8, NSTDInt8, NSTDOptionalInt8);
464gen_div_ceil!(nstd_core_math_div_ceil_u8, NSTDUInt8, NSTDOptionalUInt8);
465gen_div_ceil!(nstd_core_math_div_ceil_i16, NSTDInt16, NSTDOptionalInt16);
466gen_div_ceil!(nstd_core_math_div_ceil_u16, NSTDUInt16, NSTDOptionalUInt16);
467gen_div_ceil!(nstd_core_math_div_ceil_i32, NSTDInt32, NSTDOptionalInt32);
468gen_div_ceil!(nstd_core_math_div_ceil_u32, NSTDUInt32, NSTDOptionalUInt32);
469gen_div_ceil!(nstd_core_math_div_ceil_i64, NSTDInt64, NSTDOptionalInt64);
470gen_div_ceil!(nstd_core_math_div_ceil_u64, NSTDUInt64, NSTDOptionalUInt64);
471
472/// Generates the `div_floor` functions.
473macro_rules! gen_div_floor {
474 ($name: ident, $T: ty, $Opt: ty) => {
475 /// Divides two numbers and rounds the result down to the next integer.
476 ///
477 /// # Parameters:
478 ///
479 #[doc = concat!(" - `", stringify!($T), " x` - The first value.")]
480 ///
481 #[doc = concat!(" - `", stringify!($T), " y` - The second value.")]
482 ///
483 /// # Returns
484 ///
485 #[doc = concat!(" `", stringify!($Opt), " v` - The divided value rounded down on success, or an uninitialized \"none\" variant if `y` is 0 or overflow occurs.")]
486 ///
487 /// # Example
488 ///
489 /// ```
490 #[doc = concat!("use nstd_sys::core::{math::", stringify!($name), ", optional::NSTDOptional};")]
491 ///
492 /// # unsafe {
493 #[doc = concat!("assert!(", stringify!($name), "(5, 2) == NSTDOptional::Some(2));")]
494 #[doc = concat!("assert!(", stringify!($name), "(13, 4) == NSTDOptional::Some(3));")]
495 #[doc = concat!("assert!(", stringify!($name), "(23, 5) == NSTDOptional::Some(4));")]
496 #[doc = concat!("assert!(", stringify!($name), "(23, 0) == NSTDOptional::None);")]
497 /// # }
498 /// ```
499 #[nstdapi]
500 #[allow(unused_comparisons)]
501 pub const fn $name(x: $T, y: $T) -> $Opt {
502 if let Some(v) = x.checked_div(y) {
503 if let Some(r) = x.checked_rem(y) {
504 return match (r > 0 && y < 0) || (r < 0 && y > 0) {
505 true => match v.checked_sub(1) {
506 Some(v) => NSTDOptional::Some(v),
507 _ => NSTDOptional::None,
508 },
509 false => NSTDOptional::Some(v),
510 };
511 }
512 }
513 NSTDOptional::None
514 }
515 };
516}
517gen_div_floor!(nstd_core_math_div_floor_int, NSTDInt, NSTDOptionalInt);
518gen_div_floor!(nstd_core_math_div_floor_uint, NSTDUInt, NSTDOptionalUInt);
519gen_div_floor!(nstd_core_math_div_floor_i8, NSTDInt8, NSTDOptionalInt8);
520gen_div_floor!(nstd_core_math_div_floor_u8, NSTDUInt8, NSTDOptionalUInt8);
521gen_div_floor!(nstd_core_math_div_floor_i16, NSTDInt16, NSTDOptionalInt16);
522gen_div_floor!(nstd_core_math_div_floor_u16, NSTDUInt16, NSTDOptionalUInt16);
523gen_div_floor!(nstd_core_math_div_floor_i32, NSTDInt32, NSTDOptionalInt32);
524gen_div_floor!(nstd_core_math_div_floor_u32, NSTDUInt32, NSTDOptionalUInt32);
525gen_div_floor!(nstd_core_math_div_floor_i64, NSTDInt64, NSTDOptionalInt64);
526gen_div_floor!(nstd_core_math_div_floor_u64, NSTDUInt64, NSTDOptionalUInt64);