Skip to content

Commit 9ce33e6

Browse files
authored
poly: refactor and test AddAssign Dense-Dense (#895)
1 parent b1c8962 commit 9ce33e6

File tree

1 file changed

+124
-14
lines changed

1 file changed

+124
-14
lines changed

poly/src/polynomial/univariate/dense.rs

+124-14
Original file line numberDiff line numberDiff line change
@@ -358,26 +358,25 @@ impl<'a, F: Field> Add<&'a SparsePolynomial<F>> for &DensePolynomial<F> {
358358

359359
impl<'a, F: Field> AddAssign<&'a DensePolynomial<F>> for DensePolynomial<F> {
360360
fn add_assign(&mut self, other: &'a DensePolynomial<F>) {
361+
if other.is_zero() {
362+
self.truncate_leading_zeros();
363+
return;
364+
}
365+
361366
if self.is_zero() {
362-
self.coeffs.truncate(0);
367+
self.coeffs.clear();
363368
self.coeffs.extend_from_slice(&other.coeffs);
364-
} else if other.is_zero() {
365-
} else if self.degree() >= other.degree() {
366-
self.coeffs
367-
.iter_mut()
368-
.zip(&other.coeffs)
369-
.for_each(|(a, b)| {
370-
*a += b;
371-
});
372369
} else {
373-
// Add the necessary number of zero coefficients.
374-
self.coeffs.resize(other.coeffs.len(), F::zero());
370+
let other_coeffs_len = other.coeffs.len();
371+
if other_coeffs_len > self.coeffs.len() {
372+
// Add the necessary number of zero coefficients.
373+
self.coeffs.resize(other_coeffs_len, F::zero());
374+
}
375+
375376
self.coeffs
376377
.iter_mut()
377378
.zip(&other.coeffs)
378-
.for_each(|(a, b)| {
379-
*a += b;
380-
});
379+
.for_each(|(a, b)| *a += b);
381380
}
382381
self.truncate_leading_zeros();
383382
}
@@ -1315,4 +1314,115 @@ mod tests {
13151314
assert!(result.is_zero(), "The resulting polynomial should be zero.");
13161315
assert_eq!(result.coeffs, vec![], "Leading zeros were not truncated.");
13171316
}
1317+
1318+
#[test]
1319+
fn test_dense_dense_add_assign_with_zero_self() {
1320+
// Create a zero polynomial
1321+
let mut poly1 = DensePolynomial { coeffs: Vec::new() };
1322+
1323+
// Create a non-zero polynomial: 2 + 3x
1324+
let poly2 = DensePolynomial {
1325+
coeffs: vec![Fr::from(2), Fr::from(3)],
1326+
};
1327+
1328+
// Add the non-zero polynomial to the zero polynomial
1329+
poly1 += &poly2;
1330+
1331+
// Check that poly1 now equals poly2
1332+
assert_eq!(poly1.coeffs, poly2.coeffs);
1333+
}
1334+
1335+
#[test]
1336+
fn test_dense_dense_add_assign_with_zero_other() {
1337+
// Create a non-zero polynomial: 2 + 3x
1338+
let mut poly1 = DensePolynomial {
1339+
coeffs: vec![Fr::from(2), Fr::from(3)],
1340+
};
1341+
1342+
// Create a zero polynomial
1343+
let poly2 = DensePolynomial { coeffs: Vec::new() };
1344+
1345+
// Add the zero polynomial to poly1
1346+
poly1 += &poly2;
1347+
1348+
// Check that poly1 remains unchanged
1349+
assert_eq!(poly1.coeffs, vec![Fr::from(2), Fr::from(3)]);
1350+
}
1351+
1352+
#[test]
1353+
fn test_dense_dense_add_assign_with_different_degrees() {
1354+
// Create a polynomial: 1 + 2x + 3x^2
1355+
let mut poly1 = DensePolynomial {
1356+
coeffs: vec![Fr::from(1), Fr::from(2), Fr::from(3)],
1357+
};
1358+
1359+
// Create a smaller polynomial: 4 + 5x
1360+
let poly2 = DensePolynomial {
1361+
coeffs: vec![Fr::from(4), Fr::from(5)],
1362+
};
1363+
1364+
// Add the smaller polynomial to the larger one
1365+
poly1 += &poly2;
1366+
1367+
assert_eq!(poly1.coeffs, vec![Fr::from(5), Fr::from(7), Fr::from(3)]);
1368+
}
1369+
1370+
#[test]
1371+
fn test_dense_dense_truncate_leading_zeros_after_addition() {
1372+
// Create a first polynomial
1373+
let mut poly1 = DensePolynomial {
1374+
coeffs: vec![Fr::from(1), Fr::from(2)],
1375+
};
1376+
1377+
// Create another polynomial that will cancel out the first two terms
1378+
let poly2 = DensePolynomial {
1379+
coeffs: vec![-poly1.coeffs[0], -poly1.coeffs[1]],
1380+
};
1381+
1382+
// Add the two polynomials
1383+
poly1 += &poly2;
1384+
1385+
// Check that the resulting polynomial is zero (empty coefficients)
1386+
assert!(poly1.is_zero());
1387+
assert_eq!(poly1.coeffs, vec![]);
1388+
}
1389+
1390+
#[test]
1391+
fn test_dense_dense_add_assign_with_equal_degrees() {
1392+
// Create two polynomials with the same degree
1393+
let mut poly1 = DensePolynomial {
1394+
coeffs: vec![Fr::from(1), Fr::from(2), Fr::from(3)],
1395+
};
1396+
let poly2 = DensePolynomial {
1397+
coeffs: vec![Fr::from(4), Fr::from(5), Fr::from(6)],
1398+
};
1399+
1400+
// Add the polynomials
1401+
poly1 += &poly2;
1402+
1403+
// Check the resulting coefficients
1404+
assert_eq!(poly1.coeffs, vec![Fr::from(5), Fr::from(7), Fr::from(9)]);
1405+
}
1406+
1407+
#[test]
1408+
fn test_dense_dense_add_assign_with_other_zero_truncates_leading_zeros() {
1409+
use ark_test_curves::bls12_381::Fr;
1410+
1411+
// Create a polynomial with leading zeros: 1 + 2x + 0x^2 + 0x^3
1412+
let mut poly1 = DensePolynomial {
1413+
coeffs: vec![Fr::from(1), Fr::from(2), Fr::from(0), Fr::from(0)],
1414+
};
1415+
1416+
// Create a zero polynomial
1417+
let poly2 = DensePolynomial { coeffs: Vec::new() };
1418+
1419+
// Add the zero polynomial to poly1
1420+
poly1 += &poly2;
1421+
1422+
// Check that the leading zeros are truncated
1423+
assert_eq!(poly1.coeffs, vec![Fr::from(1), Fr::from(2)]);
1424+
1425+
// Ensure the polynomial is not zero (as it has non-zero coefficients)
1426+
assert!(!poly1.is_zero());
1427+
}
13181428
}

0 commit comments

Comments
 (0)