1use crate::consts;
19use crate::traits::{Fixed, FixedSigned, LossyFrom, ToFixed};
20use crate::types::{I9F23, I9F55, U0F128};
21use core::ops::{AddAssign, BitOrAssign, ShlAssign};
22
23type ConstType = I9F23;
24
25pub const ZERO: I9F23 = I9F23::from_bits(0i32 << 23);
27pub const ONE: I9F23 = I9F23::from_bits(1i32 << 23);
29pub const TWO: I9F23 = I9F23::from_bits(2i32 << 23);
31pub const THREE: I9F23 = I9F23::from_bits(3i32 << 23);
33pub const TWO_PI: I9F23 = I9F23::from_bits((consts::PI.to_bits() >> 102) as i32);
35pub const PI: I9F23 = I9F23::from_bits((consts::PI.to_bits() >> 103) as i32);
37pub const FRAC_PI_2: I9F23 = I9F23::from_bits((consts::PI.to_bits() >> 104) as i32);
39pub const FRAC_PI_4: I9F23 = I9F23::from_bits((consts::PI.to_bits() >> 105) as i32);
41pub const LOG2_E: I9F23 = I9F23::from_bits((consts::LOG2_E.to_bits() >> 104) as i32);
43pub const E: I9F23 = I9F23::from_bits((consts::E.to_bits() >> 103) as i32);
45
46const ARCTAN_ANGLES: [U0F128; 64] = [
54 U0F128::from_bits(0xC90FDAA22168C0000000000000000000),
55 U0F128::from_bits(0x76B19C1586ED3C000000000000000000),
56 U0F128::from_bits(0x3EB6EBF25901BA000000000000000000),
57 U0F128::from_bits(0x1FD5BA9AAC2F6E000000000000000000),
58 U0F128::from_bits(0x0FFAADDB967EF5000000000000000000),
59 U0F128::from_bits(0x07FF556EEA5D89400000000000000000),
60 U0F128::from_bits(0x03FFEAAB776E53600000000000000000),
61 U0F128::from_bits(0x01FFFD555BBBA9700000000000000000),
62 U0F128::from_bits(0x00FFFFAAAADDDDB80000000000000000),
63 U0F128::from_bits(0x007FFFF55556EEF00000000000000000),
64 U0F128::from_bits(0x003FFFFEAAAAB7780000000000000000),
65 U0F128::from_bits(0x001FFFFFD55555BC0000000000000000),
66 U0F128::from_bits(0x000FFFFFFAAAAAAE0000000000000000),
67 U0F128::from_bits(0x0007FFFFFF5555558000000000000000),
68 U0F128::from_bits(0x0003FFFFFFEAAAAAA000000000000000),
69 U0F128::from_bits(0x0001FFFFFFFD55555000000000000000),
70 U0F128::from_bits(0x0000FFFFFFFFAAAAA800000000000000),
71 U0F128::from_bits(0x00007FFFFFFFF5555400000000000000),
72 U0F128::from_bits(0x00003FFFFFFFFEAAAA00000000000000),
73 U0F128::from_bits(0x00001FFFFFFFFFD55500000000000000),
74 U0F128::from_bits(0x00000FFFFFFFFFFAAA80000000000000),
75 U0F128::from_bits(0x000007FFFFFFFFFF5540000000000000),
76 U0F128::from_bits(0x000003FFFFFFFFFFEAA0000000000000),
77 U0F128::from_bits(0x000001FFFFFFFFFFFD50000000000000),
78 U0F128::from_bits(0x000000FFFFFFFFFFFFA8000000000000),
79 U0F128::from_bits(0x0000007FFFFFFFFFFFF4000000000000),
80 U0F128::from_bits(0x0000003FFFFFFFFFFFFE000000000000),
81 U0F128::from_bits(0x00000020000000000000000000000000),
82 U0F128::from_bits(0x00000010000000000000000000000000),
83 U0F128::from_bits(0x00000008000000000000000000000000),
84 U0F128::from_bits(0x00000004000000000000000000000000),
85 U0F128::from_bits(0x00000002000000000000000000000000),
86 U0F128::from_bits(0x00000001000000000000000000000000),
87 U0F128::from_bits(0x00000000800000000000000000000000),
88 U0F128::from_bits(0x00000000400000000000000000000000),
89 U0F128::from_bits(0x00000000200000000000000000000000),
90 U0F128::from_bits(0x00000000100000000000000000000000),
91 U0F128::from_bits(0x00000000080000000000000000000000),
92 U0F128::from_bits(0x00000000040000000000000000000000),
93 U0F128::from_bits(0x00000000020000000000000000000000),
94 U0F128::from_bits(0x00000000010000000000000000000000),
95 U0F128::from_bits(0x00000000008000000000000000000000),
96 U0F128::from_bits(0x00000000004000000000000000000000),
97 U0F128::from_bits(0x00000000002000000000000000000000),
98 U0F128::from_bits(0x00000000001000000000000000000000),
99 U0F128::from_bits(0x00000000000800000000000000000000),
100 U0F128::from_bits(0x00000000000400000000000000000000),
101 U0F128::from_bits(0x00000000000200000000000000000000),
102 U0F128::from_bits(0x00000000000100000000000000000000),
103 U0F128::from_bits(0x00000000000080000000000000000000),
104 U0F128::from_bits(0x00000000000040000000000000000000),
105 U0F128::from_bits(0x00000000000020000000000000000000),
106 U0F128::from_bits(0x00000000000010000000000000000000),
107 U0F128::from_bits(0x00000000000008000000000000000000),
108 U0F128::from_bits(0x00000000000004000000000000000000),
109 U0F128::from_bits(0x00000000000002000000000000000000),
110 U0F128::from_bits(0x00000000000001000000000000000000),
111 U0F128::from_bits(0x00000000000000800000000000000000),
112 U0F128::from_bits(0x00000000000000400000000000000000),
113 U0F128::from_bits(0x00000000000000200000000000000000),
114 U0F128::from_bits(0x00000000000000100000000000000000),
115 U0F128::from_bits(0x00000000000000080000000000000000),
116 U0F128::from_bits(0x00000000000000040000000000000000),
117 U0F128::from_bits(0x00000000000000020000000000000000),
118];
119
120fn rs<T>(operand: T) -> T
122where
123 T: Fixed,
124{
125 let lsb = T::from_num(1) >> T::frac_nbits();
126 (operand >> 1) + (operand & lsb)
127 }
130
131pub fn sqrt<S, D>(operand: S) -> Result<D, &'static str>
133where
134 S: Fixed + PartialOrd<ConstType>,
135 D: Fixed + PartialOrd<ConstType> + From<S>,
136{
137 let mut invert = false;
138 if operand < ZERO {
139 return Err("Can't calculate sqrt from negative numbers.");
140 };
141
142 let mut operand = D::from(operand);
143 if operand == ZERO || operand == ONE {
144 return Ok(operand);
145 };
146 if operand < ONE {
147 invert = true;
148 operand = if let Some(r) = D::from_num(1).checked_div(operand) {
149 r
150 } else {
151 return Err("Overflow inverting operand.");
152 };
153 }
154 let mut l = (operand / D::from_num(2)) + D::from_num(1);
156 for _i in 0..D::frac_nbits() {
157 l = (l + operand / l) / D::from_num(2);
158 }
159 if invert {
160 l = if let Some(r) = D::from_num(1).checked_div(l) {
161 r
162 } else {
163 return Err("Overflow un-inverting operand.");
164 };
165 }
166 Ok(l)
167}
168
169fn log2_inner<S, D>(operand: S) -> D
171where
172 S: FixedSigned + PartialOrd<ConstType>,
173 D: FixedSigned,
174 D::Bits: Copy + ToFixed + AddAssign + BitOrAssign + ShlAssign,
175{
176 let mut x = operand;
177 let mut result = D::from_num(0).to_bits();
178 let lsb = (D::from_num(1) >> D::frac_nbits()).to_bits();
179
180 while x >= TWO {
181 result += lsb;
182 x = rs(x);
183 }
184
185 if x == ONE {
186 return D::from_num(result);
187 };
188
189 for _i in (0..D::frac_nbits()).rev() {
190 x *= x;
191 result <<= lsb;
192 if x >= TWO {
193 result |= lsb;
194 x = rs(x);
195 }
196 }
197 D::from_bits(result)
198}
199
200pub fn log2<S, D>(operand: S) -> Result<D, ()>
202where
203 S: FixedSigned + PartialOrd<ConstType>,
204 D: FixedSigned + PartialOrd<ConstType> + From<S>,
205 D::Bits: Copy + ToFixed + AddAssign + BitOrAssign + ShlAssign,
206{
207 if operand <= S::from_num(0) {
208 return Err(());
209 };
210
211 let operand = D::from(operand);
212 if operand < D::from_num(1) {
213 let inverse = D::from_num(1).checked_div(operand).ok_or(())?;
214 return Ok(-log2_inner::<D, D>(inverse));
215 };
216 return Ok(log2_inner::<D, D>(operand));
217}
218
219pub fn ln<S, D>(operand: S) -> Result<D, ()>
221where
222 S: FixedSigned + PartialOrd<ConstType>,
223 D: FixedSigned + PartialOrd<ConstType> + From<S> + From<ConstType>,
224 D::Bits: Copy + ToFixed + AddAssign + BitOrAssign + ShlAssign,
225{
226 Ok(log2::<S, D>(operand)? / D::from(LOG2_E))
227}
228
229pub fn exp<S, D>(mut operand: S) -> Result<D, ()>
231where
232 S: FixedSigned + PartialOrd<ConstType>,
233 D: FixedSigned + PartialOrd<ConstType> + From<S> + From<ConstType>,
234{
235 if operand == ZERO {
236 return Ok(D::from_num(1));
237 };
238 if operand == ONE {
239 return Ok(D::from(E));
240 };
241 let neg = operand < ZERO;
242 if neg {
243 operand = operand.checked_neg().ok_or(())?;
244 };
245
246 let operand = D::from(operand);
247 let mut result = operand.checked_add(D::from_num(1)).ok_or(())?;
248 let mut term = operand;
249
250 for i in 2..D::frac_nbits() {
251 term = if let Some(r) = term.checked_mul(operand) {
252 r
253 } else {
254 return Err(());
255 };
256 term = if let Some(r) = term.checked_div(D::from_num(i)) {
259 r
260 } else {
261 return Err(());
262 };
263
264 result = if let Some(r) = result.checked_add(term) {
265 r
266 } else {
267 return Err(());
268 };
269 }
273 if neg {
274 result = if let Some(r) = D::from_num(1).checked_div(result) {
275 r
276 } else {
277 return Err(());
278 };
279 }
280 Ok(result)
281}
282
283pub fn pow<S, D>(operand: S, exponent: S) -> Result<D, ()>
285where
286 S: FixedSigned + PartialOrd<ConstType>,
287 D: FixedSigned + PartialOrd<ConstType> + From<S> + From<ConstType>,
288 D::Bits: Copy + ToFixed + AddAssign + BitOrAssign + ShlAssign,
289{
290 if operand == S::from_num(0) {
293 return Ok(D::from_num(0));
294 };
295 if exponent == S::from_num(0) {
296 return Ok(D::from_num(1));
297 };
298 if exponent == S::from_num(1) {
299 return Ok(D::from(operand));
300 };
301
302 let r = if let Some(r) = ln::<S, D>(operand)?.checked_mul(exponent.into()) {
303 r
304 } else {
305 return Err(());
306 };
307 let result: D = if let Ok(r) = exp(r) {
308 r
309 } else {
310 return Err(());
311 };
312 let (result, oflw) = result.overflowing_to_num::<D>();
313 if oflw {
314 return Err(());
315 };
316 Ok(result)
317}
318
319pub fn powi<S, D>(operand: S, exponent: i32) -> Result<D, ()>
321where
322 S: Fixed + PartialOrd<ConstType>,
323 D: Fixed + PartialOrd<ConstType> + From<S> + From<ConstType>,
324 D::Bits: Copy + ToFixed + AddAssign + BitOrAssign + ShlAssign,
325{
326 if operand == S::from_num(0) {
327 return Ok(D::from_num(0));
328 };
329 if exponent == 0 {
330 return Ok(D::from_num(1));
331 };
332 if exponent == 1 {
333 return Ok(D::from(operand));
334 };
335 let operand = D::from(operand);
336 let mut r = operand;
337
338 for _i in 1..exponent.abs() {
339 r = if let Some(r) = r.checked_mul(operand) {
340 r
341 } else {
342 return Err(());
343 };
344 }
345 if exponent < 0 {
346 r = if let Some(r) = D::from_num(1).checked_div(r) {
347 r
348 } else {
349 return Err(());
350 };
351 }
352 Ok(r)
353}
354
355fn cordic_rotation<T>(mut x: T, mut y: T, mut z: T) -> (T, T)
357where
358 T: FixedSigned + PartialOrd<ConstType> + LossyFrom<U0F128>,
359{
360 for (angle, i) in ARCTAN_ANGLES.iter().cloned().zip(0..) {
361 let angle = T::lossy_from(angle);
362 if i >= 24 {
366 break;
367 }
368 let prev_x = x;
369 if z < ZERO {
370 x += y >> i;
371 y -= prev_x >> i;
372 z += angle;
373 } else {
374 x -= y >> i;
375 y += prev_x >> i;
376 z -= angle;
377 }
378 }
379 (x, y)
380}
381
382pub fn sin<T>(mut angle: T) -> T
384where
385 T: FixedSigned
386 + PartialOrd<ConstType>
387 + LossyFrom<ConstType>
388 + LossyFrom<I9F23>
389 + LossyFrom<U0F128>,
390{
391 while angle > PI {
393 angle -= T::lossy_from(TWO_PI);
394 }
395 while angle < -PI {
396 angle += T::lossy_from(TWO_PI);
397 }
398 if angle > FRAC_PI_2 {
400 angle = T::lossy_from(FRAC_PI_2) - (angle - T::lossy_from(FRAC_PI_2));
401 }
402 if angle < -FRAC_PI_2 {
403 angle = -T::lossy_from(FRAC_PI_2) - (angle + T::lossy_from(FRAC_PI_2));
404 }
405
406 let x = T::lossy_from(U0F128::from_bits(0x9B74EDA8A01E20000000000000000000));
411 let (_x, y) = cordic_rotation(x, T::from_num(0), angle);
413 y
414}
415
416pub fn cos<T>(angle: T) -> T
418where
419 T: FixedSigned
420 + PartialOrd<ConstType>
421 + LossyFrom<ConstType>
422 + LossyFrom<I9F55>
423 + LossyFrom<U0F128>,
424{
425 sin(angle + T::lossy_from(FRAC_PI_2))
426}
427
428pub fn tan<T>(mut angle: T) -> T
430where
431 T: FixedSigned
432 + PartialOrd<ConstType>
433 + LossyFrom<ConstType>
434 + LossyFrom<I9F55>
435 + LossyFrom<U0F128>,
436{
437 angle *= T::from_num(2);
438 sin(angle) / (T::from_num(1) + cos(angle))
439}
440
441pub fn asin<T>(angle: T) -> T {
444 angle
445}
446
447#[cfg(test)]
448mod tests {
449 use super::*;
450 use crate::traits::LossyInto;
451 use crate::types::{I32F32, I64F64, U64F64};
452
453 #[test]
454 fn sqrt_works() {
455 {
456 type S = I9F23;
457 type D = I9F23;
458
459 assert_eq!(sqrt::<S, D>(S::from_num(4)).unwrap(), TWO);
460
461 let result: f64 = sqrt::<S, D>(S::from_num(1)).unwrap().lossy_into();
462 assert_relative_eq!(result, 1.0, epsilon = 1.0e-6);
463 let result: f64 = sqrt::<S, D>(S::from_num(0)).unwrap().lossy_into();
464 assert_relative_eq!(result, 0.0, epsilon = 1.0e-6);
465 let result: f64 = sqrt::<S, D>(S::from_num(0.1_f32)).unwrap().lossy_into();
466 assert_relative_eq!(result, 0.316228, epsilon = 1.0e-4);
467 let result: f64 = sqrt::<S, D>(S::from_num(10)).unwrap().lossy_into();
468 assert_relative_eq!(result, 3.16228, epsilon = 1.0e-4);
469 }
470 {
471 type S = U64F64;
472 type D = U64F64;
473 let result: f64 = sqrt::<S, D>(S::from_num(1)).unwrap().lossy_into();
474 assert_relative_eq!(result, 1.0, epsilon = 1.0e-6);
475 }
476 }
477
478 #[test]
479 fn sqrt_check_lower_bound_of_working_values() {
480 type S = I32F32;
482 type D = I32F32;
483
484 let result: f64 = sqrt::<S, D>(S::from_num(5.8208e-10)).unwrap().lossy_into();
486 assert_relative_eq!(result, 0.0000261, epsilon = 1.0e-6);
487
488 let res = sqrt::<S, D>(S::from_num(5.8205e-10));
490 assert_eq!(res.unwrap_err(), "Overflow inverting operand.")
491 }
492
493 #[test]
494 fn rs_works() {
495 let result: f64 = rs(I9F23::from_num(0)).lossy_into();
496 assert_eq!(result, 0.0);
497 let result: f64 = rs(I9F23::from_num(1)).lossy_into();
498 assert_eq!(result, 0.5);
499 let result: f64 = rs(I9F23::from_num(2)).lossy_into();
500 assert_eq!(result, 1.0);
501 let result: f64 = rs(I9F23::from_num(3)).lossy_into();
502 assert_eq!(result, 1.5);
503 let result: f64 = rs(I9F23::from_num(4)).lossy_into();
504 assert_eq!(result, 2.0);
505 let result: f64 = rs(I9F23::from_num(-1)).lossy_into();
506 assert_eq!(result, -0.5);
507 let result: f64 = rs(I9F23::from_num(-2)).lossy_into();
508 assert_eq!(result, -1.0);
509
510 assert_eq!(rs(I9F23::from_bits(1)).to_bits(), 1);
511 assert_eq!(rs(I9F23::from_bits(2)).to_bits(), 1);
512 assert_eq!(rs(I9F23::from_bits(3)).to_bits(), 2);
513 assert_eq!(rs(I9F23::from_bits(4)).to_bits(), 2);
514 }
515
516 #[test]
517 fn log2_works() {
518 type S = I9F23;
519 type D = I32F32;
520 assert!(log2::<S, D>(S::from_num(0)).is_err());
521
522 assert_eq!(log2::<S, D>(S::from_num(1)).unwrap(), ZERO);
523
524 let result: D = log2::<S, D>(S::from_num(2)).unwrap();
525 let result: f64 = result.lossy_into();
526 assert_relative_eq!(result, 1.0, epsilon = 1.0e-6);
527 let result: D = log2::<S, D>(S::from_num(4)).unwrap();
528 let result: f64 = result.lossy_into();
529 assert_relative_eq!(result, 2.0, epsilon = 1.0e-6);
530 let result: D = log2::<S, D>(S::from_num(3.33333_f64)).unwrap();
531 let result: f64 = result.lossy_into();
532 assert_relative_eq!(result, 1.73696, epsilon = 1.0e-5);
533 let result: D = log2::<S, D>(S::from_num(0.11111_f64)).unwrap();
534 let result: f64 = result.lossy_into();
535 assert_relative_eq!(result, -3.16994, epsilon = 1.0e-2);
536 }
537
538 #[test]
539 fn ln_works() {
540 type S = I9F23;
541 type D = I32F32;
542 assert!(ln::<S, D>(S::from_num(0)).is_err());
543 assert_eq!(ln::<S, D>(S::from_num(1)).unwrap(), ZERO);
544 let result: f64 = ln::<S, D>(E).unwrap().lossy_into();
545 assert_relative_eq!(result, 1.0, epsilon = 1.0e-4);
546 let result: f64 = ln::<S, D>(S::from_num(10)).unwrap().lossy_into();
547 assert_relative_eq!(result, 2.30259, epsilon = 1.0e-4);
548 let result: f64 = ln::<S, D>(S::from_num(0.00001)).unwrap().lossy_into();
549 assert_relative_eq!(result, -11.5129, epsilon = 1.0e-1);
550 }
551
552 #[test]
553 fn exp_works() {
554 type S = I9F23;
555 type D = I32F32;
556
557 let result: f64 = exp::<S, D>(ZERO).unwrap().lossy_into();
558 assert_eq!(result, 1.0);
559
560 let result: f64 = exp::<S, D>(ONE).unwrap().lossy_into();
561 assert_relative_eq!(result, 2.718281828459045235_f64, epsilon = 1.0e-4);
562
563 let result: f64 = exp::<S, D>(S::from_num(5.0)).unwrap().lossy_into();
564 assert_relative_eq!(result, 148.413159, epsilon = 1.0e-1);
565 assert!(exp::<S, D>(S::from_num(-23)).is_err());
567 let result: f64 = exp::<S, I64F64>(S::from_num(-23)).unwrap().lossy_into();
569 assert_relative_eq!(result, 102.619e-12, epsilon = 1.0e-12);
570 }
571
572 #[test]
573 fn pow_works() {
574 type S = I9F23;
575 type D = I32F32;
576
577 let result: D = pow(ZERO, TWO).unwrap();
578 let result: f64 = result.lossy_into();
579 assert_eq!(result, 0.0);
580
581 let result: D = pow(ONE, TWO).unwrap();
582 let result: f64 = result.lossy_into();
583 assert_eq!(result, 1.0);
584
585 let result: D = pow(TWO, TWO).unwrap();
586 let result: f64 = result.lossy_into();
587 assert_relative_eq!(result, 4.0, epsilon = 1.0e-3);
588 let result: D = pow(TWO, THREE).unwrap();
589 let result: f64 = result.lossy_into();
590 assert_relative_eq!(result, 8.0, epsilon = 1.0e-3);
591 let result: D = pow(S::from_num(2.9), S::from_num(3.1)).unwrap();
592 let result: f64 = result.lossy_into();
593 assert_relative_eq!(result, 27.129, epsilon = 1.0e-2);
594 let result: D = pow(S::from_num(0.0001), S::from_num(2)).unwrap();
595 let result: f64 = result.lossy_into();
596 assert_relative_eq!(result, 0.00000001, epsilon = 1.0e-9);
597
598 assert!(pow::<S, D>(S::from_num(-0.0001), S::from_num(2)).is_err());
600 }
601
602 #[test]
603 fn powi_works() {
604 type D = I32F32;
605
606 let result: D = powi(ZERO, 2).unwrap();
607 let result: f64 = result.lossy_into();
608 assert_eq!(result, 0.0);
609
610 let result: D = powi(ONE, 2).unwrap();
611 let result: f64 = result.lossy_into();
612 assert_eq!(result, 1.0);
613
614 let result: D = powi(TWO, 2).unwrap();
615 let result: f64 = result.lossy_into();
616 assert_relative_eq!(result, 4.0, epsilon = 1.0e-3);
617
618 let result: D = powi(TWO, -2).unwrap();
619 let result: f64 = result.lossy_into();
620 assert_relative_eq!(result, 1.0 / 4.0, epsilon = 1.0e-4);
621
622 let result: D = powi(TWO, 3).unwrap();
623 let result: f64 = result.lossy_into();
624 assert_relative_eq!(result, 8.0, epsilon = 1.0e-3);
625 }
626
627 #[test]
628 fn sin_works() {
629 let result: f64 = sin(I32F32::lossy_from(FRAC_PI_2)).lossy_into();
631 assert_relative_eq!(result, 1.0, epsilon = 1.0e-5);
632
633 let result: f64 = sin(FRAC_PI_2).lossy_into();
634 assert_relative_eq!(result, 1.0, epsilon = 1.0e-5);
635
636 let result: f64 = sin(I32F32::from_num(0)).lossy_into();
637 assert_relative_eq!(result, 0.0, epsilon = 1.0e-5);
638 let result: f64 = sin(I9F23::from_num(0)).lossy_into();
639 assert_relative_eq!(result, 0.0, epsilon = 1.0e-5);
640 let result: f64 = sin(PI).lossy_into();
641 assert_relative_eq!(result, 0.0, epsilon = 1.0e-5);
642 let result: f64 = sin(PI + FRAC_PI_2).lossy_into();
643 assert_relative_eq!(result, -1.0, epsilon = 1.0e-5);
644 let result: f64 = sin(TWO_PI).lossy_into();
645 assert_relative_eq!(result, 0.0, epsilon = 1.0e-5);
646 let result: f64 = sin(FRAC_PI_4).lossy_into();
647 assert_relative_eq!(result, 0.707107, epsilon = 1.0e-1);
648 let result: f64 = sin(-FRAC_PI_2).lossy_into();
649 assert_relative_eq!(result, -1.0, epsilon = 1.0e-1);
650 let result: f64 = sin(-FRAC_PI_4).lossy_into();
651 assert_relative_eq!(result, -0.707107, epsilon = 1.0e-1);
652 let result: f64 = sin(PI + FRAC_PI_4).lossy_into();
653 assert_relative_eq!(result, -0.707107, epsilon = 1.0e-1);
654 let result: f64 = sin(TWO).lossy_into();
655 assert_relative_eq!(result, 0.909297, epsilon = 1.0e-5);
656 let result: f64 = sin(-TWO).lossy_into();
657 assert_relative_eq!(result, -0.909297, epsilon = 1.0e-5);
658 }
659
660 #[test]
661 fn cos_works() {
662 let result: f64 = cos(I9F23::from_num(0)).lossy_into();
663 assert_relative_eq!(result, 1.0, epsilon = 1.0e-5);
664 }
665
666 #[test]
667 fn tan_works() {
668 let result: f64 = tan(I9F23::from_num(0)).lossy_into();
669 assert_relative_eq!(result, 0.0, epsilon = 1.0e-5);
670
671 let result: f64 = tan(ONE).lossy_into();
672 assert_relative_eq!(result, 1.55741, epsilon = 1.0e-5);
673 }
674
675 #[test]
676 fn asin_works() {
677 let result: f64 = asin(I9F23::from_num(0)).lossy_into();
678 assert_relative_eq!(result, 0.0, epsilon = 1.0e-5);
679 let result: f64 = asin(I9F23::from_num(0.01)).lossy_into();
680 assert_relative_eq!(result, 0.01, epsilon = 1.0e-5);
681 }
682}