qfall_math/rational/poly_over_q/arithmetic/
add.rs1use super::super::PolyOverQ;
12use crate::{
13 integer::PolyOverZ,
14 macros::arithmetics::{
15 arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
16 arithmetic_trait_mixed_borrowed_owned, arithmetic_trait_reverse,
17 },
18};
19use flint_sys::fmpq_poly::fmpq_poly_add;
20use std::ops::{Add, AddAssign};
21
22impl AddAssign<&PolyOverQ> for PolyOverQ {
23 fn add_assign(&mut self, other: &Self) {
48 unsafe { fmpq_poly_add(&mut self.poly, &self.poly, &other.poly) };
49 }
50}
51impl AddAssign<&PolyOverZ> for PolyOverQ {
52 fn add_assign(&mut self, other: &PolyOverZ) {
54 let other = PolyOverQ::from(other);
55
56 self.add_assign(other);
57 }
58}
59
60arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, PolyOverQ, PolyOverQ);
61arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, PolyOverQ, PolyOverZ);
62
63impl Add for &PolyOverQ {
64 type Output = PolyOverQ;
65 fn add(self, other: Self) -> Self::Output {
87 let mut out = PolyOverQ::default();
88 unsafe {
89 fmpq_poly_add(&mut out.poly, &self.poly, &other.poly);
90 }
91 out
92 }
93}
94
95arithmetic_trait_borrowed_to_owned!(Add, add, PolyOverQ, PolyOverQ, PolyOverQ);
96arithmetic_trait_mixed_borrowed_owned!(Add, add, PolyOverQ, PolyOverQ, PolyOverQ);
97
98impl Add<&PolyOverZ> for &PolyOverQ {
99 type Output = PolyOverQ;
100 fn add(self, other: &PolyOverZ) -> Self::Output {
120 let mut out = PolyOverQ::default();
121 unsafe {
122 fmpq_poly_add(&mut out.poly, &self.poly, &PolyOverQ::from(other).poly);
123 }
124 out
125 }
126}
127
128arithmetic_trait_reverse!(Add, add, PolyOverZ, PolyOverQ, PolyOverQ);
129
130arithmetic_trait_borrowed_to_owned!(Add, add, PolyOverQ, PolyOverZ, PolyOverQ);
131arithmetic_trait_borrowed_to_owned!(Add, add, PolyOverZ, PolyOverQ, PolyOverQ);
132arithmetic_trait_mixed_borrowed_owned!(Add, add, PolyOverQ, PolyOverZ, PolyOverQ);
133arithmetic_trait_mixed_borrowed_owned!(Add, add, PolyOverZ, PolyOverQ, PolyOverQ);
134
135#[cfg(test)]
136mod test_add_assign {
137 use super::PolyOverQ;
138 use crate::{integer::PolyOverZ, rational::Q};
139 use std::str::FromStr;
140
141 #[test]
143 fn correct_small() {
144 let mut a = PolyOverQ::from_str("3 1/7 2/7 -3").unwrap();
145 let b = PolyOverQ::from_str("3 1 -2/7 3").unwrap();
146 let cmp = PolyOverQ::from_str("1 8/7").unwrap();
147
148 a += &b;
149
150 assert_eq!(cmp, a);
151 }
152
153 #[test]
155 fn correct_large() {
156 let mut a: PolyOverQ = PolyOverQ::from_str(&format!(
157 "3 {} {}/{} {}",
158 u64::MAX,
159 i64::MIN,
160 u128::MAX,
161 i64::MAX
162 ))
163 .unwrap();
164 let b = PolyOverQ::from_str(&format!("2 {} {}", u64::MAX, i64::MAX)).unwrap();
165 let cmp = PolyOverQ::from_str(&format!(
166 "3 {} {} {}",
167 u128::from(u64::MAX) * 2,
168 (Q::from_str(&format!("{}/{}", i64::MIN, u128::MAX)).unwrap() + Q::from(i64::MAX)),
169 i64::MAX
170 ))
171 .unwrap();
172
173 a += b;
174
175 assert_eq!(cmp, a);
176 }
177
178 #[test]
180 fn availability() {
181 let mut a = PolyOverQ::from_str("3 1 2 -3").unwrap();
182 let b = PolyOverQ::from_str("3 -1 -2 3").unwrap();
183 let c = PolyOverZ::from_str("4 2 -1 2 3").unwrap();
184
185 a += &b;
186 a += b;
187 a += &c;
188 a += c;
189 }
190}
191
192#[cfg(test)]
193mod test_add {
194 use super::PolyOverQ;
195 use crate::rational::Q;
196 use std::str::FromStr;
197
198 #[test]
200 fn add() {
201 let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2 -3").unwrap();
202 let b: PolyOverQ = PolyOverQ::from_str("5 1/9 2/9 5/2 1 2/7").unwrap();
203 let c: PolyOverQ = a + b;
204 assert_eq!(c, PolyOverQ::from_str("5 16/63 20/9 -1/2 1 2/7").unwrap());
205 }
206
207 #[test]
209 fn add_borrow() {
210 let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2 -3").unwrap();
211 let b: PolyOverQ = PolyOverQ::from_str("5 1/9 2/9 5/2 1 2/7").unwrap();
212 let c: PolyOverQ = a + b;
213 assert_eq!(c, PolyOverQ::from_str("5 16/63 20/9 -1/2 1 2/7").unwrap());
214 }
215
216 #[test]
218 fn add_first_borrowed() {
219 let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2 -3").unwrap();
220 let b: PolyOverQ = PolyOverQ::from_str("5 1/9 2/9 5/2 1 2/7").unwrap();
221 let c: PolyOverQ = &a + &b;
222 assert_eq!(c, PolyOverQ::from_str("5 16/63 20/9 -1/2 1 2/7").unwrap());
223 }
224
225 #[test]
227 fn add_second_borrowed() {
228 let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2 -3").unwrap();
229 let b: PolyOverQ = PolyOverQ::from_str("5 1/9 2/9 5/2 1 2/7").unwrap();
230 let c: PolyOverQ = &a + b;
231 assert_eq!(c, PolyOverQ::from_str("5 16/63 20/9 -1/2 1 2/7").unwrap());
232 }
233
234 #[test]
236 fn add_eliminating_coefficients() {
237 let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2/7 -3").unwrap();
238 let b: PolyOverQ = PolyOverQ::from_str("3 1 -2/7 3").unwrap();
239 let c: PolyOverQ = a + &b;
240 assert_eq!(c, PolyOverQ::from_str("1 8/7").unwrap());
241 }
242
243 #[test]
245 fn add_large_numbers() {
246 let a: PolyOverQ = PolyOverQ::from_str(&format!(
247 "3 {} {}/{} {}",
248 u64::MAX,
249 i64::MIN,
250 u128::MAX,
251 i64::MAX
252 ))
253 .unwrap();
254 let b: PolyOverQ = PolyOverQ::from_str(&format!("2 {} {}", u64::MAX, i64::MAX)).unwrap();
255 let c: PolyOverQ = a + b;
256 assert_eq!(
257 c,
258 PolyOverQ::from_str(&format!(
259 "3 {} {} {}",
260 u128::from(u64::MAX) * 2,
261 (Q::from_str(&format!("{}/{}", i64::MIN, u128::MAX)).unwrap() + Q::from(i64::MAX)),
262 i64::MAX
263 ))
264 .unwrap()
265 );
266 }
267}
268
269#[cfg(test)]
270mod test_mul_poly_over_z {
271 use super::PolyOverQ;
272 use crate::integer::PolyOverZ;
273 use std::str::FromStr;
274
275 #[test]
277 fn borrowed_correctness() {
278 let poly_1 = PolyOverQ::from_str(&format!("1 1/{}", i64::MAX)).unwrap();
279 let poly_2 = PolyOverZ::from_str("2 1 2").unwrap();
280 let poly_cmp =
281 PolyOverQ::from_str(&format!("2 {}/{} 2", i64::MAX as u64 + 1, i64::MAX)).unwrap();
282
283 let poly_1 = &poly_1 + &poly_2;
284
285 assert_eq!(poly_cmp, poly_1);
286 }
287
288 #[test]
290 fn availability() {
291 let poly = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
292 let z = PolyOverZ::from(2);
293
294 _ = poly.clone() + z.clone();
295 _ = z.clone() + poly.clone();
296 _ = &poly + &z;
297 _ = &z + &poly;
298 _ = &poly + z.clone();
299 _ = z.clone() + &poly;
300 _ = &z + poly.clone();
301 _ = poly.clone() + &z;
302 }
303}