const_num_traits/ops/
mul_add.rs1c0nst::c0nst! {
2pub c0nst trait MulAdd<A = Self, B = Self> {
25 type Output;
27
28 fn mul_add(self, a: A, b: B) -> Self::Output;
30}
31}
32
33c0nst::c0nst! {
34pub c0nst trait MulAddAssign<A = Self, B = Self> {
36 fn mul_add_assign(&mut self, a: A, b: B);
38}
39}
40
41#[cfg(any(feature = "std", feature = "libm"))]
43impl MulAdd<f32, f32> for f32 {
44 type Output = Self;
45
46 #[inline]
47 fn mul_add(self, a: Self, b: Self) -> Self::Output {
48 <Self as crate::Float>::mul_add(self, a, b)
49 }
50}
51
52#[cfg(any(feature = "std", feature = "libm"))]
53impl MulAdd<f64, f64> for f64 {
54 type Output = Self;
55
56 #[inline]
57 fn mul_add(self, a: Self, b: Self) -> Self::Output {
58 <Self as crate::Float>::mul_add(self, a, b)
59 }
60}
61
62macro_rules! mul_add_impl {
63 ($trait_name:ident for $($t:ty)*) => {$(
64 c0nst::c0nst! {
65 c0nst impl $trait_name for $t {
66 type Output = Self;
67
68 #[inline]
69 fn mul_add(self, a: Self, b: Self) -> Self::Output {
70 (self * a) + b
71 }
72 }
73 }
74 )*}
75}
76
77mul_add_impl!(MulAdd for isize i8 i16 i32 i64 i128);
78mul_add_impl!(MulAdd for usize u8 u16 u32 u64 u128);
79
80#[cfg(any(feature = "std", feature = "libm"))]
81impl MulAddAssign<f32, f32> for f32 {
82 #[inline]
83 fn mul_add_assign(&mut self, a: Self, b: Self) {
84 *self = <Self as crate::Float>::mul_add(*self, a, b)
85 }
86}
87
88#[cfg(any(feature = "std", feature = "libm"))]
89impl MulAddAssign<f64, f64> for f64 {
90 #[inline]
91 fn mul_add_assign(&mut self, a: Self, b: Self) {
92 *self = <Self as crate::Float>::mul_add(*self, a, b)
93 }
94}
95
96macro_rules! mul_add_assign_impl {
97 ($trait_name:ident for $($t:ty)*) => {$(
98 c0nst::c0nst! {
99 c0nst impl $trait_name for $t {
100 #[inline]
101 fn mul_add_assign(&mut self, a: Self, b: Self) {
102 *self = (*self * a) + b
103 }
104 }
105 }
106 )*}
107}
108
109mul_add_assign_impl!(MulAddAssign for isize i8 i16 i32 i64 i128);
110mul_add_assign_impl!(MulAddAssign for usize u8 u16 u32 u64 u128);
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn mul_add_integer() {
118 macro_rules! test_mul_add {
119 ($($t:ident)+) => {
120 $(
121 {
122 let m: $t = 2;
123 let x: $t = 3;
124 let b: $t = 4;
125
126 assert_eq!(MulAdd::mul_add(m, x, b), (m*x + b));
127 }
128 )+
129 };
130 }
131
132 test_mul_add!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
133 }
134
135 #[test]
136 #[cfg(feature = "std")]
137 fn mul_add_float() {
138 macro_rules! test_mul_add {
139 ($($t:ident)+) => {
140 $(
141 {
142 use core::$t;
143
144 let m: $t = 12.0;
145 let x: $t = 3.4;
146 let b: $t = 5.6;
147
148 let abs_difference = (MulAdd::mul_add(m, x, b) - (m*x + b)).abs();
149
150 assert!(abs_difference <= 46.4 * $t::EPSILON);
151 }
152 )+
153 };
154 }
155
156 test_mul_add!(f32 f64);
157 }
158}