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);