mathx/math.rs
1
2use core::ops::Range;
3
4/// A "static" structure used to compute math functions. Since `f32` gets a lot of it's
5/// functions stripped away when using `no_std`, you can use this structure to regain
6/// those functions. It will also work the same even if you don't use it for `no_std`.
7pub struct Math;
8
9// Constants
10impl Math {
11 pub const PI: f32 = 3.14159265359;
12 pub const PI_OVER_2: f32 = 1.570796326;
13 pub const PI_OVER_4: f32 = 0.785398163;
14 pub const TWO_PI: f32 = 6.28318530718;
15 pub const E: f32 = 2.71828182845;
16 pub const DEG_TO_RAD: f32 = 0.01745329251;
17 pub const RAD_TO_DEG: f32 = 57.2957795131;
18 pub const LN2: f32 = 0.69314718056;
19 pub const LN10: f32 = 2.30258509299;
20}
21
22// Public Functions
23impl Math {
24 /// Gets the absolute value of the number
25 /// - **value**: The number to get the absolute value from
26 ///
27 /// **Returns**: Returns the absolute value of the number
28 /// #### Examples
29 /// ```
30 /// # use mathx::Math;
31 /// let value = Math::abs(10.0);
32 /// assert_eq!(10.0, value);
33 /// let value = Math::abs(-10.0);
34 /// assert_eq!(10.0, value);
35 /// let value = Math::abs(-0.0);
36 /// assert_eq!(0.0, value);
37 /// ```
38 pub fn abs(value: f32) -> f32 {
39 #[cfg(not(feature = "no_std"))] { value.abs() }
40 #[cfg(feature = "no_std")] {
41 if value < 0.0 { -value } else { value }
42 }
43 }
44
45 /// Gets the absolute value of the number
46 /// - **value**: The number to get the absolute value from
47 ///
48 /// **Returns**: Returns the absolute value of the number
49 /// #### Examples
50 /// ```
51 /// # use mathx::Math;
52 /// let value = Math::abs_i32(10);
53 /// assert_eq!(10, value);
54 /// let value = Math::abs_i32(-10);
55 /// assert_eq!(10, value);
56 /// let value = Math::abs_i32(-0);
57 /// assert_eq!(0, value);
58 /// ```
59 pub fn abs_i32(value: i32) -> i32 {
60 #[cfg(not(feature = "no_std"))] { value.abs() }
61 #[cfg(feature = "no_std")] {
62 if value < 0 { -value } else { value }
63 }
64 }
65
66 /// Finds if the two floating point numbers are approximately close to each other. Checks with epsilon = 0.000001
67 /// - **a**: The first number to check with
68 /// - **b**: The second number to check with
69 ///
70 /// **Returns**: Returns true if the two values are approximately close to each other
71 /// #### Examples
72 /// ```
73 /// # use mathx::Math;
74 /// assert!(Math::approx(1.20000001, 1.2));
75 /// ```
76 pub fn approx(a: f32, b: f32) -> bool {
77 Math::abs(a - b) < 0.000001
78 }
79
80 /// Finds if the two floating point numbers are approximately close to each other, provided the epsilon
81 /// - **a**: The first number to check with
82 /// - **b**: The second number to check with
83 /// - **epsilon**: The epsilon (smallest possible difference between numbers) to check with
84 ///
85 /// **Returns**: Returns true if the two values are approximately close to each other
86 /// #### Examples
87 /// ```
88 /// # use mathx::Math;
89 /// assert!(Math::approx_epsilon(1.2001, 1.2, 0.001));
90 /// ```
91 pub fn approx_epsilon(a: f32, b: f32, epsilon: f32) -> bool {
92 Math::abs(a - b) < epsilon
93 }
94
95 /// Computes the arc cosine (a.k.a. inverse cosine) with the provided value
96 /// - **value**: The value to compute the arc cosine with, must be within -1 and 1
97 ///
98 /// **Returns**: Returns the angle at which the value exists in radians,
99 /// returns `NaN` if the value provided is less than -1 or greater than 1
100 /// #### Examples
101 /// ```
102 /// # use mathx::{Math,assert_range};
103 /// let value = Math::acos(0.0);
104 /// assert_range!(Math::PI_OVER_2, value);
105 /// let value = Math::acos(1.0);
106 /// assert_range!(0.0, value);
107 /// let value = Math::acos(-1.0);
108 /// assert_range!(Math::PI, value);
109 /// let value = Math::acos(0.707106781);
110 /// assert_range!(Math::PI_OVER_4, value);
111 /// let value = Math::acos(0.540302306);
112 /// assert_range!(1.0, value);
113 /// let value = Math::acos(2.0);
114 /// assert!(value.is_nan());
115 /// let value = Math::acos(-1.001);
116 /// assert!(value.is_nan());
117 /// ```
118 pub fn acos(value: f32) -> f32 {
119 #[cfg(not(feature = "no_std"))] { value.acos() }
120 #[cfg(feature = "no_std")] {
121 if value < -1.0 || value > 1.0 { return f32::NAN; }
122
123 let negate = if value <= -0.0 { 1.0 } else { 0.0 };
124 let value = Math::abs(value);
125 let mut angle = -0.0187293;
126
127 angle *= value;
128 angle += 0.0742610;
129 angle *= value;
130 angle -= 0.2121144;
131 angle *= value;
132 angle += Math::PI_OVER_2;
133 angle *= Math::sqrt(1.0 - value);
134 angle -= 2.0 * negate * angle;
135
136 return negate * Math::PI + angle;
137 }
138 }
139
140 /// Computes the arc cosine (a.k.a. inverse cosine) with the provided value
141 /// - **value**: The value to compute the arc cosine with, must be within -1 and 1
142 ///
143 /// **Returns**: Returns the angle at which the value exists in degrees,
144 /// returns `NaN` if the value provided is less than -1 or greater than 1
145 /// #### Examples
146 /// ```
147 /// # use mathx::{Math,assert_range};
148 /// let value = Math::acos_deg(0.0);
149 /// assert_range!(90.0, value);
150 /// let value = Math::acos_deg(1.0);
151 /// assert_range!(0.0, value);
152 /// let value = Math::acos_deg(-1.0);
153 /// assert_range!(180.0, value);
154 /// let value = Math::acos_deg(0.707106781);
155 /// assert_range!(45.0, value, 0.005);
156 /// let value = Math::acos_deg(0.540302306);
157 /// assert_range!(57.29578, value, 0.001);
158 /// let value = Math::acos_deg(2.0);
159 /// assert!(value.is_nan());
160 /// let value = Math::acos_deg(-1.001);
161 /// assert!(value.is_nan());
162 /// ```
163 pub fn acos_deg(value: f32) -> f32 { Math::RAD_TO_DEG * Math::acos(value) }
164
165 /// Computes the arc hyperbolic cosine (a.k.a. inverse hyperbolic cosine)
166 /// - **value**: The value to compute with
167 ///
168 /// **Returns**: Returns the computed inverse hyperbolic cosine
169 /// #### Examples
170 /// ```
171 /// # use mathx::{Math,assert_range};
172 /// let value = Math::acosh(0.0);
173 /// assert!(value.is_nan());
174 /// let value = Math::acosh(1.0);
175 /// assert_range!(0.0, value);
176 /// let value = Math::acosh(1.54308063482);
177 /// assert_range!(1.0, value);
178 /// let value = Math::acosh(11.591954);
179 /// assert_range!(Math::PI, value);
180 /// let value = Math::acosh(7.6101246);
181 /// assert_range!(Math::E, value);
182 /// ```
183 pub fn acosh(value: f32) -> f32 {
184 #[cfg(not(feature = "no_std"))] { value.acosh() }
185 #[cfg(feature = "no_std")] {
186 if value < 1.0 { return f32::NAN; }
187 Math::ln(value + Math::sqrt(value * value - 1.0))
188 }
189 }
190
191 /// Computes the arc sine (a.k.a. inverse sine) with the provided value
192 /// - **value**: The value to compute the arc sine with, must be within -1 and 1
193 ///
194 /// **Returns**: Returns the angle at which the value exists in radians,
195 /// returns `NaN` if the value provided is less than -1 or greater than 1
196 /// #### Examples
197 /// ```
198 /// # use mathx::{Math,assert_range};
199 /// let value = Math::asin(0.0);
200 /// assert_range!(0.0, value);
201 /// let value = Math::asin(1.0);
202 /// assert_range!(Math::PI_OVER_2, value);
203 /// let value = Math::asin(-1.0);
204 /// assert_range!(-Math::PI_OVER_2, value);
205 /// let value = Math::asin(0.707106781);
206 /// assert_range!(Math::PI_OVER_4, value);
207 /// let value = Math::asin(-1.1);
208 /// assert!(value.is_nan());
209 /// let value = Math::asin(2.0);
210 /// assert!(value.is_nan());
211 /// let value = Math::asin(0.9999);
212 /// assert_range!(1.5566529, value);
213 /// let value = Math::asin(-0.25);
214 /// assert_range!(-0.25268024, value);
215 /// ```
216 pub fn asin(value: f32) -> f32 {
217 #[cfg(not(feature = "no_std"))] { value.asin() }
218 #[cfg(feature = "no_std")] {
219 if value < -1.0 || value > 1.0 { return f32::NAN; }
220
221 let negate = if value < 0.0 { 1.0 } else { 0.0 };
222 let value = Math::abs(value);
223 let mut angle = -0.0187293;
224
225 angle *= value;
226 angle += 0.0742610;
227 angle *= value;
228 angle -= 0.2121144;
229 angle *= value;
230 angle += Math::PI_OVER_2;
231 angle = Math::PI * 0.5 - Math::sqrt(1.0 - value) * angle;
232
233 return angle - 2.0 * negate * angle;
234 }
235 }
236
237 /// Computes the arc sine (a.k.a. inverse sine) with the provided value
238 /// - **value**: The value to compute the arc sine with, must be within -1 and 1
239 ///
240 /// **Returns**: Returns the angle at which the value exists in degrees,
241 /// returns `NaN` if the value provided is less than -1 or greater than 1
242 /// #### Examples
243 /// ```
244 /// # use mathx::{Math,assert_range};
245 /// let value = Math::asin_deg(0.0);
246 /// assert_range!(0.0, value);
247 /// let value = Math::asin_deg(1.0);
248 /// assert_range!(90.0, value);
249 /// let value = Math::asin_deg(-1.0);
250 /// assert_range!(-90.0, value);
251 /// let value = Math::asin_deg(0.707106781);
252 /// assert_range!(45.0, value, 0.005);
253 /// let value = Math::asin_deg(-1.1);
254 /// assert!(value.is_nan());
255 /// let value = Math::asin_deg(2.0);
256 /// assert!(value.is_nan());
257 /// let value = Math::asin_deg(0.9999);
258 /// assert_range!(89.189644, value);
259 /// let value = Math::asin_deg(-0.25);
260 /// assert_range!(-14.477511, value, 0.005);
261 /// ```
262 pub fn asin_deg(value: f32) -> f32 { Math::RAD_TO_DEG * Math::asin(value) }
263
264 /// Computes the arc hyperbolic sine (a.k.a. inverse hyperbolic sine)
265 /// - **value**: The value to compute with
266 ///
267 /// **Returns**: Returns the computed inverse hyperbolic sine
268 /// #### Examples
269 /// ```
270 /// # use mathx::{Math,assert_range};
271 /// let value = Math::asinh(0.0);
272 /// assert_range!(0.0, value);
273 /// let value = Math::asinh(1.0);
274 /// assert_range!(0.8813736, value);
275 /// let value = Math::asinh(1.1752012);
276 /// assert_range!(1.0, value);
277 /// let value = Math::asinh(-1.1752012);
278 /// assert_range!(-1.0, value);
279 /// let value = Math::asinh(11.54874);
280 /// assert_range!(Math::PI, value);
281 /// let value = Math::asinh(7.5441365);
282 /// assert_range!(Math::E, value);
283 /// ```
284 pub fn asinh(value: f32) -> f32 {
285 #[cfg(not(feature = "no_std"))] { value.asinh() }
286 #[cfg(feature = "no_std")] {
287 Math::ln(value + Math::sqrt(value * value + 1.0))
288 }
289 }
290
291 /// Computes the arc tangent (a.k.a. inverse tangent) with the provided value
292 /// - **value**: The value to compute the arc tangent with
293 ///
294 /// **Returns**: Returns the angle at which the value exists in radians
295 /// #### Examples
296 /// ```
297 /// # use mathx::{Math,assert_range};
298 /// let value = Math::atan(0.0);
299 /// assert_range!(0.0, value);
300 /// let value = Math::atan(1.0);
301 /// assert_range!(Math::PI_OVER_4, value);
302 /// let value = Math::atan(-1.0);
303 /// assert_range!(-Math::PI_OVER_4, value);
304 /// let value = Math::atan(0.707106781);
305 /// assert_range!(0.615479708546, value);
306 /// let value = Math::atan(1.557407725);
307 /// assert_range!(1.0, value);
308 /// ```
309 pub fn atan(value: f32) -> f32 {
310 #[cfg(not(feature = "no_std"))] { value.atan() }
311 #[cfg(feature = "no_std")] {
312 Math::atan2(value, 1.0)
313 }
314 }
315
316 /// Computes the arc tangent (a.k.a. inverse tangent) with the provided value
317 /// - **value**: The value to compute the arc tangent with
318 ///
319 /// **Returns**: Returns the angle at which the value exists in degrees
320 /// #### Examples
321 /// ```
322 /// # use mathx::{Math,assert_range};
323 /// let value = Math::atan_deg(0.0);
324 /// assert_range!(0.0, value);
325 /// let value = Math::atan_deg(1.0);
326 /// assert_range!(45.0, value, 0.001);
327 /// let value = Math::atan_deg(-1.0);
328 /// assert_range!(-45.0, value, 0.001);
329 /// let value = Math::atan_deg(0.707106781);
330 /// assert_range!(35.26439, value, 0.001);
331 /// let value = Math::atan_deg(1.557407725);
332 /// assert_range!(57.29578, value);
333 /// ```
334 pub fn atan_deg(value: f32) -> f32 { Math::RAD_TO_DEG * Math::atan(value) }
335
336 /// Computes the arc hyperbolic tangent (a.k.a. inverse hyperbolic tangent)
337 /// - **value**: The value to compute with
338 ///
339 /// **Returns**: Returns the computed inverse hyperbolic tangent
340 /// #### Examples
341 /// ```
342 /// # use mathx::{Math,assert_range};
343 /// let value = Math::atanh(0.0);
344 /// assert_range!(0.0, value);
345 /// let value = Math::atanh(1.0);
346 /// assert!(value.is_infinite());
347 /// let value = Math::atanh(0.7615942);
348 /// assert_range!(1.0, value, 0.001);
349 /// let value = Math::atanh(-0.7615942);
350 /// assert_range!(-1.0, value, 0.001);
351 /// let value = Math::atanh(0.9962721);
352 /// assert_range!(Math::PI, value);
353 /// let value = Math::atanh(0.9913289);
354 /// assert_range!(Math::E, value);
355 /// ```
356 pub fn atanh(value: f32) -> f32 {
357 #[cfg(not(feature = "no_std"))] { value.atanh() }
358 #[cfg(feature = "no_std")] {
359 if value >= 1.0 { return f32::INFINITY; }
360 if value <= -1.0 { return f32::NEG_INFINITY; }
361 0.5 * Math::ln((1.0 + value) * (1.0 - value).recip())
362 }
363 }
364
365 /// Computes the arc tangent (a.k.a. inverse tangent) with the provided x and y values
366 /// - **y**: The y value to compute the arc tangent with
367 /// - **x**: The x value to compute the arc tangent with
368 ///
369 /// **Returns**: Returns the angle at with the two values divided exists in radians
370 /// #### Examples
371 /// ```
372 /// # use mathx::{Math,assert_range};
373 /// let value = Math::atan2(0.0, 1.0);
374 /// assert_range!(0.0, value);
375 /// let value = Math::atan2(1.0, 1.0);
376 /// assert_range!(Math::PI_OVER_4, value);
377 /// let value = Math::atan2(-1.0, 1.0);
378 /// assert_range!(-Math::PI_OVER_4, value);
379 /// let value = Math::atan2(5.0, 1.0);
380 /// assert_range!(1.3734008, value);
381 /// let value = Math::atan2(1.0, 5.0);
382 /// assert_range!(0.19739556, value);
383 /// let value = Math::atan2(-5.0, 1.0);
384 /// assert_range!(-1.3734008, value);
385 /// let value = Math::atan2(-1.0, 5.0);
386 /// assert_range!(-0.19739556, value);
387 /// ```
388 pub fn atan2(y: f32, x: f32) -> f32 {
389 #[cfg(not(feature = "no_std"))] { y.atan2(x) }
390 #[cfg(feature = "no_std")] {
391 let mut a = Math::abs(x);
392 let mut b = Math::abs(y);
393 let mut c = Math::max(a, b);
394 b = Math::min(a, b);
395 a = c.recip();
396 a = b * a;
397
398 let d = a * a;
399 c = -0.013480470;
400 c = c * d + 0.057477314;
401 c = c * d - 0.121239071;
402 c = c * d + 0.195635925;
403 c = c * d - 0.332994597;
404 c = c * d + 0.999995630;
405 a *= c;
406
407 if Math::abs(y) > Math::abs(x) { a = Math::PI_OVER_2 - a; }
408 if x < 0.0 { a = Math::PI - a; }
409 if y < 0.0 { a *= -1.0; }
410
411 return a;
412 }
413 }
414
415 /// Computes the arc tangent (a.k.a. inverse tangent) with the provided x and y values
416 /// - **y**: The y value to compute the arc tangent with
417 /// - **x**: The x value to compute the arc tangent with
418 ///
419 /// **Returns**: Returns the angle at with the two values divided exists in degrees
420 /// #### Examples
421 /// ```
422 /// # use mathx::{Math,assert_range};
423 /// let value = Math::atan2_deg(0.0, 1.0);
424 /// assert_range!(0.0, value);
425 /// let value = Math::atan2_deg(1.0, 1.0);
426 /// assert_range!(45.0, value, 0.005);
427 /// let value = Math::atan2_deg(-1.0, 1.0);
428 /// assert_range!(-45.0, value, 0.005);
429 /// let value = Math::atan2_deg(5.0, 1.0);
430 /// assert_range!(78.69007, value);
431 /// let value = Math::atan2_deg(1.0, 5.0);
432 /// assert_range!(11.309933, value);
433 /// let value = Math::atan2_deg(-5.0, 1.0);
434 /// assert_range!(-78.69007, value);
435 /// let value = Math::atan2_deg(-1.0, 5.0);
436 /// assert_range!(-11.309933, value);
437 /// ```
438 pub fn atan2_deg(y: f32, x: f32) -> f32 { Math::RAD_TO_DEG * Math::atan2(y, x) }
439
440 /// Gets the smallest integer number that is greater than or equal to the given number
441 /// - **value**: The value to get the ceiling with
442 ///
443 /// **Returns**: Returns the ceiling number
444 /// #### Examples
445 /// ```
446 /// # use mathx::Math;
447 /// let value = Math::ceil(-3.0);
448 /// assert_eq!(-3.0, value);
449 /// let value = Math::ceil(1.4);
450 /// assert_eq!(2.0, value);
451 /// let value = Math::ceil(2.9);
452 /// assert_eq!(3.0, value);
453 /// let value = Math::ceil(-4.9);
454 /// assert_eq!(-4.0, value);
455 /// let value = Math::ceil(-5.3);
456 /// assert_eq!(-5.0, value);
457 /// ```
458 pub fn ceil(value: f32) -> f32 {
459 #[cfg(not(feature = "no_std"))] { value.ceil() }
460 #[cfg(feature = "no_std")] {
461 let truncated = Math::trunc(value);
462
463 if truncated == value { return truncated; }
464
465 return truncated + if value < 0.0 { 0.0 } else { 1.0 };
466 }
467 }
468
469 /// Clamps the value between the min and max values
470 /// - **value**: The value to clamp with
471 /// - **min**: The lower-bound minimum value to clamp to
472 /// - **max**: The upper-bound maximum value to clamp to
473 ///
474 /// **Returns**: Returns the clamped value
475 /// #### Examples
476 /// ```
477 /// # use mathx::Math;
478 /// let value = Math::clamp(20.0, 0.0, 10.0);
479 /// assert_eq!(10.0, value);
480 /// let value = Math::clamp(20.0, 0.0, 100.0);
481 /// assert_eq!(20.0, value);
482 /// let value = Math::clamp(-0.001, 0.0, 10.0);
483 /// assert_eq!(0.0, value);
484 /// let value = Math::clamp(0.18, -0.1, 0.1);
485 /// assert_eq!(0.1, value);
486 /// ```
487 pub fn clamp(value: f32, min: f32, max: f32) -> f32 { value.clamp(min, max) }
488
489 /// Computes the cosine of the given angle in radians
490 /// - **angle**: The angle to compute cosine with in radians
491 ///
492 /// **Returns**: Returns a value from the computed cosine
493 /// #### Remarks
494 /// If you need to compute both `cos` and `sin` of the same angle, use `sin_cos` instead as it's more
495 /// performant to produce both values than calling `cos` and `sin` separately
496 /// #### Examples
497 /// ```
498 /// # use mathx::{Math,assert_range};
499 /// let value = Math::cos(0.0);
500 /// assert_range!(1.0, value);
501 /// let value = Math::cos(Math::PI_OVER_2);
502 /// assert_range!(0.0, value);
503 /// let value = Math::cos(Math::PI);
504 /// assert_range!(-1.0, value);
505 /// let value = Math::cos(Math::PI + Math::PI_OVER_2);
506 /// assert_range!(0.0, value);
507 /// let value = Math::cos(Math::TWO_PI);
508 /// assert_range!(1.0, value);
509 /// let value = Math::cos(Math::PI_OVER_4);
510 /// assert_range!(0.707106781, value);
511 /// let value = Math::cos(1.0);
512 /// assert_range!(0.540302306, value);
513 /// let value = Math::cos(-100.0);
514 /// assert_range!(0.862318872, value);
515 /// ```
516 pub fn cos(angle: f32) -> f32 { Math::sin_cos(angle).1 }
517
518 /// Computes the cosine of the given angle in degrees
519 /// - **angle**: The angle to compute cosine with in degrees
520 ///
521 /// **Returns**: Returns a value from the computed cosine
522 /// #### Remarks
523 /// If you need to compute both `cos_deg` and `sin_deg` of the same angle, use `sin_cos_deg` instead as it's more
524 /// performant to produce both values than calling `cos_deg` and `sin_deg` separately
525 /// #### Examples
526 /// ```
527 /// # use mathx::{Math,assert_range};
528 /// let value = Math::cos_deg(0.0);
529 /// assert_range!(1.0, value);
530 /// let value = Math::cos_deg(90.0);
531 /// assert_range!(0.0, value);
532 /// let value = Math::cos_deg(180.0);
533 /// assert_range!(-1.0, value);
534 /// let value = Math::cos_deg(270.0);
535 /// assert_range!(0.0, value);
536 /// let value = Math::cos_deg(360.0);
537 /// assert_range!(1.0, value);
538 /// let value = Math::cos_deg(45.0);
539 /// assert_range!(0.707106781, value);
540 /// let value = Math::cos_deg(57.29577951);
541 /// assert_range!(0.540302306, value);
542 /// let value = Math::cos_deg(-5729.577951);
543 /// assert_range!(0.862318872, value);
544 /// ```
545 pub fn cos_deg(angle: f32) -> f32 { Math::cos(Math::DEG_TO_RAD * angle) }
546
547 /// Computes the hyperbolic cosine function
548 /// - **value**: The value to compute the hyperbolic cosine function
549 ///
550 /// **Returns**: Returns the computed hyperbolic cosine function
551 /// #### Examples
552 /// ```
553 /// # use mathx::{Math,assert_range};
554 /// let value = Math::cosh(0.0);
555 /// assert_range!(1.0, value);
556 /// let value = Math::cosh(1.0);
557 /// assert_range!(1.54308063482, value);
558 /// let value = Math::cosh(-1.0);
559 /// assert_range!(1.54308063482, value);
560 /// let value = Math::cosh(Math::PI);
561 /// assert_range!(11.591954, value);
562 /// let value = Math::cosh(Math::E);
563 /// assert_range!(7.6101246, value);
564 /// ```
565 pub fn cosh(value: f32) -> f32 {
566 #[cfg(not(feature = "no_std"))] { value.cosh() }
567 #[cfg(feature = "no_std")] {
568 let exp = Math::exp(value);
569
570 if exp.is_infinite() || exp.is_nan() {
571 if value > 0.0 { return f32::INFINITY; }
572 else { return f32::NEG_INFINITY; }
573 }
574
575 (exp + exp.recip()) * 0.5
576 }
577 }
578
579 /// Computes the cotangent of the given angle in radians
580 /// - **angle**: The angle to compute the cotangent with in radians
581 ///
582 /// **Returns**: Returns the computed cotangent value
583 /// #### Examples
584 /// ```
585 /// # use mathx::{Math,assert_range};
586 /// let value = Math::cot(Math::PI_OVER_2);
587 /// assert_range!(0.0, value);
588 /// let value = Math::cot(Math::PI + Math::PI_OVER_2);
589 /// assert_range!(0.0, value);
590 /// let value = Math::cot(Math::PI_OVER_4);
591 /// assert_range!(1.0, value);
592 /// let value = Math::cot(1.0);
593 /// assert_range!(0.642092616, value);
594 /// let value = Math::cot(-100.0);
595 /// assert_range!(1.702956919, value);
596 /// ```
597 pub fn cot(angle: f32) -> f32 { Math::tan(angle).recip() }
598
599 /// Computes the cotangent of the given angle in degrees
600 /// - **angle**: The angle to compute the cotangent with in degrees
601 ///
602 /// **Returns**: Returns the computed cotangent value
603 /// #### Examples
604 /// ```
605 /// # use mathx::{Math,assert_range};
606 /// let value = Math::cot_deg(90.0);
607 /// assert_range!(0.0, value);
608 /// let value = Math::cot_deg(270.0);
609 /// assert_range!(0.0, value);
610 /// let value = Math::cot_deg(45.0);
611 /// assert_range!(1.0, value);
612 /// let value = Math::cot_deg(57.29577951);
613 /// assert_range!(0.642092616, value);
614 /// let value = Math::cot_deg(-5729.577951);
615 /// assert_range!(1.702956919, value);
616 /// ```
617 pub fn cot_deg(angle: f32) -> f32 { Math::cot(Math::DEG_TO_RAD * angle) }
618
619 /// Computes the cosecant of the given angle in radians
620 /// - **angle**: The angle to compute the cosecant with in radians
621 ///
622 /// **Returns**: Returns the computed cosecant value
623 /// #### Examples
624 /// ```
625 /// # use mathx::{Math,assert_range};
626 /// let value = Math::csc(Math::PI_OVER_2);
627 /// assert_range!(1.0, value);
628 /// let value = Math::csc(Math::PI + Math::PI_OVER_2);
629 /// assert_range!(-1.0, value);
630 /// let value = Math::csc(Math::PI_OVER_4);
631 /// assert_range!(1.414213562, value);
632 /// let value = Math::csc(1.0);
633 /// assert_range!(1.188395106, value);
634 /// let value = Math::csc(-100.0);
635 /// assert_range!(1.974857531, value);
636 /// ```
637 pub fn csc(angle: f32) -> f32 { Math::sin(angle).recip() }
638
639 /// Computes the cosecant of the given angle in degrees
640 /// - **angle**: The angle to compute the cosecant with in degrees
641 ///
642 /// **Returns**: Returns the computed cosecant value
643 /// #### Examples
644 /// ```
645 /// # use mathx::{Math,assert_range};
646 /// let value = Math::csc_deg(90.0);
647 /// assert_range!(1.0, value);
648 /// let value = Math::csc_deg(270.0);
649 /// assert_range!(-1.0, value);
650 /// let value = Math::csc_deg(45.0);
651 /// assert_range!(1.414213562, value);
652 /// let value = Math::csc_deg(57.29577951);
653 /// assert_range!(1.188395106, value);
654 /// let value = Math::csc_deg(-5729.577951);
655 /// assert_range!(1.974857531, value);
656 /// ```
657 pub fn csc_deg(angle: f32) -> f32 { Math::csc(Math::DEG_TO_RAD * angle) }
658
659 /// Converts the value from degrees to radians
660 /// - **degrees**: The value in degrees to convert
661 ///
662 /// **Returns**: Returns the value in radians
663 /// #### Examples
664 /// ```
665 /// # use mathx::Math;
666 /// let value = Math::deg2rad(35.0);
667 /// assert_eq!(0.610865238198, value);
668 /// let value = Math::deg2rad(300.0);
669 /// assert_eq!(5.23598775598, value);
670 /// ```
671 pub fn deg2rad(degrees: f32) -> f32 { Math::DEG_TO_RAD * degrees }
672
673 /// Computes e^x
674 /// - **value**: The value to compute with
675 ///
676 /// **Returns**: Returns the computed e^x
677 /// #### Examples
678 /// ```
679 /// # use mathx::{Math,assert_range};
680 /// let value = Math::exp(0.0);
681 /// assert_range!(1.0, value);
682 /// let value = Math::exp(-10.0);
683 /// assert_range!(0.000004539993, value);
684 /// let value = Math::exp(10.0);
685 /// assert_range!(22026.465, value);
686 /// let value = Math::exp(12.34);
687 /// assert_range!(228661.98, value, 0.05);
688 /// let value = Math::exp(2.9);
689 /// assert_range!(18.174147, value);
690 /// ```
691 pub fn exp(value: f32) -> f32 {
692 #[cfg(not(feature = "no_std"))] { value.exp() }
693 #[cfg(feature = "no_std")] {
694 if value < 0.0 { return Math::exp(-value).recip(); }
695
696 let mut result = 1.0;
697 let mut term = 1.0;
698 let mut n = 1;
699
700 while n <= 100 {
701 term *= value / n as f32;
702 result += term;
703 n += 1;
704 }
705
706 return result;
707 }
708 }
709
710 /// Computes 2^x
711 /// - **value**: The value to compute with
712 ///
713 /// **Returns**: Returns the computed 2^x
714 /// #### Examples
715 /// ```
716 /// # use mathx::{Math,assert_range};
717 /// let value = Math::exp2(0.0);
718 /// assert_range!(1.0, value);
719 /// let value = Math::exp2(-10.0);
720 /// assert_range!(0.0009765625, value);
721 /// let value = Math::exp2(10.0);
722 /// assert_range!(1024.0, value, 0.0002);
723 /// let value = Math::exp2(12.34);
724 /// assert_range!(5184.5396, value, 0.05);
725 /// let value = Math::exp2(2.9);
726 /// assert_range!(7.464265, value);
727 /// ```
728 pub fn exp2(value: f32) -> f32 {
729 #[cfg(not(feature = "no_std"))] { value.exp2() }
730 #[cfg(feature = "no_std")] {
731 Math::exp(value * Math::LN2)
732 }
733 }
734
735 /// Gets the largest integer number that is less than or equal to the given number
736 /// - **value**: The value to get the floor with
737 ///
738 /// **Returns**: Returns the floored number
739 /// #### Examples
740 /// ```
741 /// # use mathx::Math;
742 /// let value = Math::floor(-3.0);
743 /// assert_eq!(-3.0, value);
744 /// let value = Math::floor(1.4);
745 /// assert_eq!(1.0, value);
746 /// let value = Math::floor(2.9);
747 /// assert_eq!(2.0, value);
748 /// let value = Math::floor(-4.9);
749 /// assert_eq!(-5.0, value);
750 /// let value = Math::floor(-5.3);
751 /// assert_eq!(-6.0, value);
752 /// ```
753 pub fn floor(value: f32) -> f32 {
754 #[cfg(not(feature = "no_std"))] { value.floor() }
755 #[cfg(feature = "no_std")] {
756 let truncated = Math::trunc(value);
757
758 if truncated == value { return truncated; }
759
760 return truncated - if value < 0.0 { 1.0 } else { 0.0 };
761 }
762 }
763
764 /// Gets the fractional part of the value, getting only a value between 0 and 1
765 /// - **value**: The value to get the fraction from
766 ///
767 /// **Returns**: Returns the fraction of the given number
768 /// #### Examples
769 /// ```
770 /// # use mathx::{Math,assert_range};
771 /// let value = Math::fract(3.0);
772 /// assert_range!(0.0, value);
773 /// let value = Math::fract(-3.0);
774 /// assert_range!(0.0, value);
775 /// let value = Math::fract(4.9);
776 /// assert_range!(0.9, value);
777 /// let value = Math::fract(-4.9);
778 /// assert_range!(0.1, value);
779 /// let value = Math::fract(12.34);
780 /// assert_range!(0.34, value);
781 /// ```
782 pub fn fract(value: f32) -> f32 { value - Math::floor(value) }
783
784 /// Linearly interpolates between the first and second values
785 /// - **a**: The first value to start from
786 /// - **b**: The second value to end from
787 /// - **t**: The ratio value to interpolate between both values. Clamped between 0.0 and 1.0
788 ///
789 /// **Returns**: Returns the interpolated value
790 /// #### Examples
791 /// ```
792 /// # use mathx::Math;
793 /// let value = Math::lerp(0.0, 1.0, 0.5);
794 /// assert_eq!(0.5, value);
795 /// let value = Math::lerp(0.0, 0.1, 0.9);
796 /// assert_eq!(0.089999996, value);
797 /// let value = Math::lerp(-10.0, 10.0, 0.6);
798 /// assert_eq!(2.0, value);
799 /// let value = Math::lerp(-10.0, -4.0, 0.7);
800 /// assert_eq!(-5.8, value);
801 /// ```
802 pub fn lerp(a: f32, b: f32, t: f32) -> f32 { Math::lerp_unclamped(a, b, Math::clamp(t, 0.0, 1.0)) }
803
804 /// Linearly interpolates between the first and second values (not clamped)
805 /// - **a**: The first value to start from
806 /// - **b**: The second value to end from
807 /// - **t**: The ratio value to interpolate between both values
808 ///
809 /// **Returns**: Returns the interpolated value
810 /// #### Examples
811 /// ```
812 /// # use mathx::Math;
813 /// let value = Math::lerp_unclamped(0.0, 1.0, 0.5);
814 /// assert_eq!(0.5, value);
815 /// let value = Math::lerp_unclamped(0.0, 0.1, 0.9);
816 /// assert_eq!(0.089999996, value);
817 /// let value = Math::lerp_unclamped(-10.0, 10.0, 0.6);
818 /// assert_eq!(2.0, value);
819 /// let value = Math::lerp_unclamped(-10.0, -4.0, 0.7);
820 /// assert_eq!(-5.8, value);
821 /// ```
822 pub fn lerp_unclamped(a: f32, b: f32, t: f32) -> f32 { a + t * (b - a) }
823
824 /// Computes the natural log of the given number
825 /// - **value**: The value to compute the natural log of
826 ///
827 /// **Returns**: Returns the natural log of the given value. Returns `infinity` if the value infinity
828 /// and `-infinity` if the value is 0.0. Returns `NaN` if the value is `NaN` or less than 0.0
829 /// #### Examples
830 /// ```
831 /// # use mathx::{Math,assert_range};
832 /// let value = Math::ln(1.0);
833 /// assert_range!(0.0, value);
834 /// let value = Math::ln(100.0);
835 /// assert_range!(4.60517018599, value);
836 /// let value = Math::ln(0.01);
837 /// assert_range!(-4.60517018599, value);
838 /// let value = Math::ln(Math::E);
839 /// assert_range!(1.0, value);
840 /// let value = Math::ln(2.0);
841 /// assert_range!(0.69314718056, value);
842 /// let value = Math::ln(10.0);
843 /// assert_range!(2.30258509299, value);
844 /// let value = Math::ln(-10.0);
845 /// assert!(value.is_nan());
846 /// let value = Math::ln(0.0);
847 /// assert!(value.is_infinite());
848 /// ```
849 pub fn ln(value: f32) -> f32 {
850 #[cfg(not(feature = "no_std"))] { value.ln() }
851 #[cfg(feature = "no_std")] {
852 if value.is_nan() { return f32::NAN; }
853 if value == 0.0 { return f32::NEG_INFINITY; }
854 if value < 0.0 { return f32::NAN; }
855 if value < 1.0 { return -Math::ln(value.recip()); }
856 if value.is_infinite() { return f32::INFINITY; }
857 if value == 1.0 { return 0.0; }
858
859 let mut x = value;
860 let mut ln10_count = 0;
861 let mut ln2_count = 0;
862
863 while x > 10.0 {
864 x /= 10.0;
865 ln10_count += 1;
866 }
867 while x >= 2.0 {
868 x /= 2.0;
869 ln2_count += 1;
870 }
871
872 if x == 1.0 { return ln2_count as f32 * Math::LN2 + ln10_count as f32 * Math::LN10; }
873
874 let term = x - 1.0;
875 let mut power = term;
876 let mut series = power;
877
878 for i in 2..17 {
879 let negative = if i % 2 == 0 { -1.0 } else { 1.0 };
880
881 power *= term;
882 series += negative * power / i as f32;
883 }
884
885 return ln2_count as f32 * Math::LN2 + ln10_count as f32 * Math::LN10 + series;
886 }
887 }
888
889 /// Computes the natural log of the given number plus one
890 /// - **value**: The value to compute the natural log of
891 ///
892 /// **Returns**: Returns the natural log of the given value. Returns `infinity` if the value infinity
893 /// and `-infinity` if the value is -1.0. Returns `NaN` if the value is `NaN` or less than -1.0
894 /// #### Examples
895 /// ```
896 /// # use mathx::{Math,assert_range};
897 /// let value = Math::ln_1p(1.0);
898 /// assert_range!(0.6931472, value);
899 /// let value = Math::ln_1p(100.0);
900 /// assert_range!(4.6151204, value);
901 /// let value = Math::ln_1p(0.01);
902 /// assert_range!(0.0099503305, value);
903 /// let value = Math::ln_1p(2.0);
904 /// assert_range!(1.0986123, value);
905 /// let value = Math::ln_1p(10.0);
906 /// assert_range!(2.3978953, value);
907 /// let value = Math::ln_1p(-10.0);
908 /// assert!(value.is_nan());
909 /// let value = Math::ln_1p(0.0);
910 /// assert_range!(0.0, value);
911 /// ```
912 pub fn ln_1p(value: f32) -> f32 {
913 #[cfg(not(feature = "no_std"))] { value.ln_1p() }
914 #[cfg(feature = "no_std")] { Math::ln(value + 1.0) }
915 }
916
917 /// Computes the log of the given number with a given base
918 /// - **value**: The value to compute the logarithm with
919 /// - **base**: The base of the logarithm
920 ///
921 /// **Returns**: Returns the computed logarithm
922 /// #### Examples
923 /// ```
924 /// # use mathx::{Math,assert_range};
925 /// let value = Math::log(2.0, 2.0);
926 /// assert_range!(1.0, value);
927 /// let value = Math::log(1.0, 2.0);
928 /// assert_range!(0.0, value);
929 /// let value = Math::log(10.0, 2.0);
930 /// assert_range!(3.32192809489, value);
931 /// let value = Math::log(16.0, 4.0);
932 /// assert_range!(2.0, value);
933 /// let value = Math::log(2.0, 1.0);
934 /// assert!(value.is_infinite());
935 /// ```
936 pub fn log(value: f32, base: f32) -> f32 {
937 #[cfg(not(feature = "no_std"))] { value.log(base) }
938 #[cfg(feature = "no_std")] { Math::ln(value) * Math::ln(base).recip() }
939 }
940
941 /// Computes the log of the given number with base 10
942 /// - **value**: The value to compute the log with
943 ///
944 /// **Returns**: Returns the computed log in base 10
945 /// #### Examples
946 /// ```
947 /// # use mathx::{Math,assert_range};
948 /// let value = Math::log10(1.0);
949 /// assert_range!(0.0, value);
950 /// let value = Math::log10(2.0);
951 /// assert_range!(0.301029995664, value);
952 /// let value = Math::log10(10.0);
953 /// assert_range!(1.0, value);
954 /// let value = Math::log10(50.0);
955 /// assert_range!(1.69897000434, value);
956 /// let value = Math::log10(100.0);
957 /// assert_range!(2.0, value);
958 /// ```
959 pub fn log10(value: f32) -> f32 {
960 #[cfg(not(feature = "no_std"))] { value.log10() }
961 #[cfg(feature = "no_std")] { Math::ln(value) * Math::LN10.recip() }
962 }
963
964 /// Computes the log of the given number with base 2
965 /// - **value**: The value to compute the log with
966 ///
967 /// **Returns**: Returns the computed log in base 2
968 /// #### Examples
969 /// ```
970 /// # use mathx::{Math,assert_range};
971 /// let value = Math::log2(1.0);
972 /// assert_range!(0.0, value);
973 /// let value = Math::log2(2.0);
974 /// assert_range!(1.0, value);
975 /// let value = Math::log2(10.0);
976 /// assert_range!(3.32192809489, value);
977 /// let value = Math::log2(16.0);
978 /// assert_range!(4.0, value);
979 /// ```
980 pub fn log2(value: f32) -> f32 {
981 #[cfg(not(feature = "no_std"))] { value.log2() }
982 #[cfg(feature = "no_std")] { Math::ln(value) * Math::LN2.recip() }
983 }
984
985 /// Maps the value from one range into another range
986 /// - **value**: The value to map
987 /// - **in_range**: The starting input range to map from
988 /// - **out_range**: The ending output range to map to
989 ///
990 /// **Returns**: Returns the mapped value
991 /// #### Examples
992 /// ```
993 /// # use mathx::Math;
994 /// let value = Math::map(1.5, 1.0..2.0, 1.0..2.0);
995 /// assert_eq!(1.5, value);
996 /// let value = Math::map(1.0, 0.0..10.0, 0.0..1.0);
997 /// assert_eq!(0.1, value);
998 /// let value = Math::map(11.0, 0.0..10.0, 0.0..1.0);
999 /// assert_eq!(1.1, value);
1000 /// let value = Math::map(1.0, -10.0..10.0, 0.0..1.0);
1001 /// assert_eq!(0.55, value);
1002 /// let value = Math::map(-10.0, -100.0..-10.0, 10.0..100.0);
1003 /// assert_eq!(100.0, value);
1004 /// ```
1005 pub fn map(value: f32, in_range: Range<f32>, out_range: Range<f32>) -> f32 {
1006 return
1007 (value - in_range.start)
1008 * (out_range.end - out_range.start)
1009 / (in_range.end - in_range.start)
1010 + out_range.start;
1011 }
1012
1013 /// Gets the maximum value between the two values
1014 /// - **a**: The first value to get the maximum value from
1015 /// - **b**: The second value to get the maximum value from
1016 ///
1017 /// **Returns**: Returns the maximum number between the two values
1018 /// #### Examples
1019 /// ```
1020 /// # use mathx::Math;
1021 /// let value = Math::max(-1.0, 1.0);
1022 /// assert_eq!(1.0, value);
1023 /// let value = Math::max(-19.0, -19.1);
1024 /// assert_eq!(-19.0, value);
1025 /// ```
1026 pub fn max(a: f32, b: f32) -> f32 { a.max(b) }
1027
1028 /// Gets the minimum value between the two values
1029 /// - **a**: The first value to get the minimum value from
1030 /// - **b**: The second value to get the minimum value from
1031 ///
1032 /// **Returns**: Returns the minimum number between the two values
1033 /// #### Examples
1034 /// ```
1035 /// # use mathx::Math;
1036 /// let value = Math::min(-1.0, 1.0);
1037 /// assert_eq!(-1.0, value);
1038 /// let value = Math::min(-19.0, -19.1);
1039 /// assert_eq!(-19.1, value);
1040 /// ```
1041 pub fn min(a: f32, b: f32) -> f32 { a.min(b) }
1042
1043 /// Gets the minimum and maximum value returned as a tuple correctly sorted
1044 /// - **a**: The first value to get the minimum and maximum value from
1045 /// - **b**: The second value to get the minimum and maximum value from
1046 ///
1047 /// **Returns**: Returns a tuple that holds the minimum and maximum values respectively
1048 /// #### Examples
1049 /// ```
1050 /// # use mathx::Math;
1051 /// let value = Math::min_max(-1.0, 1.0);
1052 /// assert_eq!((-1.0, 1.0), value);
1053 /// let value = Math::min_max(-19.0, -19.1);
1054 /// assert_eq!((-19.1, -19.0), value);
1055 /// ```
1056 pub fn min_max(a: f32, b: f32) -> (f32, f32) { (Math::min(a, b), Math::max(a, b)) }
1057
1058 /// Raised the value by the power (as a floating point number)
1059 /// - **value**: The value to raise with
1060 /// - **power**: The power to raise by
1061 ///
1062 /// **Returns**: Returns the value raised by the power
1063 /// #### Examples
1064 /// ```
1065 /// # use mathx::{Math,assert_range};
1066 /// let value = Math::pow(1.0, 0.0);
1067 /// assert_range!(1.0, value);
1068 /// let value = Math::pow(1.0, 10.0);
1069 /// assert_range!(1.0, value);
1070 /// let value = Math::pow(2.0, 10.0);
1071 /// assert_range!(1024.0, value, 0.0002);
1072 /// let value = Math::pow(40.0, 1.2);
1073 /// assert_range!(83.65118, value);
1074 /// let value = Math::pow(3.0, -2.3);
1075 /// assert_range!(0.07991368, value);
1076 /// ```
1077 pub fn pow(value: f32, power: f32) -> f32 {
1078 if power == 0.0 { return 1.0; }
1079 if power == 1.0 { return value; }
1080 if value == 1.0 { return 1.0; }
1081 if value == 2.0 { return Math::exp2(power); }
1082
1083 let fract = Math::fract(power);
1084
1085 if fract == 0.0 { return Math::pow_i32(value, Math::floor(power) as i32); }
1086
1087 #[cfg(not(feature = "no_std"))] { value.powf(power) }
1088 #[cfg(feature = "no_std")] {
1089 Math::exp(power * Math::ln(value))
1090 }
1091 }
1092
1093 /// Gets the power of the given number by the other given number, with the power being an `i32`
1094 /// - **a**: The base number to power
1095 /// - **b**: The number to power with
1096 ///
1097 /// **Returns**: Returns the powered number
1098 /// #### Examples
1099 /// ```
1100 /// # use mathx::{Math,assert_range};
1101 /// let value = Math::pow_i32(3.0, 5);
1102 /// assert_range!(243.0, value);
1103 /// let value = Math::pow_i32(10.45, 3);
1104 /// assert_range!(1141.166, value, 0.001);
1105 /// let value = Math::pow_i32(0.0, 0);
1106 /// assert_range!(1.0, value);
1107 /// let value = Math::pow_i32(10.0, 0);
1108 /// assert_range!(1.0, value);
1109 /// let value = Math::pow_i32(0.0, 2);
1110 /// assert_range!(0.0, value);
1111 /// let value = Math::pow_i32(2.0, -3);
1112 /// assert_range!(0.125, value);
1113 /// ```
1114 pub fn pow_i32(a: f32, b: i32) -> f32 {
1115 #[cfg(not(feature = "no_std"))] { a.powi(b) }
1116 #[cfg(feature = "no_std")] {
1117 if b == 0 { return 1.0 }
1118
1119 let mut result = a;
1120
1121 for _ in 1..Math::abs_i32(b) {
1122 result *= a;
1123 }
1124
1125 if b < 0 { result.recip() }
1126 else { result }
1127 }
1128 }
1129
1130 /// Converts the value from radians to degrees
1131 /// - **radians**: The value in radians to convert
1132 ///
1133 /// **Returns**: Returns the value in degrees
1134 /// #### Examples
1135 /// ```
1136 /// # use mathx::Math;
1137 /// let value = Math::rad2deg(1.0);
1138 /// assert_eq!(57.2957795131, value);
1139 /// let value = Math::rad2deg(4.0);
1140 /// assert_eq!(229.183118052, value);
1141 /// ```
1142 pub fn rad2deg(radians: f32) -> f32 { Math::RAD_TO_DEG * radians }
1143
1144 /// Repeats the value around the range, making sure it stays within the range
1145 /// - **value**: The value to repeat
1146 /// - **range**: The range to repeat around
1147 ///
1148 /// **Returns**: Returns the wrapped value
1149 /// #### Examples
1150 /// ```
1151 /// # use mathx::{Math,assert_range};
1152 /// let value = Math::repeat(1.0, 0.0..2.0);
1153 /// assert_range!(1.0, value);
1154 /// let value = Math::repeat(1.0, 2.0..3.0);
1155 /// assert_range!(3.0, value);
1156 /// let value = Math::repeat(5.3, 0.0..3.0);
1157 /// assert_range!(2.3, value);
1158 /// let value = Math::repeat(-4.0, 0.0..1.23);
1159 /// assert_range!(0.31, value);
1160 /// let value = Math::repeat(-4.0, 10.0..12.23);
1161 /// assert_range!(10.620003, value);
1162 /// ```
1163 pub fn repeat(value: f32, range: Range<f32>) -> f32 {
1164 if value >= range.start && value <= range.end {
1165 return value;
1166 }
1167
1168 let x = value - range.start;
1169 let distance = range.end - range.start;
1170
1171 if x < 0.0 {
1172 return range.end - distance * Math::fract(x * distance.recip());
1173 }
1174
1175 return distance * Math::fract(x * distance.recip()) + range.start;
1176 }
1177
1178 /// Rounds the given value to the nearest zero
1179 /// - **value**: The value to round with
1180 ///
1181 /// **Returns**: Returns the rounded value
1182 /// #### Examples
1183 /// ```
1184 /// # use mathx::Math;
1185 /// let value = Math::round(0.0);
1186 /// assert_eq!(0.0, value);
1187 /// let value = Math::round(1.1);
1188 /// assert_eq!(1.0, value);
1189 /// let value = Math::round(2.9);
1190 /// assert_eq!(3.0, value);
1191 /// let value = Math::round(3.5);
1192 /// assert_eq!(4.0, value);
1193 /// let value = Math::round(-4.5);
1194 /// assert_eq!(-5.0, value);
1195 /// let value = Math::round(-5.45);
1196 /// assert_eq!(-5.0, value);
1197 /// ```
1198 pub fn round(value: f32) -> f32 {
1199 #[cfg(not(feature = "no_std"))] { value.round() }
1200 #[cfg(feature = "no_std")] {
1201 let mut fraction = Math::fract(value);
1202 let truncated = Math::trunc(value);
1203
1204 if value < 0.0 && fraction > 0.0 { fraction = 1.0 - fraction; }
1205
1206 if fraction >= 0.5 {
1207 return truncated + Math::sign(value);
1208 }
1209
1210 return truncated;
1211 }
1212 }
1213
1214 /// Rounds the value up to the given amount of digits past the decimal
1215 /// - **value**: The value to round with
1216 /// - **digits**: The digit past the decimal to round to, must be between -15 and 15
1217 ///
1218 /// #### Examples
1219 /// ```
1220 /// # use mathx::Math;
1221 /// let value = Math::round_to_digit(1.0, 0);
1222 /// assert_eq!(1.0, value);
1223 /// let value = Math::round_to_digit(-1.0, 0);
1224 /// assert_eq!(-1.0, value);
1225 /// let value = Math::round_to_digit(1.525, 0);
1226 /// assert_eq!(2.0, value);
1227 /// let value = Math::round_to_digit(1.525, 1);
1228 /// assert_eq!(1.5, value);
1229 /// let value = Math::round_to_digit(1.525, 2);
1230 /// assert_eq!(1.53, value);
1231 /// let value = Math::round_to_digit(-1.525, 0);
1232 /// assert_eq!(-2.0, value);
1233 /// let value = Math::round_to_digit(-1.525, 2);
1234 /// assert_eq!(-1.53, value);
1235 /// let value = Math::round_to_digit(-2.4, 0);
1236 /// assert_eq!(-2.0, value);
1237 /// let value = Math::round_to_digit(-2.6, 0);
1238 /// assert_eq!(-3.0, value);
1239 /// ```
1240 pub fn round_to_digit(value: f32, digits: i32) -> f32 {
1241 let digits = digits.clamp(-15, 15);
1242 let pow10 = Math::pow_i32(10.0, digits);
1243 let powered = value * pow10;
1244 let mut fraction = Math::fract(powered);
1245 let truncated = Math::trunc(powered);
1246
1247 if fraction == 0.0 { return value; }
1248 if value < 0.0 { fraction = 1.0 - fraction; }
1249
1250 if fraction >= 0.5 {
1251 return (truncated + Math::sign(value)) / pow10;
1252 }
1253
1254 return truncated / pow10;
1255 }
1256
1257 /// Computes the secant of the given angle in radians
1258 /// - **angle**: The given angle to compute the secant with in radians
1259 ///
1260 /// **Returns**: Returns the computed secant value
1261 /// #### Examples
1262 /// ```
1263 /// # use mathx::{Math,assert_range};
1264 /// let value = Math::sec(0.0);
1265 /// assert_range!(1.0, value);
1266 /// let value = Math::sec(Math::PI);
1267 /// assert_range!(-1.0, value);
1268 /// let value = Math::sec(Math::TWO_PI);
1269 /// assert_range!(1.0, value);
1270 /// let value = Math::sec(Math::PI_OVER_4);
1271 /// assert_range!(1.414213562, value);
1272 /// let value = Math::sec(1.0);
1273 /// assert_range!(1.850815718, value);
1274 /// let value = Math::sec(-100.0);
1275 /// assert_range!(1.159663823, value);
1276 /// ```
1277 pub fn sec(angle: f32) -> f32 { Math::cos(angle).recip() }
1278
1279 /// Computes the secant of the given angle in degrees
1280 /// - **angle**: The given angle to compute the secant with in degrees
1281 ///
1282 /// **Returns**: Returns the computed secant value
1283 /// #### Examples
1284 /// ```
1285 /// # use mathx::{Math,assert_range};
1286 /// let value = Math::sec_deg(0.0);
1287 /// assert_range!(1.0, value);
1288 /// let value = Math::sec_deg(180.0);
1289 /// assert_range!(-1.0, value);
1290 /// let value = Math::sec_deg(360.0);
1291 /// assert_range!(1.0, value);
1292 /// let value = Math::sec_deg(45.0);
1293 /// assert_range!(1.414213562, value);
1294 /// let value = Math::sec_deg(57.29577951);
1295 /// assert_range!(1.850815718, value);
1296 /// let value = Math::sec_deg(-5729.577951);
1297 /// assert_range!(1.159663823, value);
1298 /// ```
1299 pub fn sec_deg(angle: f32) -> f32 { Math::sec(Math::DEG_TO_RAD * angle) }
1300
1301 /// Gets the sign (positive or negative) of the given value
1302 /// - **value**: The value to check the sign with
1303 ///
1304 /// **Returns**: Returns 1.0 if the value is positive, and -1.0 if the value is negative
1305 /// #### Examples
1306 /// ```
1307 /// # use mathx::Math;
1308 /// let value = Math::sign(10.0);
1309 /// assert_eq!(1.0, value);
1310 /// let value = Math::sign(-10.0);
1311 /// assert_eq!(-1.0, value);
1312 /// let value = Math::sign(-0.0);
1313 /// assert_eq!(-1.0, value);
1314 /// ```
1315 pub fn sign(value: f32) -> f32 {
1316 #[cfg(not(feature = "no_std"))] { value.signum() }
1317 #[cfg(feature = "no_std")] {
1318 if value.is_nan() { return value; }
1319 if value <= -0.0 { -1.0 } else { 1.0 }
1320 }
1321 }
1322
1323 /// Computes the sine of the given angle in radians
1324 /// - **angle**: The angle to compute sine with in radians
1325 ///
1326 /// **Returns**: Returns a value from the computed sine
1327 /// #### Remarks
1328 /// If you need to compute both `cos` and `sin` of the same angle, use `sin_cos` instead as it's more
1329 /// performant to produce both values than calling `cos` and `sin` separately
1330 /// ##### Examples
1331 /// ```
1332 /// # use mathx::{Math,assert_range};
1333 /// let value = Math::sin(0.0);
1334 /// assert_range!(0.0, value);
1335 /// let value = Math::sin(Math::PI_OVER_2);
1336 /// assert_range!(1.0, value);
1337 /// let value = Math::sin(Math::PI);
1338 /// assert_range!(0.0, value);
1339 /// let value = Math::sin(Math::PI + Math::PI_OVER_2);
1340 /// assert_range!(-1.0, value);
1341 /// let value = Math::sin(Math::TWO_PI);
1342 /// assert_range!(0.0, value);
1343 /// let value = Math::sin(Math::PI_OVER_4);
1344 /// assert_range!(0.707106781, value);
1345 /// let value = Math::sin(1.0);
1346 /// assert_range!(0.841470985, value);
1347 /// let value = Math::sin(-100.0);
1348 /// assert_range!(0.506365641, value);
1349 /// ```
1350 pub fn sin(angle: f32) -> f32 { Math::sin_cos(angle).0 }
1351
1352 /// Computes the sine of the given angle in degrees
1353 /// - **angle**: The angle to compute sine with in degrees
1354 ///
1355 /// **Returns**: Returns a value from the computed sine
1356 /// #### Remarks
1357 /// If you need to compute both `cos_deg` and `sin_deg` of the same angle, use `sin_cos_deg` instead as it's more
1358 /// performant to produce both values than calling `cos_deg` and `sin_deg` separately
1359 /// ##### Examples
1360 /// ```
1361 /// # use mathx::{Math,assert_range};
1362 /// let value = Math::sin_deg(0.0);
1363 /// assert_range!(0.0, value);
1364 /// let value = Math::sin_deg(90.0);
1365 /// assert_range!(1.0, value);
1366 /// let value = Math::sin_deg(180.0);
1367 /// assert_range!(0.0, value);
1368 /// let value = Math::sin_deg(270.0);
1369 /// assert_range!(-1.0, value);
1370 /// let value = Math::sin_deg(360.0);
1371 /// assert_range!(0.0, value);
1372 /// let value = Math::sin_deg(45.0);
1373 /// assert_range!(0.707106781, value);
1374 /// let value = Math::sin_deg(57.29577951);
1375 /// assert_range!(0.841470985, value);
1376 /// let value = Math::sin_deg(-5729.577951);
1377 /// assert_range!(0.506365641, value);
1378 /// ```
1379 pub fn sin_deg(angle: f32) -> f32 { Math::sin(Math::DEG_TO_RAD * angle) }
1380
1381 /// Computes the sine and cosine of the angle in radians
1382 /// - **angle**: The angle to compute the sine and cosine with in radians
1383 ///
1384 /// **Returns**: Returns the sine and cosine (respectively) as a tuple
1385 /// #### Remarks
1386 /// If you need to compute both `cos` and `sin` of the same angle, this function is more
1387 /// performant to produce both values than calling `cos` and `sin` separately
1388 /// #### Examples
1389 /// ```
1390 /// # use mathx::{Math,assert_range_tuple2};
1391 /// let value = Math::sin_cos(0.0);
1392 /// assert_range_tuple2!((0.0, 1.0), value);
1393 /// let value = Math::sin_cos(Math::PI_OVER_2);
1394 /// assert_range_tuple2!((1.0, 0.0), value);
1395 /// let value = Math::sin_cos(Math::PI);
1396 /// assert_range_tuple2!((0.0, -1.0), value);
1397 /// let value = Math::sin_cos(Math::PI + Math::PI_OVER_2);
1398 /// assert_range_tuple2!((-1.0, 0.0), value);
1399 /// let value = Math::sin_cos(Math::TWO_PI);
1400 /// assert_range_tuple2!((0.0, 1.0), value);
1401 /// let value = Math::sin_cos(Math::PI_OVER_4);
1402 /// assert_range_tuple2!((0.707106781, 0.707106781), value);
1403 /// let value = Math::sin_cos(1.0);
1404 /// assert_range_tuple2!((0.841470985, 0.540302306), value);
1405 /// let value = Math::sin_cos(-100.0);
1406 /// assert_range_tuple2!((0.506365641, 0.862318872), value);
1407 /// ```
1408 pub fn sin_cos(angle: f32) -> (f32, f32) {
1409 #[cfg(not(feature = "no_std"))] { angle.sin_cos() }
1410 #[cfg(feature = "no_std")] {
1411 const ITERATIONS: i32 = 28;
1412
1413 if angle < -Math::PI_OVER_2 || angle > Math::PI_OVER_2 {
1414 return if angle < 0.0 { Math::negate_tuple(Math::sin_cos(angle + Math::PI)) }
1415 else { Math::negate_tuple(Math::sin_cos(angle - Math::PI)) };
1416 }
1417
1418 let mut cos = 0.60725293500888;
1419 let mut sin = 0.0_f32;
1420 let mut z = angle;
1421
1422 for i in 0..ITERATIONS {
1423 let di = if z <= 0.0 { -1.0 } else { 1.0 };
1424 let new_cos = cos - (sin * di * Math::pow_i32(2.0, -i));
1425 let new_sin = sin + (cos * di * Math::pow_i32(2.0, -i));
1426
1427 cos = new_cos;
1428 sin = new_sin;
1429 z -= di * Math::get_atan_for_cordic(i);
1430 }
1431
1432 return (sin, cos);
1433 }
1434 }
1435
1436 /// Computes the sine and cosine of the angle in degrees
1437 /// - **angle**: The angle to compute the sine and cosine with in degrees
1438 ///
1439 /// **Returns**: Returns the sine and cosine (respectively) as a tuple
1440 /// #### Remarks
1441 /// If you need to compute both `cos_deg` and `sin_deg` of the same angle, this function is more
1442 /// performant to produce both values than calling `cos_deg` and `sin_deg` separately
1443 /// #### Examples
1444 /// ```
1445 /// # use mathx::{Math,assert_range_tuple2};
1446 /// let value = Math::sin_cos_deg(0.0);
1447 /// assert_range_tuple2!((0.0, 1.0), value);
1448 /// let value = Math::sin_cos_deg(90.0);
1449 /// assert_range_tuple2!((1.0, 0.0), value);
1450 /// let value = Math::sin_cos_deg(180.0);
1451 /// assert_range_tuple2!((0.0, -1.0), value);
1452 /// let value = Math::sin_cos_deg(270.0);
1453 /// assert_range_tuple2!((-1.0, 0.0), value);
1454 /// let value = Math::sin_cos_deg(360.0);
1455 /// assert_range_tuple2!((0.0, 1.0), value);
1456 /// let value = Math::sin_cos_deg(45.0);
1457 /// assert_range_tuple2!((0.707106781, 0.707106781), value);
1458 /// let value = Math::sin_cos_deg(57.29577951);
1459 /// assert_range_tuple2!((0.841470985, 0.540302306), value);
1460 /// let value = Math::sin_cos_deg(-5729.577951);
1461 /// assert_range_tuple2!((0.506365641, 0.862318872), value);
1462 /// ```
1463 pub fn sin_cos_deg(angle: f32) -> (f32, f32) { Math::sin_cos(Math::DEG_TO_RAD * angle) }
1464
1465 /// Computes the hyperbolic sine function
1466 /// - **value**: The value to compute the hyperbolic sine function with
1467 ///
1468 /// **Returns**: Returns the computed hyperbolic sine function
1469 /// #### Examples
1470 /// ```
1471 /// # use mathx::{Math,assert_range};
1472 /// let value = Math::sinh(0.0);
1473 /// assert_range!(0.0, value);
1474 /// let value = Math::sinh(1.0);
1475 /// assert_range!(1.1752012, value);
1476 /// let value = Math::sinh(-1.0);
1477 /// assert_range!(-1.1752012, value);
1478 /// let value = Math::sinh(Math::PI);
1479 /// assert_range!(11.54874, value);
1480 /// let value = Math::sinh(Math::E);
1481 /// assert_range!(7.5441365, value);
1482 /// ```
1483 pub fn sinh(value: f32) -> f32 {
1484 #[cfg(not(feature = "no_std"))] { value.sinh() }
1485 #[cfg(feature = "no_std")] {
1486 let exp = Math::exp(value);
1487
1488 if exp.is_infinite() || exp.is_nan() {
1489 if value > 0.0 { return f32::INFINITY; }
1490 else { return f32::NEG_INFINITY; }
1491 }
1492
1493 (exp - exp.recip()) * 0.5
1494 }
1495 }
1496
1497 /// Computes a smooth Hermite interpolation that returns a number between 0.0 and 1.0
1498 /// - **value**: The value for the interpolation, where `left_edge` < `value` < `right_edge`
1499 /// - **left_edge**: The leftmost edge to where 0.0 would start at
1500 /// - **right_edge**: The rightmost edge where 1.0 would start at
1501 ///
1502 /// **Returns**: Returns a smooth Hermite interpolation that returns a number between 0.0 and 1.0
1503 /// #### Examples
1504 /// ```
1505 /// # use mathx::Math;
1506 /// let value = Math::smoothstep(-1.0, 0.0, 1.5);
1507 /// assert_eq!(0.0, value);
1508 /// let value = Math::smoothstep(1.0, 0.0, 1.5);
1509 /// assert_eq!(0.7407408, value);
1510 /// let value = Math::smoothstep(2.0, 0.0, 1.5);
1511 /// assert_eq!(1.0, value);
1512 /// let value = Math::smoothstep(0.5, -1.0, 3.0);
1513 /// assert_eq!(0.31640625, value);
1514 /// ```
1515 pub fn smoothstep(value: f32, left_edge: f32, right_edge: f32) -> f32 {
1516 let y = Math::clamp((value - left_edge) / (right_edge - left_edge), 0.0, 1.0);
1517
1518 return y * y * (3.0 - 2.0 * y);
1519 }
1520
1521 /// Gets the square root of the given number
1522 /// - **value**: The number to square root
1523 ///
1524 /// **Returns**: Returns the square root of the number, returns NaN if `value` is negative
1525 /// #### Examples
1526 /// ```
1527 /// # use mathx::{Math,assert_range};
1528 /// let value = Math::sqrt(16.0);
1529 /// assert_range!(4.0, value);
1530 /// let value = Math::sqrt(1023.835);
1531 /// assert_range!(31.9974217711, value);
1532 /// let value = Math::sqrt(-102.0);
1533 /// assert_eq!(true, f32::is_nan(value));
1534 /// let value = Math::sqrt(-0.0);
1535 /// assert_range!(0.0, value);
1536 /// let value = Math::sqrt(0.2146018);
1537 /// assert_range!(0.46325132, value);
1538 /// ```
1539 pub fn sqrt(value: f32) -> f32 {
1540 #[cfg(not(feature = "no_std"))] { value.sqrt() }
1541 #[cfg(feature = "no_std")] {
1542 if value < -0.0 { return f32::NAN; }
1543 if value == 0.0 { return 0.0; }
1544 if value == 1.0 { return 1.0; }
1545
1546 let mut max = 50;
1547 let mut x = value;
1548
1549 while max > 0 && Math::abs(x) > 0.000000001 {
1550 x = (x * x * x + 3.0 * value * x) / (3.0 * x * x + value);
1551 max -= 1;
1552 }
1553
1554 return x;
1555 }
1556 }
1557
1558 /// Gets the tangent of the angle in radians
1559 /// - **angle**: The angle to compute the tangent with in radians
1560 ///
1561 /// **Returns**: Returns the value from the computed tangent
1562 /// #### Examples
1563 /// ```
1564 /// # use mathx::{Math,assert_range};
1565 /// let value = Math::tan(0.0);
1566 /// assert_range!(0.0, value);
1567 /// let value = Math::tan(Math::PI);
1568 /// assert_range!(0.0, value);
1569 /// let value = Math::tan(Math::TWO_PI);
1570 /// assert_range!(0.0, value);
1571 /// let value = Math::tan(Math::PI_OVER_4);
1572 /// assert_range!(1.0, value);
1573 /// let value = Math::tan(1.0);
1574 /// assert_range!(1.557407725, value);
1575 /// let value = Math::tan(-100.0);
1576 /// assert_range!(0.587213915, value);
1577 /// ```
1578 pub fn tan(angle: f32) -> f32 {
1579 #[cfg(not(feature = "no_std"))] { angle.tan() }
1580 #[cfg(feature = "no_std")] {
1581 let (sin, cos) = Math::sin_cos(angle);
1582
1583 sin / cos
1584 }
1585 }
1586
1587 /// Gets the tangent of the angle in degrees
1588 /// - **angle**: The angle to compute the tangent with in degrees
1589 ///
1590 /// **Returns**: Returns the value from the computed tangent
1591 /// #### Examples
1592 /// ```
1593 /// # use mathx::{Math,assert_range};
1594 /// let value = Math::tan_deg(0.0);
1595 /// assert_range!(0.0, value);
1596 /// let value = Math::tan_deg(180.0);
1597 /// assert_range!(0.0, value);
1598 /// let value = Math::tan_deg(360.0);
1599 /// assert_range!(0.0, value);
1600 /// let value = Math::tan_deg(45.0);
1601 /// assert_range!(1.0, value);
1602 /// let value = Math::tan_deg(57.29577951);
1603 /// assert_range!(1.557407725, value);
1604 /// let value = Math::tan_deg(-5729.577951);
1605 /// assert_range!(0.587213915, value);
1606 /// ```
1607 pub fn tan_deg(angle: f32) -> f32 { Math::tan(Math::DEG_TO_RAD * angle) }
1608
1609
1610 /// Computes the hyperbolic tangent function
1611 /// - **value**: The value to compute the hyperbolic tangent function with
1612 ///
1613 /// **Returns**: Returns the computed hyperbolic tangent function
1614 /// #### Examples
1615 /// ```
1616 /// # use mathx::{Math,assert_range};
1617 /// let value = Math::tanh(0.0);
1618 /// assert_range!(0.0, value);
1619 /// let value = Math::tanh(1.0);
1620 /// assert_range!(0.7615942, value);
1621 /// let value = Math::tanh(-1.0);
1622 /// assert_range!(-0.7615942, value);
1623 /// let value = Math::tanh(Math::PI);
1624 /// assert_range!(0.9962721, value);
1625 /// let value = Math::tanh(Math::E);
1626 /// assert_range!(0.9913289, value);
1627 /// ```
1628 pub fn tanh(value: f32) -> f32 {
1629 #[cfg(not(feature = "no_std"))] { value.tanh() }
1630 #[cfg(feature = "no_std")] {
1631 let exp = Math::exp(2.0 * value);
1632
1633 if exp.is_infinite() || exp.is_nan() {
1634 if value > 0.0 { return 1.0; }
1635 else { return -1.0; }
1636 }
1637
1638 (exp - 1.0) * (exp + 1.0).recip()
1639 }
1640 }
1641
1642 /// Truncates the value of the floating point number
1643 /// - **value**: The number to truncate
1644 ///
1645 /// **Returns**: Returns the truncated number
1646 /// #### Examples
1647 /// ```
1648 /// # use mathx::Math;
1649 /// let value = Math::trunc(123.456);
1650 /// assert_eq!(123.0, value);
1651 /// let value = Math::trunc(-5.4);
1652 /// assert_eq!(-5.0, value);
1653 /// let value = Math::trunc(6.0);
1654 /// assert_eq!(6.0, value);
1655 /// let value = Math::trunc(-0.0);
1656 /// assert_eq!(0.0, value);
1657 /// ```
1658 pub fn trunc(value: f32) -> f32 {
1659 #[cfg(not(feature = "no_std"))] { value.trunc() }
1660 #[cfg(feature = "no_std")] {
1661 (value as i32) as f32
1662 }
1663 }
1664}
1665
1666// Private Functions
1667impl Math {
1668 /// Gets the pre-calculated arc tangent values for use in the cordic algorithm
1669 /// - **index**: The index to get the pre-calculated value from
1670 ///
1671 /// **Returns**: Returns the pre-calculated value for the arc tangent
1672 #[cfg(feature = "no_std")]
1673 pub(self) fn get_atan_for_cordic(index: i32) -> f32 {
1674 match index {
1675 0 => 0.7853982,
1676 1 => 0.4636476,
1677 2 => 0.24497867,
1678 3 => 0.124354996,
1679 4 => 0.06241881,
1680 5 => 0.031239834,
1681 6 => 0.015623729,
1682 7 => 0.007812341,
1683 8 => 0.0039062302,
1684 9 => 0.0019531226,
1685 10 => 0.0009765622,
1686 11 => 0.00048828122,
1687 12 => 0.00024414063,
1688 13 => 0.00012207031,
1689 14 => 0.000061035156,
1690 15 => 0.000030517578,
1691 16 => 0.00001525878906,
1692 17 => 0.00000762939453,
1693 18 => 0.00000381469727,
1694 19 => 0.00000190734863,
1695 20 => 0.00000095367432,
1696 21 => 0.00000047683716,
1697 22 => 0.00000023841858,
1698 23 => 0.00000011920929,
1699 24 => 0.00000005960464,
1700 25 => 0.00000002980232,
1701 26 => 0.00000001490116,
1702 27 => 0.00000000745058,
1703 _ => 0.0,
1704 }
1705 }
1706
1707 /// Negates the tuple, multiplying both components by -1
1708 /// - **tuple**: The tuple to negate
1709 ///
1710 /// **Returns**: Returns the negated tuple
1711 #[cfg(feature = "no_std")]
1712 pub(self) fn negate_tuple(tuple: (f32, f32)) -> (f32, f32) { (-tuple.0, -tuple.1) }
1713}
1714
1715#[doc(hidden)]
1716#[macro_export]
1717macro_rules! assert_range {
1718 ($expected:expr, $value:expr) => {
1719 assert_range!($expected, $value, 0.0001);
1720 };
1721 ($expected:expr, $value:expr, $epsilon:expr) => {
1722 if !Math::approx_epsilon($expected, $value, $epsilon) { panic!("\n\nleft: {:?}\nright: {:?}\n\n", $expected, $value); }
1723 };
1724}
1725
1726#[doc(hidden)]
1727#[macro_export]
1728macro_rules! assert_range_tuple2 {
1729 ($expected:expr, $value:expr, $epsilon:expr) => {
1730 if !Math::approx_epsilon($expected.0, $value.0, $epsilon) || !Math::approx_epsilon($expected.1, $value.1, $epsilon) { panic!("\n\nleft: {:?}\nright: {:?}\n\n", $expected, $value); }
1731 };
1732 ($expected:expr, $value:expr) => {
1733 assert_range_tuple2!($expected, $value, 0.0001);
1734 };
1735}